标签 插件 下的文章

目前为止,在一系列介绍 vim 插件文章中,我们介绍了使用 Pathogen 插件管理包安装基本的 vim 插件,也提及了另外三个插件:Tagbar、delimitMateSyntastic。现在,在最后一部分,我们将介绍另一个十分有用的插件 a.vim。

请注意所有本篇教程所提及的例子、命令和指导,它们已经在 Ubuntu 16.04 测试完毕,vim 使用版本为 vim7.4 (LCTT 译注:Ubuntu 16.04 的默认版本)。

A.vim

如果你一直用像 C、C++ 这样的语言进行开发工作,你一定有这样的感触:我特么已经数不清我在头文件和源代码之间切换过多少次了。我想说的是,确实,这个操作十分基本,十分频繁。

尽管使用基于 GUI(图形界面)的 IDE(集成开发环境)非常容易通过鼠标的双击切换文件,但是如果你是资深 vim 粉,习惯用命令工作就有点尴尬了。但是不要害怕,我有秘籍--插件 a.vim。它可以让你解决尴尬,专治各种文件切换。

在我们介绍这个神器用法之前,我必须强调一点:这个插件的安装过程和我们其他篇介绍的不太一样,步骤如下:

  • 首先,你需要下载两个文件(a.vimalternate.txt),你可以在这里找到它们。
  • 接下来,创建如下目录:~/.vim/bundle/avim~/.vim/bundle/avim/doc~/.vim/bundle/avim/plugin~/.vim/bundle/autoload
  • 创建好目录之后,将 a.vim 放到 ~/.vim/bundle/avim/plugin~/.vim/bundle/autoload,以及将 alternate.txt 放到 ~/.vim/bundle/avim/doc

就是这样,如果上述步骤被你成功完成,你的系统就会安装好这个插件。

使用这个插件十分简单,你仅仅需要运行这个命令 :A 如果目前的文件是源文件(比如 test.c),这个神器就会帮你打开 test.c 对应的头文件(test.h),反之亦然。

当然咯,不是每个文件对应的头文件都存在。这种情况下,如果那你运行 :A 命令,神器就会为你新建一个文件。比如,如果 test.h 不存在,那么运行此命令就会帮你创建一个 test.h,然后打开它。

如果你不想要神器开启此功能,你可以在你的家目录的隐藏文件 .vimrc 中写入 g:alternateNonDefaultAlternate 变量,并且赋给它一个非零值即可。

还有一种情况也很普遍,你需要打开的文件并非是当前源代码的头文件。比如你目前在 test.c 你想打开 men.h 这个头文件,那么你可以输入这个命令 :IH <filename> ,毋需赘言,你肯定要在后面输入你要打开的的文件名称 <filename>

目前为止,我们讨论的功能都仅限于你当前文件和要操作的文件都在同一个目录去实现。但是,你也知道,我们还有特殊情况,我是说,许多项目中头文件与对应的源文件并不一定在同一目录下。

为了搞定这个问题,你要使用这个 g:alternateSearchPath 这个变量。官方文档是这么解释的:

这个插件可以让用户配置它的搜索源文件和头文件的搜索路径。这个搜索路径可以通过设置 g:alternateSearchPath 这个变量的值指定。默认的设定如下:

g:alternateSearchPath = 'sfr:../source,sfr:../src,sfr:../include,sfr:../inc' 

使用这个代码表示神器将搜索 ../source../src../include../inc 下所有与目标文件相关的文件。 g:alternateSearchPath 变量的值由前缀和路径组成,每个单元用逗号隔开。 sfr 前缀是指后面的路径是相对于目前文件的,wdr 前缀是指目录是相对于目前的工作目录, abs 是指路径是绝对路径。如果不指定前缀,那么默认为 sfr

如果我们前文所提及的特性就能让你觉得很炫酷,那我不得不告诉你,这才哪跟哪。还有一个十分有用的功能是分割 Vim 屏幕,这样你就可以同时看到头文件和相应的源文件。

哦,还有,你还可以选择垂直或者水平分割。全凭你心意。使用 :AS 命令可以水平分割,使用 :AV 可以垂直分割。

Vim.a vertical split screen

vim.a horizontal split screen

使用 :A 命令在已经打开的文件中切换。

这个插件还可以让你在同一个 Vim 窗口中不同选项卡中打开多个相应的文件,你键入这个命令 :AT

tabs in Vim with a.vim.

当然,你可以用这些命令 :AV:AS:AT,也可以使用这些命令 :IHV:IHS:IHT

最后

还有许多和编程相关的 Vim 的插件,我们在这个三篇系列主要讨论的是,如果你为你的软件开发工作安装了合适的插件,你就会明白为什么 vim 被叫做编辑器之神。

当然,我们在这只关注编程方面,对于那些把 Vim 当做日常文档编辑器的人来说,你也应该了解一些 Vim 的插件,让你的编辑更好,更高效.我们就改日再谈这个问题吧。


via: https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers-3/

作者:Ansh 译者:Taylor1024 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

WordPress 是迄今为止最流行的博客平台。

正由于它的流行,也因此带来了正面和负面的影响。事实上,几乎每个人都使用它,使它更容易被发现漏洞。WordPress 的开发人员做了很多工作,一旦新的缺陷被发现,就会发布修复和补丁,但这并不意味着你可以安装完就置之脑后。

在这篇文章中,我们将提供一些最常见的保护和强化 WordPress 网站的方法。

在登录后台时总是使用 SSL

不用说的是,如果你并不打算只是做一个随意的博客,你应该总是使用 SSL。不使用加密连接登录到你的网站会暴露你的用户名和密码。任何人嗅探流量都可能会发现你的密码。如果你使用 WiFi 上网或者连接到一个公共热点,那么你被黑的几率更高,这是特别真实的。你可以从这里获取受信任的免费 SSL 证书。

精心挑选附加的插件

由第三方开发人员所开发,每个插件的质量和安全性总是值得怀疑,并且它仅取决于其开发人员的经验。当安装任何额外的插件时,你应该仔细选择,并考虑其受欢迎程度以及插件的维护频率。应该避免维护不良的插件,因为它们更容易出现易于被利用的错误和漏洞。

此主题也是上一个关于 SSL 主题的补充,因为许多插件包含的脚本会发出不安全连接(HTTP)的请求。只要你的网站通过 HTTP 访问,一切似乎很好。但是,一旦你决定使用加密并强制使用 SSL 访问,则会立即导致网站的功能被破坏,因为当你使用 HTTPS 访问其他网站时,这些插件上的脚本将继续通过 HTTP 提供请求。

安装 Wordfence

Wordfence 是由 Feedjit Inc. 开发的,Wordfence 是目前最流行的 WordPress 安全插件,并且是每个严肃的 WordPress 网站必备的,特别是那些使用 WooCommerce 或其它的 WordPress 电子商务平台的网站。

Wordfence 不只是一个插件,因为它提供了一系列加强您的网站的安全功能。它具有 web 程序防火墙、恶意软件扫描、实时流量分析器和各种其它工具,它们可以提高你网站的安全性。防火墙将默认阻止恶意登录尝试,甚至可以配置为按照 IP 地址范围来阻止整个国家/地区的访问。我们真正喜欢 Wordfence 的原因是,即使你的网站因为某些原因被侵害,例如恶意脚本,Wordfence 可以在安装以后扫描和清理你的网站上被感染的文件。

该公司提供这个插件的免费和付费订阅计划,但即使是免费计划,你的网站仍将获得令人满意的水平。

用额外的密码锁住 /wp-admin 和 /wp-login.php

保护你的 WordPress 后端的另一个步骤是使用额外的密码保护任何除了你以外不打算让任何人使用的目录(即URL)。 /wp-admin 目录属于此关键目录列表。 如果你不允许普通用户登录 WordPress,你应该使用密码限制对 wp.login.php 文件的访问。无论是使用 Apache 还是 Nginx,你都可以访问这两篇文章,了解如何额外保护 WordPress 安装。

禁用/停止用户枚举

这是攻击者发现你网站上的有效用户名的一种相当简单的方法(即找出管理员用户名)。那么它是如何工作的?这很简单。在任何 WordPress 站点上的主要 URL 后面跟上 /?author=1 即可。 例如:wordpressexample.com/?author=1

要保护您的网站免受此影响,只需安装停止用户枚举插件。

禁用 XML-RPC

RPC 代表远程过程调用,它可以用来从位于网络上另一台计算机上的程序请求服务的协议。对于 WordPress 来说,XML-RPC 允许你使用流行的网络博客客户端(如 Windows Live Writer)在你的 WordPress 博客上发布文章,如果你使用 WordPress 移动应用程序那么也需要它。 XML-RPC 在早期版本中被禁用,但是从 WordPress 3.5 时它被默认启用,这让你的网站面临更大的攻击可能。虽然各种安全研究人员建议这不是一个大问题,但如果你不打算使用网络博客客户端或 WP 的移动应用程序,你应该禁用 XML-RPC 服务。

有多种方法可以做到这一点,最简单的是安装禁用 XML-RPC插件。


via: https://www.rosehosting.com/blog/5-tips-for-securing-your-wordpress-sites/

作者:<rosehosting.com> 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

毫无疑问,Vim 是一个开箱即用并能够胜任编程任务的编辑器,但实际上是该编辑器中的插件帮你实现这些方便的功能。在 开发者的实用 Vim 插件(一),我们已经讨论两个编程相关的 Vim 插件——标签侧边栏(Tagbar)和定界符自动补齐(delimitMate)。作为相同系列,我们在本文讨论另一个非常有用、专门为软件开发正定制的插件——语法高亮插件。

请注意:本教程中列举的所有例示、命令和说明都是在 Ubuntu 16.04 环境下进行测试的,并且,我们使用的 Vim 版本是 7.4。

语法高亮(Syntastic)插件

假如你的软件开发工作涉及到 C/C++ 语言,毫无疑问的说,遇到编译错误也是你每天工作中的一部分。很多时候,编译错误是由源代码之中的语法不正确造成的,因为开发者在浏览源码的时候很少能够一眼就看出所有这些错误。

那么 Vim 中是否存在一种插件可以让你不经编译源码就可以显示出语法错误呢?当然是有这样一种插件的,其名字就是 Syntastic。

“Syntastic 是 Vim 用来检验语法的插件,通过外部语法校验器校验文件并将错误呈现给用户。该过程可以在需要时进行,或者在文件保存的时候自动进行。”该插件 官方文档 如是说。“如果检测到语法错误就会提示用户,因为不用编译代码或者执行脚本就可以知道语法错误,用户也就乐享与此了。”

安装过程和第一部分提到的方法类似,你只需要运行下列命令即可:

cd ~/.vim/bundle/

git clone https://github.com/scrooloose/syntastic.git

一旦你成功安装这个插件(即上述命令执行成功),你就不需要进行任何配置了——当 Vim 启动时会自动加载这个插件。

现在,打开一个源码文件并用 :w Vim 命令保存即可使用这个插件了。等待片刻之后,如果在源码中有语法错误的好,就会高亮显示出来。比如,看看一下截图你就会明白该插件是如何高亮显示语法错误的:

Vim Syntax error highlighting

在每行之前的 >> 表示该行中有语法错误。了解确切的错误或者想知道是什么东西错了,将光标移到该行——错误描述就会展示在 Vim 窗口的最底下。

View Syntax errors in Vim

这样,不用进行编译你就能够修复大多数语法相关的错误。

再往下,如果你运行 :Errors 命令,就会展现当前源文件中所有语法相关错误的描述。比如,我运行 :Errors 命令就是下图的效果:

Syntastic :Errors command

请记住,:Errors 展现的语法错误是不会自动更新的,这意味着在你修复错误之后,你需要重新运行 :Errors 命令,编辑器底部的错误描述才会消除。

值得一提的是,还有 许多配置选项 能够使得 Syntastic 插件使用起来更加友好。比如,你可以在你的 .vimrc 中添加下列内容,然后 :Errors 就可以在修复错误之后自动更新它的底部描述。

let g:syntastic_always_populate_loc_list = 1

添加以下内容,以确保在你打开文件时 Syntastic 插件自动高亮显示错误。

let g:syntastic_check_on_open = 1

类似的,你也可以在保存或打开文件时让光标跳转到检测到的第一个问题处,将下列行放到你的 .vimrc 文件之中:

let g:syntastic_auto_jump = 1

这个值也可以指定为其它两个值: 2 和 3,其官方文档的解释如下:

“如果设置为 2 的话,光标就会跳到检测到的第一个问题,当然,只有这个问题是一个错误的时候才跳转;设置为 3 的话,如果存在错误,则会跳到第一个错误。所有检测到的问题都会有警告,但光标不会跳转。”

以下信息可能对你有帮助:

“使用 :SyntasticCheck 来手动检测错误。使用 :Errors 打开错误位置列表并使用 :lclose 来关闭。使用 :SyntasticReset 可以清除掉错误列表,使用 :SyntasticToggleMode 来切换激活(在写到 buffer 时检测)和被动(即手动检测)检测错误。”

注意:Syntastic 并不局限于 C/C++ 所写的代码,它同时也支持很多的编程语言——点击 此处 了解更多相关信息。

结论

毫无疑问的,Syntastic 是一个非常有用的 Vim 插件,因为在出现语法相关错误时候,它至少能够让免去频繁编译的麻烦,而且不用说,同时也节约了你不少的时间。

正如你所看到的一样,配置好几个主要选项之后,Syntastic 变得非常好用了。为了帮助你了解这些设置,官方文档中包含了一份“推荐设置”——跟着文档进行设置即可。加入你遇到一些错误、有些疑问或者问题,你也可以查询一下 FAQ。


via: https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers-2-syntastic/

作者:Ansh 译者:GHLandy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

作为 Vi 的升级版,Vim 毫无争议是 Linux 中最受欢迎的命令行编辑器之一。除了是一个多功能编辑器外,世界各地的软件开发者将 Vim 当做 IDE( 集成开发环境 Integrated Development Environment )来使用。

事实上,因为 Vim 可以通过插件来扩展其自身功能才使得它如此功能强大。不用说,肯定有那么几个 Vim 插件是旨在提高用户的编程体验的。

特别是对于刚刚使用 Vim 或者使用 Vim 做开发的的软件开发者来说,我们将在本教程中讨论一些非常有用的 Vim 插件,具体请看例示。

请注意:本教程中列举的所有例示、命令和说明都是在 Ubuntu 16.04 环境下进行测试的,并且,我们使用的 Vim 版本是 7.4。

插件安装设置

这是为新用户准备的,假设他们不知道如何安装 Vim 插件。所以,首先,就是给出一些完成安装设置的步骤。

  • 在你的家目录下创建 .vim 目录,并在其中创建子目录 autoloadbundle
  • 然后,在 autoload 放置 pathogen.vim 文件,这个文件可以从此处 下载。
  • 最后,在你的家目录创建 .vimrc 文件,并添加以下内容。
call pathogen#infect() 

Vim plugin installation

至此,你已完成了 Vim 插件安装的准备工作。

注意:我们已经讨论了使用 Pathogen 管理 Vim 插件。当然还有其他的插件管理工具——欲了解,请访问此处

现在已经全部设置完毕,就让我们来讨论两个好用的 Vim 插件吧。

Vim 标签侧边栏(Tagbar)插件

首先就是标签侧边栏(Tagbar)插件。该插件能够让你浏览源文件包含的标签,从而提供该源文件的结构简览。其官网的插件说明是这样说的:“它通过创建侧边栏,然后以一定顺序展示从当前文件以 ctags 提取的标签来完成这一功能。这意味着,比如,C++ 中的方法将展示在其自身所定义在的类里边。”

听起来很酷,不是吗?让我们来看看该怎么安装它。

标签侧边栏(Tagbar)的安装过程是相当容易的——你只需要运行下列命令:

cd ~/.vim/bundle/

git clone git://github.com/majutsushi/tagbar

安装完之后就可以使用了,你可以在 Vim 中打开一个 .cpp 文件来测试它:进入命令模式,然后运行 :TagbarOpen 命令。以下是运行 :TagbarOpen 命令之后出现侧边栏(右侧) 的效果图。

Vim tagbar plugin

使用 :TagbarClose 可以关闭侧边栏。值得一提的是,可以使用 :TagbarOpen fj 命令打开侧边栏来打开它的跳转(shift control)功能。也就是说,你可以很方便的浏览当前文件包含的标签——在对应的标签上按下 Enter 键,然后在左侧的源代码窗口跳转到对应的位置。

假如你想要反复地开关侧边栏,你可以使用 :TagbarToggle 命令,而不用交替的使用 :TagbarOpen:TagbarClose 命令。

如果你觉得输入这些命令很费时间,你可以为 :TagbarToggle 命令创建快捷键。比如,添加以下内容到 .vimrc 文件中:

nmap <F8> :TagbarToggle<CR>

这样,你就可以用 F8 来切换标签侧边栏(Tagbar)了。

更进一步,有时候你可能会注意到某个标签前边有一个 +- 或者 # 符号。比如,以下截图(取自该插件的官网)展示了一些前边有 + 号的标签。

Toggle Tagbar window

这些符号基本是用来表明一个特定标签的可见性信息。特别是 + 表示该类是 public 的,而 - 表示一个 private 类。# 则是表示一个 protected 类。

以下是使用标签侧边栏(Tagbar)的一些注意事项:

  • 该插件的官网早就有说明:“标签侧边栏(Tagbar)并非是管理标签(tags)文件而设计,它只是在内存中动态创建所需的标签,而非创建任何文件。标签(tags)文件的管理有其他插件提供支持。”
  • 低于 7.0.167 版本的 Vim 和标签侧边栏(Tagbar)插件存在着一个兼容性问题。根据官网:“如果你受到此问题的影响,请使用代替版:下载 zip 压缩包。这对应到 2.2 版本,但由于大量的依赖变更,它可能不会再升级。”
  • 如果你在加载该插件时遇到这样的错误:未找到 ctags!(Tagbar: Exuberant ctags not found!)。你可以从 此处下载并安装 ctags 来修复错误。
  • 获取更多信息请访问 这里

Vim 界定符自动补齐(delimitMate)插件

下一个要介绍的插件就是界定符自动补齐(delimitMate)。该插件在 Vim 插入模式下提供引号、圆括号和方括号等界定符自动补齐功能。

该插件官网说:“它同时也提供一些相关的特性让你在输入模式下变得更加便捷,比如语法纠错(在注释区或者其他的可配置区不会自动插入结束界定符)、回车和空格填充(默认关闭)等。”

安装步骤与之前介绍的相似:

cd ~/.vim/bundle/

git clone git://github.com/Raimondi/delimitMate.git

一旦你成功安装这个插件(即上述命令执行成功),你就不需要进行任何配置了——当 Vim 启动时会自动加载这个插件。

至此,在你使用 Vim 的任何时候,只要你输入一个双引号、单引号、单号、圆括号、方括号,它们都会自动补齐。

你可以自己配置界定符自动补齐(delimitMate)。比如,你可以添加需要自动补齐的符号列表,阻止自动加载该插件,对指定类型文件关闭该插件等。想了解如何配置这些(或者其他更多的配置),请阅读该插件的详细文档——运行 :help delimitMate 即可。

上述命令会将你的 Vim 窗口水平分割成两个,上边一个包含我们所说的文档。

Vim deliMate Plugin

结论

本文之中提到的两个插件,Tagbar 需要花费较多时间来适应——你应该会同样这个说法。但只要正确设置好它(这意味着你像是有了快捷键一样方便),就容易使用了。至于 delimitMate,不需要任何要求就可以上手。

本教程就是向你展示 Vim 如何高效能的想法。除了本文中提及的,仍然还有许多开发者可用的插件,我们将在下一个部分进行讨论。假如你正在使用一个关于开发的 Vim 插件,并希望广为人知,请在下方留下评论。

我们将在本教程的第二部分讲到 语法高亮插件:Syntastic


via: https://www.howtoforge.com/tutorial/vim-editor-plugins-for-software-developers/

作者:Ansh 译者:GHLandy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

序言

这篇教程将会教你怎么制作你的第一个 Atom 文本编辑器的插件。我们将会制作一个山寨版的 Sourcerer,这是一个从 StackOverflow 查询并使用代码片段的插件。到教程结束时,你将会制作好一个将编程问题(用英语描述的)转换成获取自 StackOverflow 的代码片段的插件,像这样:

教程须知

Atom 文本编辑器是用 web 技术创造出来的。我们将完全使用 JavaScript 的 EcmaScript 6 规范来制作插件。你需要熟悉以下内容:

教程的仓库

你可以跟着教程一步一步走,或者看看 放在 GitHub 上的仓库,这里有插件的源代码。这个仓库的历史提交记录包含了这里每一个标题。

开始

安装 Atom

根据 Atom 官网 的说明来下载 Atom。我们同时还要安装上 apm(Atom 包管理器的命令行工具)。你可以打开 Atom 并在应用菜单中导航到 Atom > Install Shell Commands 来安装。打开你的命令行终端,运行 apm -v 来检查 apm 是否已经正确安装好,安装成功的话打印出来的工具版本和相关环境信息应该是像这样的:

apm -v
> apm  1.9.2
> npm  2.13.3
> node 0.10.40
> python 2.7.10
> git 2.7.4

生成骨架代码

让我们使用 Atom 提供的一个实用工具创建一个新的 package(软件包)来开始这篇教程。

  • 启动编辑器,按下 Cmd+Shift+P(MacOS)或者 Ctrl+Shift+P(Windows/Linux)来打开 命令面板 Command Palette
  • 搜索“Package Generator: Generate Package”并点击列表中正确的条目,你会看到一个输入提示,输入软件包的名称:“sourcefetch”。
  • 按下回车键来生成这个骨架代码包,它会自动在 Atom 中打开。

如果你在侧边栏没有看到软件包的文件,依次按下 Cmd+K Cmd+B(MacOS)或者 Ctrl+K Ctrl+B(Windows/Linux)。

命令面板 Command Palette 可以让你通过模糊搜索来找到并运行软件包。这是一个执行命令比较方便的途径,你不用去找导航菜单,也不用刻意去记快捷键。我们将会在整篇教程中使用这个方法。

运行骨架代码包

在开始编程前让我们来试用一下这个骨架代码包。我们首先需要重启 Atom,这样它才可以识别我们新增的软件包。再次打开命令面板,执行 Window: Reload 命令。

重新加载当前窗口以确保 Atom 执行的是我们最新的源代码。每当需要测试我们对软件包的改动的时候,就需要运行这条命令。

通过导航到编辑器菜单的 Packages > sourcefetch > Toggle 或者在命令面板执行 sourcefetch:toggle 来运行软件包的 toggle 命令。你应该会看到屏幕的顶部出现了一个小黑窗。再次运行这条命令就可以隐藏它。

“toggle”命令

打开 lib/sourcefetch.js,这个文件包含有软件包的逻辑和 toggle 命令的定义。

toggle() {
 console.log('Sourcefetch was toggled!');
 return (
   this.modalPanel.isVisible() ?
   this.modalPanel.hide() :
   this.modalPanel.show()
 );
}

toggle 是这个模块导出的一个函数。根据模态面板的可见性,它通过一个三目运算符 来调用 showhide 方法。modalPanelPanel(一个由 Atom API 提供的 UI 元素) 的一个实例。我们需要在 export default 内部声明 modalPanel 才可以让我们通过一个实例变量 this 来访问它。

this.subscriptions.add(atom.commands.add('atom-workspace', {
  'sourcefetch:toggle': () => this.toggle()
}));

上面的语句让 Atom 在用户运行 sourcefetch:toggle 的时候执行 toggle 方法。我们指定了一个 匿名函数 () => this.toggle(),每次执行这条命令的时候都会执行这个函数。这是事件驱动编程(一种常用的 JavaScript 模式)的一个范例。

Atom 命令

命令只是用户触发事件时使用的一些字符串标识符,它定义在软件包的命名空间内。我们已经用过的命令有:

  • package-generator:generate-package
  • Window:reload
  • sourcefetch:toggle

软件包对应到命令,以执行代码来响应事件。

进行你的第一次代码更改

让我们来进行第一次代码更改——我们将通过改变 toggle 函数来实现逆转用户选中文本的功能。

改变 “toggle” 函数

如下更改 toggle 函数。

toggle() {
  let editor
  if (editor = atom.workspace.getActiveTextEditor()) {
    let selection = editor.getSelectedText()
    let reversed = selection.split('').reverse().join('')
    editor.insertText(reversed)
  }
}

测试你的改动

  • 通过在命令面板运行 Window: Reload 来重新加载 Atom。
  • 通过导航到 File > New 来创建一个新文件,随便写点什么并通过光标选中它。
  • 通过命令面板、Atom 菜单或者右击文本然后选中 Toggle sourcefetch 来运行 sourcefetch:toggle 命令。

更新后的命令将会改变选中文本的顺序:

sourcefetch 教程仓库 查看这一步的全部代码更改。

Atom 编辑器 API

我们添加的代码通过用 TextEditor API 来访问编辑器内的文本并进行操作。让我们来仔细看看。

let editor
if (editor = atom.workspace.getActiveTextEditor()) { /* ... */ }

头两行代码获取了 TextEditor 实例的一个引用。变量的赋值和后面的代码被包在一个条件结构里,这是为了处理没有可用的编辑器实例的情况,例如,当用户在设置菜单中运行该命令时。

let selection = editor.getSelectedText()

调用 getSelectedText 方法可以让我们访问到用户选中的文本。如果当前没有文本被选中,函数将返回一个空字符串。

let reversed = selection.split('').reverse().join('')
editor.insertText(reversed)

我们选中的文本通过一个 JavaScript 字符串方法 来逆转。最后,我们调用 insertText 方法来将选中的文本替换为逆转后的文本副本。通过阅读 Atom API 文档,你可以学到更多关于 TextEditor 的不同的方法。

浏览骨架代码

现在我们已经完成第一次代码更改了,让我们浏览骨架代码包的代码来深入了解一下 Atom 的软件包是怎样构成的。

主文件

主文件是 Atom 软件包的入口文件。Atom 通过 package.json 里的条目设置来找到主文件的位置:

"main": "./lib/sourcefetch",

这个文件导出一个带有生命周期函数(Atom 在特定的事件发生时调用的处理函数)的对象。

  • activate 会在 Atom 初次加载软件包的时候调用。这个函数用来初始化一些诸如软件包所需的用户界面元素的对象,以及订阅软件包命令的处理函数。
  • deactivate 会在软件包停用的时候调用,例如,当用户关闭或者刷新编辑器的时候。
  • serialize Atom 调用它在使用软件包的过程中保存软件包的当前状态。它的返回值会在 Atom 下一次加载软件包的时候作为一个参数传递给 activate

我们将会重命名我们的软件包命令为 fetch,并移除一些我们不再需要的用户界面元素。按照如下更改主文件:

'use babel';

import { CompositeDisposable } from 'atom'

export default {

  subscriptions: null,

  activate() {
    this.subscriptions = new CompositeDisposable()

    this.subscriptions.add(atom.commands.add('atom-workspace', {
      'sourcefetch:fetch': () => this.fetch()
    }))
  },

  deactivate() {
    this.subscriptions.dispose()
  },

  fetch() {
    let editor
    if (editor = atom.workspace.getActiveTextEditor()) {
      let selection = editor.getSelectedText()
      selection = selection.split('').reverse().join('')
      editor.insertText(selection)
    }
  }
};

“启用”命令

为了提升性能,Atom 软件包可以用时加载。我们可以让 Atom 在用户执行特定的命令的时候才加载我们的软件包。这些命令被称为 启用命令,它们在 package.json 中定义:

"activationCommands": {
  "atom-workspace": "sourcefetch:toggle"
},

更新一下这个条目设置,让 fetch 成为一个启用命令。

"activationCommands": {
  "atom-workspace": "sourcefetch:fetch"
},

有一些软件包需要在 Atom 启动的时候被加载,例如那些改变 Atom 外观的软件包。在那样的情况下,activationCommands 会被完全忽略。

“触发”命令

菜单项

menus 目录下的 JSON 文件指定了哪些菜单项是为我们的软件包而建的。让我们看看 menus/sourcefetch.json

"context-menu": {
  "atom-text-editor": [
    {
      "label": "Toggle sourcefetch",
      "command": "sourcefetch:toggle"
    }
  ]
},

这个 context-menu 对象可以让我们定义右击菜单的一些新条目。每一个条目都是通过一个显示在菜单的 label 属性和一个点击后执行的命令的 command 属性来定义的。

"context-menu": {
  "atom-text-editor": [
    {
      "label": "Fetch code",
      "command": "sourcefetch:fetch"
    }
  ]
},

同一个文件中的这个 menu 对象用来定义插件的自定义应用菜单。我们如下重命名它的条目:

"menu": [
  {
    "label": "Packages",
    "submenu": [
      {
        "label": "sourcefetch",
        "submenu": [
          {
            "label": "Fetch code",
            "command": "sourcefetch:fetch"
          }
        ]
      }
    ]
  }
]

键盘快捷键

命令还可以通过键盘快捷键来触发。快捷键通过 keymaps 目录的 JSON 文件来定义:

{
  "atom-workspace": {
    "ctrl-alt-o": "sourcefetch:toggle"
  }
}

以上代码可以让用户通过 Ctrl+Alt+O(Windows/Linux) 或 Cmd+Alt+O(MacOS) 来触发 toggle 命令。

重命名引用的命令为 fetch

"ctrl-alt-o": "sourcefetch:fetch"

通过执行 Window: Reload 命令来重启 Atom。你应该会看到 Atom 的右击菜单更新了,并且逆转文本的功能应该还可以像之前一样使用。

sourcefetch 教程仓库 查看这一步所有的代码更改。

使用 NodeJS 模块

现在我们已经完成了第一次代码更改并且了解了 Atom 软件包的结构,让我们介绍一下 Node 包管理器(npm) 中的第一个依赖项模块。我们将使用 request 模块发起 HTTP 请求来下载网站的 HTML 文件。稍后将会用到这个功能来扒 StackOverflow 的页面。

安装依赖

打开你的命令行工具,切换到你的软件包的根目录并运行:

npm install --save [email protected]
apm install

这两条命令将 request 模块添加到我们软件包的依赖列表并将模块安装到 node_modules 目录。你应该会在 package.json 看到一个新条目。@ 符号的作用是让 npm 安装我们这篇教程需要用到的特定版本的模块。运行 apm install 是为了让 Atom 知道使用我们新安装的模块。

"dependencies": {
  "request": "^2.73.0"
}

下载 HTML 并将记录打印在开发者控制台

通过在 lib/sourcefetch.js 的顶部添加一条引用语句引入 request 模块到我们的主文件:

import { CompositeDisposable } from 'atom'
import request from 'request'

现在,在 fetch 函数下面添加一个新函数 download 作为模块的导出项:

export default {  

  /* subscriptions, activate(), deactivate() */

  fetch() {
    ...
  },

  download(url) {
    request(url, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        console.log(body)
      }
    })
  }
}

这个函数用 request 模块来下载一个页面的内容并将记录输出到控制台。当 HTTP 请求完成之后,我们的回调函数会将响应体作为参数来被调用。

最后一步是更新 fetch 函数以调用 download 函数:

fetch() {
  let editor
  if (editor = atom.workspace.getActiveTextEditor()) {
    let selection = editor.getSelectedText()
    this.download(selection)
  }
},

fetch 函数现在的功能是将 selection 当作一个 URL 传递给 download 函数,而不再是逆转选中的文本了。让我们来看看这次的更改:

  • 通过执行 Window: Reload 命令来重新加载 Atom。
  • 打开开发者工具。为此,导航到菜单中的 View > Developer > Toggle Developer Tools
  • 新建一个文件,导航到 File > New
  • 输入一个 URL 并选中它,例如:http://www.atom.io
  • 用上述的任意一种方法执行我们软件包的命令:

开发者工具让 Atom 软件包的调试更轻松。每个 console.log 语句都可以将信息打印到交互控制台,你还可以使用 Elements 选项卡来浏览整个应用的可视化结构——即 HTML 的文本对象模型(DOM)

sourcefetch 教程仓库 查看这一步所有的代码更改。

用 Promises 来将下载好的 HTML 插入到编辑器中

理想情况下,我们希望 download 函数可以将 HTML 作为一个字符串来返回,而不仅仅是将页面的内容打印到控制台。然而,返回文本内容是无法实现的,因为我们要在回调函数里面访问内容而不是在 download 函数那里。

我们会通过返回一个 Promise 来解决这个问题,而不再是返回一个值。让我们改动 download 函数来返回一个 Promise:

download(url) {
  return new Promise((resolve, reject) => {
    request(url, (error, response, body) => {
      if (!error && response.statusCode == 200) {
        resolve(body)
      } else {
        reject({
          reason: 'Unable to download page'
        })
      }
    })
  })
}

Promises 允许我们通过将异步逻辑封装在一个提供两个回调方法的函数里来返回获得的值(resolve 用来处理请求成功的返回值,reject 用来向使用者报错)。如果请求返回了错误我们就调用 reject,否则就用 resolve 来处理 HTML。

让我们更改 fetch 函数来使用 download 返回的 Promise:

fetch() {
  let editor
  if (editor = atom.workspace.getActiveTextEditor()) {
    let selection = editor.getSelectedText()
    this.download(selection).then((html) => {
      editor.insertText(html)
    }).catch((error) => {
      atom.notifications.addWarning(error.reason)
    })
  }
},

在我们新版的 fetch 函数里,我们通过在 download 返回的 Promise 调用 then 方法来对 HTML 进行操作。这会将 HTML 插入到编辑器中。我们同样会通过调用 catch 方法来接收并处理所有的错误。我们通过用 Atom Notification API 来显示警告的形式来处理错误。

看看发生了什么变化。重新加载 Atom 并在一个选中的 URL 上执行软件包命令:

如果这个 URL 是无效的,一个警告通知将会弹出来:

sourcefetch 教程仓库 查看这一步所有的代码更改。

编写一个爬虫来提取 StackOverflow 页面的代码片段

下一步涉及用我们前面扒到的 StackOverflow 的页面的 HTML 来提取代码片段。我们尤其关注那些来自采纳答案(提问者选择的一个正确答案)的代码。我们可以在假设这类答案都是相关且正确的前提下大大简化我们这个软件包的实现。

使用 jQuery 和 Chrome 开发者工具来构建查询

这一部分假设你使用的是 Chrome 浏览器。你接下来可以使用其它浏览器,但是提示可能会不一样。

让我们先看看一张典型的包含采纳答案和代码片段的 StackOverflow 页面。我们将会使用 Chrome 开发者工具来浏览 HTML:

  • 打开 Chrome 并跳到任意一个带有采纳答案和代码的 StackOverflow 页面,比如像这个用 Python 写的 hello world 的例子或者这个关于 C 来读取文本内容的问题
  • 滚动窗口到采纳答案的位置并选中一部分代码。
  • 右击选中文本并选择 检查
  • 使用元素侦察器来检查代码片段在 HTML 中的位置。

注意文本结构应该是这样的:

<div class="accepted-answer">
  ...
    ...
      <pre>
        <code>
          ...snippet elements...
        </code>
      </pre>
    ...
  ...
</div>
  • 采纳的答案通过一个 class 为 accepted-answerdiv 来表示
  • 代码块位于 pre 元素的内部
  • 呈现代码片段的元素就是里面那一对 code 标签

现在让我们写一些 jQuery 代码来提取代码片段:

  • 在开发者工具那里点击 Console 选项卡来访问 Javascript 控制台。
  • 在控制台中输入 $('div.accepted-answer pre code').text() 并按下回车键。

你应该会看到控制台中打印出采纳答案的代码片段。我们刚刚运行的代码使用了一个 jQuery 提供的特别的 $ 函数。$ 接收要选择的查询字符串并返回网站中的某些 HTML 元素。让我们通过思考几个查询案例看看这段代码的工作原理:

$('div.accepted-answer')
> [<div id="answer-1077349" class="answer accepted-answer" ... ></div>]

上面的查询会匹配所有 class 为 accepted-answer<div> 元素,在我们的案例中只有一个 div。

$('div.accepted-answer pre code')
> [<code>...</code>]

在前面的基础上改造了一下,这个查询会匹配所有在之前匹配的 <div> 内部的 <pre> 元素内部的 <code> 元素。

$('div.accepted-answer pre code').text()
> "print("Hello World!")"

text 函数提取并连接原本将由上一个查询返回的元素列表中的所有文本。这也从代码中去除了用来使语法高亮的元素。

介绍 Cheerio

我们的下一步涉及使用我们创建好的查询结合 Cheerio(一个服务器端实现的 jQuery)来实现扒页面的功能。

安装 Cheerio

打开你的命令行工具,切换到你的软件包的根目录并执行:

npm install --save [email protected]
apm install

实现扒页面的功能

lib/sourcefetch.jscheerio 添加一条引用语句:

import { CompositeDisposable } from 'atom'
import request from 'request'
import cheerio from 'cheerio'

现在创建一个新函数 scrape,它用来提取 StackOverflow HTML 里面的代码片段:

fetch() {
  ...
},

scrape(html) {
  $ = cheerio.load(html)
  return $('div.accepted-answer pre code').text()
},

download(url) {
  ...
}

最后,让我们更改 fetch 函数以传递下载好的 HTML 给 scrape 而不是将其插入到编辑器:

fetch() {
  let editor
  let self = this

  if (editor = atom.workspace.getActiveTextEditor()) {
    let selection = editor.getSelectedText()
    this.download(selection).then((html) => {
      let answer = self.scrape(html)
      if (answer === '') {
        atom.notifications.addWarning('No answer found :(')
      } else {
        editor.insertText(answer)
      }
    }).catch((error) => {
      console.log(error)
      atom.notifications.addWarning(error.reason)
    })
  }
},

我们扒取页面的功能仅仅用两行代码就实现了,因为 cheerio 已经替我们做好了所有的工作!我们通过调用 load 方法加载 HTML 字符串来创建一个 $ 函数,然后用这个函数来执行 jQuery 语句并返回结果。你可以在官方 开发者文档 查看完整的 Cheerio API

测试更新后的软件包

重新加载 Atom 并在一个选中的 StackOverflow URL 上运行 soucefetch:fetch 以查看到目前为止的进度。

如果我们在一个有采纳答案的页面上运行这条命令,代码片段将会被插入到编辑器中:

如果我们在一个没有采纳答案的页面上运行这条命令,将会弹出一个警告通知:

我们最新的 fetch 函数给我们提供了一个 StackOverflow 页面的代码片段而不再是整个 HTML 内容。要注意我们更新的 fetch 函数会检查有没有答案并显示通知以提醒用户。

sourcefetch 教程仓库 查看这一步所有的代码更改。

实现用来查找相关的 StackOverflow URL 的谷歌搜索功能

现在我们已经将 StackOverflow 的 URL 转化为代码片段了,让我们来实现最后一个函数——search,它应该要返回一个相关的 URL 并附加一些像“hello world”或者“快速排序”这样的描述。我们会通过一个非官方的 google npm 模块来使用谷歌搜索功能,这样可以让我们以编程的方式来搜索。

安装这个 Google npm 模块

通过在软件包的根目录打开命令行工具并执行命令来安装 google 模块:

npm install --save [email protected]
apm install

引入并配置模块

lib/sourcefetch.js 的顶部为 google 模块添加一条引用语句:

import google from "google"

我们将配置一下 google 以限制搜索期间返回的结果数。将下面这行代码添加到引用语句下面以限制搜索返回最热门的那个结果。

google.resultsPerPage = 1

实现 search 函数

接下来让我们来实现我们的 search 函数:

fetch() {
  ...
},

search(query, language) {
  return new Promise((resolve, reject) => {
    let searchString = `${query} in ${language} site:stackoverflow.com`

    google(searchString, (err, res) => {
      if (err) {
        reject({
          reason: 'A search error has occured :('
        })
      } else if (res.links.length === 0) {
        reject({
          reason: 'No results found :('
        })
      } else {
        resolve(res.links[0].href)
      }
    })
  })
},

scrape() {
  ...
}

以上代码通过谷歌来搜索一个和指定的关键词以及编程语言相关的 StackOverflow 页面,并返回一个最热门的 URL。让我们看看这是怎样来实现的:

let searchString = `${query} in ${language} site:stackoverflow.com`

我们使用用户输入的查询和当前所选的语言来构造搜索字符串。比方说,当用户在写 Python 的时候输入“hello world”,查询语句就会变成 hello world in python site:stackoverflow.com。字符串的最后一部分是谷歌搜索提供的一个过滤器,它让我们可以将搜索结果的来源限制为 StackOverflow。

google(searchString, (err, res) => {
  if (err) {
    reject({
      reason: 'A search error has occured :('
    })
  } else if (res.links.length === 0) {
    reject({
      reason: 'No results found :('
    })
  } else {
    resolve(res.links[0].href)
  }
})

我们将 google 方法放在一个 Promise 里面,这样我们可以异步地返回我们的 URL。我们会传递由 google 返回的所有错误并且会在没有可用的搜索结果的时候返回一个错误。否则我们将通过 resolve 来解析最热门结果的 URL。

更新 fetch 来使用 search

我们的最后一步是更新 fetch 函数来使用 search 函数:

fetch() {
  let editor
  let self = this

  if (editor = atom.workspace.getActiveTextEditor()) {
    let query = editor.getSelectedText()
    let language = editor.getGrammar().name

    self.search(query, language).then((url) => {
      atom.notifications.addSuccess('Found google results!')
      return self.download(url)
    }).then((html) => {
      let answer = self.scrape(html)
      if (answer === '') {
        atom.notifications.addWarning('No answer found :(')
      } else {
        atom.notifications.addSuccess('Found snippet!')
        editor.insertText(answer)
      }
    }).catch((error) => {
      atom.notifications.addWarning(error.reason)
    })
  }
}

让我们看看发生了什么变化:

  • 我们选中的文本现在变成了用户输入的 query
  • 我们使用 TextEditor API 来获取当前编辑器选项卡使用的 language
  • 我们调用 search 方法来获取一个 URL,然后通过在得到的 Promise 上调用 then 方法来访问这个 URL

我们不在 download 返回的 Promise 上调用 then 方法,而是在前面 search 方法本身链式调用的另一个 then 方法返回的 Promise 上面接着调用 then 方法。这样可以帮助我们避免回调地狱

sourcefetch 教程仓库 查看这一步所有的代码更改。

测试最终的插件

大功告成了!重新加载 Atom,对一个“问题描述”运行软件包的命令来看看我们最终的插件是否工作,不要忘了在编辑器右下角选择一种语言。

下一步

现在你知道怎么去 “hack” Atom 的基本原理了,通过 分叉 sourcefetch 这个仓库并添加你的特性 来随心所欲地实践你所学到的知识。


via: https://github.com/blog/2231-building-your-first-atom-plugin

作者:NickTikhonov 译者:OneNewLife 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

前一段时间,有关程序员鼓励师的炒作传得满世界都是,原来宅男程序员们也有福利啊。当然,我是从来没在那些配备了程序员鼓励师的公司干过,无从体验是什么感觉。

不过,对于程序员来说,最重要的是咱可以双手撸码,没有咱可以自己造啊!这不,有位叫“sunqibuhuake”的程序员就自己撸了一个“初音未来”给自己写程序加油了!

(题图来自: kurorofikkykakao.deviantart.com)

如何给你的编辑器也配上一个初音未来给你加油呢?

使用快捷键 command + ,/ctrl + , 打开偏好设置。点击左侧的 Install 即可浏览线上的插件 。 顶部是一个搜索框,可以搜索已经发布在 atom.io 上的插件,输入“atom-miku”搜索安装即可。

然后用 ctrl-alt-k 激活就可以看到初音未来蹦到了你的桌面上了! 她能从你的键盘输入获取到能量,就会唱歌和跳舞~继续撸,不能停!

来看看:

(动图,1Mb+)

据作者说,插件还很粗糙。当然作者也很勤奋,发布三天,已经放出了9个版本,大家快去提交 issues 和 PR 吧。程序员们,你不来试试?