制作你的第一个 Atom 文本编辑器插件

序言

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

教程须知

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

教程的仓库

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

开始

安装 Atom

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


  1. apm -v
  2. > apm 1.9.2
  3. > npm 2.13.3
  4. > node 0.10.40
  5. > python 2.7.10
  6. > 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+KCtrl+B(Windows/Linux)。

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

运行骨架代码包

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

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

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

“toggle”命令

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


  1. toggle() {
  2. console.log('Sourcefetch was toggled!');
  3. return (
  4. this.modalPanel.isVisible() ?
  5. this.modalPanel.hide() :
  6. this.modalPanel.show()
  7. );
  8. }

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


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

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

Atom 命令

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

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

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

进行你的第一次代码更改

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

改变 “toggle” 函数

如下更改 toggle 函数。


  1. toggle() {
  2. let editor
  3. if (editor = atom.workspace.getActiveTextEditor()) {
  4. let selection = editor.getSelectedText()
  5. let reversed = selection.split('').reverse().join('')
  6. editor.insertText(reversed)
  7. }
  8. }

测试你的改动

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

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

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

Atom 编辑器 API

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


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

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


  1. let selection = editor.getSelectedText()

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


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

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

浏览骨架代码

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

主文件

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


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

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

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

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


  1. 'use babel';
  2. import { CompositeDisposable } from 'atom'
  3. export default {
  4. subscriptions: null,
  5. activate() {
  6. this.subscriptions = new CompositeDisposable()
  7. this.subscriptions.add(atom.commands.add('atom-workspace', {
  8. 'sourcefetch:fetch': () => this.fetch()
  9. }))
  10. },
  11. deactivate() {
  12. this.subscriptions.dispose()
  13. },
  14. fetch() {
  15. let editor
  16. if (editor = atom.workspace.getActiveTextEditor()) {
  17. let selection = editor.getSelectedText()
  18. selection = selection.split('').reverse().join('')
  19. editor.insertText(selection)
  20. }
  21. }
  22. };

“启用”命令

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


  1. "activationCommands": {
  2. "atom-workspace": "sourcefetch:toggle"
  3. },

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


  1. "activationCommands": {
  2. "atom-workspace": "sourcefetch:fetch"
  3. },

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

“触发”命令

菜单项

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


  1. "context-menu": {
  2. "atom-text-editor": [
  3. {
  4. "label": "Toggle sourcefetch",
  5. "command": "sourcefetch:toggle"
  6. }
  7. ]
  8. },

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


  1. "context-menu": {
  2. "atom-text-editor": [
  3. {
  4. "label": "Fetch code",
  5. "command": "sourcefetch:fetch"
  6. }
  7. ]
  8. },

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


  1. "menu": [
  2. {
  3. "label": "Packages",
  4. "submenu": [
  5. {
  6. "label": "sourcefetch",
  7. "submenu": [
  8. {
  9. "label": "Fetch code",
  10. "command": "sourcefetch:fetch"
  11. }
  12. ]
  13. }
  14. ]
  15. }
  16. ]

键盘快捷键

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


  1. {
  2. "atom-workspace": {
  3. "ctrl-alt-o": "sourcefetch:toggle"
  4. }
  5. }

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

重命名引用的命令为 fetch


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

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

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

使用 NodeJS 模块

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

安装依赖

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


  1. npm install --save request@2.73.0
  2. apm install

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


  1. "dependencies": {
  2. "request": "^2.73.0"
  3. }

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

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


  1. import { CompositeDisposable } from 'atom'
  2. import request from 'request'

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


  1. export default {
  2. /* subscriptions, activate(), deactivate() */
  3. fetch() {
  4. ...
  5. },
  6. download(url) {
  7. request(url, (error, response, body) => {
  8. if (!error && response.statusCode == 200) {
  9. console.log(body)
  10. }
  11. })
  12. }
  13. }

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

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


  1. fetch() {
  2. let editor
  3. if (editor = atom.workspace.getActiveTextEditor()) {
  4. let selection = editor.getSelectedText()
  5. this.download(selection)
  6. }
  7. },

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:


  1. download(url) {
  2. return new Promise((resolve, reject) => {
  3. request(url, (error, response, body) => {
  4. if (!error && response.statusCode == 200) {
  5. resolve(body)
  6. } else {
  7. reject({
  8. reason: 'Unable to download page'
  9. })
  10. }
  11. })
  12. })
  13. }

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

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


  1. fetch() {
  2. let editor
  3. if (editor = atom.workspace.getActiveTextEditor()) {
  4. let selection = editor.getSelectedText()
  5. this.download(selection).then((html) => {
  6. editor.insertText(html)
  7. }).catch((error) => {
  8. atom.notifications.addWarning(error.reason)
  9. })
  10. }
  11. },

在我们新版的 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 中的位置。

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


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

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

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

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


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

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


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

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


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

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

介绍 Cheerio

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

安装 Cheerio

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


  1. npm install --save cheerio@0.20.0
  2. apm install

实现扒页面的功能

在 lib/sourcefetch.js 为 cheerio 添加一条引用语句:


  1. import { CompositeDisposable } from 'atom'
  2. import request from 'request'
  3. import cheerio from 'cheerio'

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


  1. fetch() {
  2. ...
  3. },
  4. scrape(html) {
  5. $ = cheerio.load(html)
  6. return $('div.accepted-answer pre code').text()
  7. },
  8. download(url) {
  9. ...
  10. }

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


  1. fetch() {
  2. let editor
  3. let self = this
  4. if (editor = atom.workspace.getActiveTextEditor()) {
  5. let selection = editor.getSelectedText()
  6. this.download(selection).then((html) => {
  7. let answer = self.scrape(html)
  8. if (answer === '') {
  9. atom.notifications.addWarning('No answer found :(')
  10. } else {
  11. editor.insertText(answer)
  12. }
  13. }).catch((error) => {
  14. console.log(error)
  15. atom.notifications.addWarning(error.reason)
  16. })
  17. }
  18. },

我们扒取页面的功能仅仅用两行代码就实现了,因为 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 模块:


  1. npm install --save google@2.0.0
  2. apm install

引入并配置模块

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


  1. import google from "google"

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


  1. google.resultsPerPage = 1

实现 search 函数

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


  1. fetch() {
  2. ...
  3. },
  4. search(query, language) {
  5. return new Promise((resolve, reject) => {
  6. let searchString = `${query} in ${language} site:stackoverflow.com`
  7. google(searchString, (err, res) => {
  8. if (err) {
  9. reject({
  10. reason: 'A search error has occured :('
  11. })
  12. } else if (res.links.length === 0) {
  13. reject({
  14. reason: 'No results found :('
  15. })
  16. } else {
  17. resolve(res.links[0].href)
  18. }
  19. })
  20. })
  21. },
  22. scrape() {
  23. ...
  24. }

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


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

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


  1. google(searchString, (err, res) => {
  2. if (err) {
  3. reject({
  4. reason: 'A search error has occured :('
  5. })
  6. } else if (res.links.length === 0) {
  7. reject({
  8. reason: 'No results found :('
  9. })
  10. } else {
  11. resolve(res.links[0].href)
  12. }
  13. })

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

更新 fetch 来使用 search

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


  1. fetch() {
  2. let editor
  3. let self = this
  4. if (editor = atom.workspace.getActiveTextEditor()) {
  5. let query = editor.getSelectedText()
  6. let language = editor.getGrammar().name
  7. self.search(query, language).then((url) => {
  8. atom.notifications.addSuccess('Found google results!')
  9. return self.download(url)
  10. }).then((html) => {
  11. let answer = self.scrape(html)
  12. if (answer === '') {
  13. atom.notifications.addWarning('No answer found :(')
  14. } else {
  15. atom.notifications.addSuccess('Found snippet!')
  16. editor.insertText(answer)
  17. }
  18. }).catch((error) => {
  19. atom.notifications.addWarning(error.reason)
  20. })
  21. }
  22. }

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

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

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

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

测试最终的插件

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

下一步

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

原文发布时间为:2016-10-15

本文来自合作伙伴“Linux中国”

时间: 2024-10-27 01:33:28

制作你的第一个 Atom 文本编辑器插件的相关文章

在 Ubuntu 14.04 和 Linux Mint 17 上安装 Atom 文本编辑器

在 Ubuntu 14.04 和 Linux Mint 17 上安装 Atom 文本编辑器 Atom是Github上时髦的,功能丰富的开源文本编辑器.目前,它正处于测试阶段,但如果你对它很好奇,那我们就来看看如何在 Ubuntu 14.04 和 Linux Mint 17 上安装 Atom. 无论是在外观,还是在功能上,Atom 都有很多与Sublime Text editor相似之处.Sublime Text editor是一个功能强大,并深受程序员喜爱的跨平台文本编辑器,可惜它是闭源的.事实

Vim一个高级文本编辑器

Vim 是一个高级http://www.aliyun.com/zixun/aggregation/18444.html">文本编辑器,她提供了Unix下编辑器 'Vi' 的功能并对其进行了完善.Vim 经常被认为是 "程序员的编辑器",她在程序编写时非常有用,很多人认为她是一个完整的集成开发环境(IDE).仅管如此,Vim并不只是程序员使用的.Vim可以用于多种文档编辑,从email排版到配置文件编写. 本篇文章将告诉您如何安装vim,并对其进行简单介绍. 安装 vim

谁有javaweb 的文本编辑器插件了

问题描述 谁有javaweb 的文本编辑器插件了 最近需要一个编辑器,自己不想写一个简单的,想功能多一点的编辑器,请问哪位大神有关于javaweb方面的文本编辑器插件了,告诉地址也行,急用.谢谢!

Vrapper 0.16.0发布 Eclipse文本编辑器插件

Vrapper是一个http://www.aliyun.com/zixun/aggregation/13428.html">Eclipse的文本编辑器插件,使文本编辑器具备 vi 的编辑效果. 习惯了vim的操作方式,换上IDE环境还真有点不习惯,像dd yy $ gg jkli这些常用的操作指令还是很高效,eclipse下面也有vim的插件来支持一些vim常见的操作方式.eclipse下常用的vim插件有两个,一个收费的ViPlugin,另一个免费的vrapper Vrapper是开源的

就像这样子的就可以啦-跪求一份简单文本编辑器插件,能copy在java web项目中就能运行的那一种

问题描述 跪求一份简单文本编辑器插件,能copy在java web项目中就能运行的那一种 解决方案 http://kindeditor.net/demo.php 解决方案二: http://kindeditor.net/demo.php http://ueditor.baidu.com/website/onlinedemo.html http://ckeditor.com/demo

Github 为开发者发布 Atom 文本编辑器

Github 今天发布了一个名为 Atom 的全新在线文本编辑器.编辑器采用全新域名 atom.io 运行.据说 Github 内部已经使用 Atom 六年时间.目前 Atom 暂时只接受邀请注册使用. 在文章 announcing the new editor today 中,Github 称 Atom 之前只是一个试验性项目,而后迅速发展成实用工具.而且 Atom 是完全开源,Github 鼓励开发者对它进行扩展. Mac 版的 Atom 还在封闭测试中,而 Windows 和 Linux

《Linux指令从入门到精通》——4.2 Linux下的简单文字模式文本编辑器

4.2 Linux下的简单文字模式文本编辑器 Linux下的文本编辑器种类很多,功能的复杂程度和操作的难易度也不尽相同.在此我们将其大致分为可视和不可视两种.在本节中讲解的ed,jed,joe,pico和sed都属于不可视编辑器,不能进行全屏方式下的操作,操作相对简单.但可视编辑器的交互功能更好,典型的可视编辑器有vi和emacs,这将在下一节中讲述. 4.2.1 ed指令:简单的行文本编辑器 理解行编辑的概念,掌握ed指令进行简单的行文本编辑的方法 ed [参数] [文件名] ed指令是Lin

手机端--富文本编辑器

问题描述 各位大神,手机端想弄一个富文本编辑器,有没有好的推荐:不是安卓...是基于浏览器的[有过成功经验的大虾,给点提示,,,谢谢] 解决方案 解决方案二:先从业务角度把东西想明白.在手机上弄一个Html编辑器,进行十几.二十几项编辑,如何操作?用手指头吗?先把这个业务设计出来,才好找实现.解决方案三:需求挺逗解决方案四: 解决方案五:楼上更逗,人家需求怎么就逗了?手机端富文本编辑器很多场景都有需求解决方案六:百度的富文本编辑器ueditor,之前用了还不错.解决方案七:没看清是手机端使用.手

iOS实现富文本编辑器的方法详解_IOS

前言 富文本编辑器不同于文本编辑器,国内做的比较好的比如有百度的UEditor和kindEditor.但是这两个也有它的缺点:界面过于复杂.不够简洁.UI设计也比较落后.不够轻量化,这篇文章我们将给大家介绍利用iOS如何实现富文本编辑器. 实现的效果 解决思路 采用webview加载一个本地html文件,该html内部编写好js方法用于与oc相互调用 最终输出该富文本字符串传输给服务器 为什么选择这样的方式 服务端要求我最终返回的数据格式为: { @"Id":"当时新建模板这