Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu.Wang 2018-07-03 21:13:12 +08:00
commit a6ba8bd424
10 changed files with 487 additions and 559 deletions

View File

@ -0,0 +1,99 @@
如何记录你在终端中执行的所有操作
======
![](https://www.ostechnix.com/wp-content/uploads/2017/03/Record-Everything-You-Do-In-Terminal-720x340.png)
几天前,我们发布了一个解释如何[保存终端中的命令并按需使用][1]的指南。对于那些不想记忆冗长的 Linux 命令的人来说,这非常有用。今天,在本指南中,我们将看到如何使用 `script` 命令记录你在终端中执行的所有操作。你可能已经在终端中运行了一个命令,或创建了一个目录,或者安装了一个程序。`script` 命令会保存你在终端中执行的任何操作。如果你想知道你几小时或几天前做了什么,那么你可以查看它们。我知道我知道,我们可以使用上/下箭头或 `history` 命令查看以前运行的命令。但是,你无法查看这些命令的输出。而 `script` 命令记录并显示完整的终端会话活动。
`script` 命令会在终端中创建你所做的所有事件的记录。无论你是安装程序,创建目录/文件还是删除文件夹,一切都会被记录下来,包括命令和相应的输出。这个命令对那些想要一份交互式会话拷贝作为作业证明的人有用。无论是学生还是导师,你都可以将所有在终端中执行的操作和所有输出复制一份。
### 在 Linux 中使用 script 命令记录终端中的所有内容
`script` 命令预先安装在大多数现代 Linux 操作系统上。所以,我们不用担心安装。
让我们继续看看如何实时使用它。
运行以下命令启动终端会话记录。
```
$ script -a my_terminal_activities
```
其中,`-a` 标志用于将输出追加到文件(记录)中,并保留以前的内容。上述命令会记录你在终端中执行的所有操作,并将输出追加到名为 `my_terminal_activities` 的文件中,并将其保存在当前工作目录中。
示例输出:
```
Script started, file is my_terminal_activities
```
现在,在终端中运行一些随机的 Linux 命令。
```
$ mkdir ostechnix
$ cd ostechnix/
$ touch hello_world.txt
$ cd ..
$ uname -r
```
运行所有命令后,使用以下命令结束 `script` 命令的会话:
```
$ exit
```
示例输出:
```
exit
Script done, file is my_terminal_activities
```
如你所见,终端活动已存储在名为 `my_terminal_activities` 的文件中,并将其保存在当前工作目录中。
要查看你的终端活动,只需在任何编辑器中打开此文件,或者使用 `cat` 命令直接显示它。
```
$ cat my_terminal_activities
```
示例输出:
```
Script started on Thu 09 Mar 2017 03:33:44 PM IST
[sk@sk]: ~>$ mkdir ostechnix
[sk@sk]: ~>$ cd ostechnix/
[sk@sk]: ~/ostechnix>$ touch hello_world.txt
[sk@sk]: ~/ostechnix>$ cd ..
[sk@sk]: ~>$ uname -r
4.9.11-1-ARCH
[sk@sk]: ~>$ exit
exit
Script done on Thu 09 Mar 2017 03:37:49 PM IST
```
正如你在上面的输出中看到的,`script` 命令记录了我所有的终端活动,包括 `script` 命令的开始和结束时间。真棒,不是吗?使用 `script` 命令的原因不仅仅是记录命令,还有命令的输出。简单地说,脚本命令将记录你在终端上执行的所有操作。
### 结论
就像我说的那样,脚本命令对于想要保留其终端活动记录的学生,教师和 Linux 用户非常有用。尽管有很多 CLI 和 GUI 可用来执行此操作,但 `script` 命令是记录终端会话活动的最简单快捷的方式。
就是这些。希望这有帮助。如果你发现本指南有用,请在你的社交,专业网络上分享,并支持我们。
干杯!
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/record-everything-terminal/
作者:[SK][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.ostechnix.com/author/sk/
[1]:https://www.ostechnix.com/save-commands-terminal-use-demand/

View File

@ -4,11 +4,12 @@
> 这是许多事情的第一步
![women programming](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/collab-team-pair-programming-code-keyboard2.png?itok=WnKfsl-G "women programming")
图片提供 : [WOCinTech Chat][16]. 图片修改 : Opensource.com. [CC BY-SA 4.0][17]
有一个普遍的误解,那就是对开源做出贡献是一件很难的事。你可能会想,“有时我甚至不能理解我自己的代码;那我怎么可能理解别人的?”
放轻松。直到去年,我都以为是这样。阅读和理解他人的代码,然后把你自己的写在顶上,这是一件令人气馁的任务;但如果有合适的资源,这不像你想象的那么糟。
放轻松。直到去年,我都以为是这样。阅读和理解他人的代码,然后在他们的基础上写上你自己的代码,这是一件令人气馁的任务;但如果有合适的资源,这不像你想象的那么糟。
第一步要做的是选择一个项目。这个决定是可能是一个菜鸟转变成一个老练的开源贡献者的关键一步。
@ -16,7 +17,7 @@
### 理解产品
在开始贡献之前,你需要理解项目是怎么工作的。为了理解这一点,你需要自己来尝试。如果你发现这个产品很有趣并且游泳,它就值得你来做贡献。
在开始贡献之前,你需要理解项目是怎么工作的。为了理解这一点,你需要自己来尝试。如果你发现这个产品很有趣并且有用,它就值得你来做贡献。
初学者常常选择参与贡献那些他们没有使用过的软件。他们会失望,并且最终放弃贡献。如果你没有用过这个软件,你不会理解它是怎么工作的。如果你不理解它是怎么工作的,你怎么能解决 bug 或添加新特性呢?
@ -31,77 +32,59 @@
这里介绍了怎么确认一个项目是否还是活跃的:
* **贡献者数量:** 一个增加的贡献者数量表明开发者社区乐于接受新的贡献者。
* **<ruby>提交<rt>commit</rt></ruby>频率:** 查看最近的提交时间。如果是一周之内,甚至是一两个月内,这个项目应该是定期维护的。
* **维护者数量:** 维护者的数量越多,你越可能得到指导。
* **聊天室活动等级:** 一个繁忙的聊天室意味着你的问题可以更快得到回复。
* **<ruby>提交<rt>commit</rt></ruby>频率:** 查看最近的提交时间。如果是一周之内,甚至是一两个月内,这个项目应该是定期维护的。
* **维护者数量:** 维护者的数量越多,你越可能得到指导。
* **聊天室或 IRC 活跃度:** 一个繁忙的聊天室意味着你的问题可以更快得到回复。
### 新手资源
Coala 是一个开源项目的例子。它有自己的教程和文档让你可以使用它每一个类和方法的 API。这个网站还设计了一个有吸引力的界面让你有阅读的兴趣。
**文档:** 所有水平的开发者都需要可靠的,被很好地维护的文档,来理解项目的细节。找找在 [GitHub][19](或者承载的任何位置)上,或者在单独的类似于 [阅读文档][20] 的页面上提供完善文档的项目,这样可以帮助你深入了解代码。
### [Coala 新手指南.png][2]
**文档:** 不管哪种水平的开发者都需要可靠的、被很好地维护的文档,来理解项目的细节。找找在 [GitHub][19](或者放在其它位置)或者类似于 [Read the Docs][20] 之类的独立站点上提供了完善文档的项目,这样可以帮助你深入了解代码。
![Coala Newcomers' Guide screen](https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/coala-newcomers_guide.png?itok=G7mfPbXN "Coala Newcomers' Guide screen")
**教程:** 教程会给新手解释如何在项目里添加特性 然而你可以在任何项目里找到它。例如Coala 提供了 [tutorials for writing  _bears_][21]  (执行代码分析的<ruby>格式化代码<rt>linting</rt></ruby>工具的Python 包装器).
### [Coala 界面.png][3]
**教程:** 教程会给新手解释如何在项目里添加特性 然而你不是在每个项目中都能找到它。例如Coala 提供了 [小熊编写指南][21] (进行代码分析的<ruby>代码格式化<rt>linting</rt></ruby>工具的 Python 包装器)。
![Coala UI](https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/coala_ui.png?itok=LR02629W "Coala User Interface screenshot")
**添加标签的<ruby>讨论点<rt>issue</rt></ruby>:** 对刚刚想明白如何选择第一个项目的初学者来说,选择一个讨论点是一个更加困难的任务。标签被设为“难度/低”,“难度/新手”“利于初学者”以及“low-hanging fruit”都表明是对新手友好的。F
### [Coala 讨论点标签.png][4]
**分类的<ruby>讨论点<rt>issue</rt></ruby>** 对刚刚想明白如何选择第一个项目的初学者来说,选择一个讨论点是一个更加困难的任务。标签被设为“难度/低”、“难度/新手”、“利于初学者”,以及“<ruby>触手可及<rt>low-hanging fruit</rt></ruby>”都表明是对新手友好的。
![Coala labeled issues](https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/coala_labeled_issues.png?itok=74qSjG_T "Coala labeled issues")
### 其他因素
### [ci_历史纪录.png][5]
![CI user pipeline log](https://opensource.com/sites/default/files/styles/panopoly_image_original/public/images/life-uploads/ci_logs.png?itok=J3V8gbc7 "CI user pipeline log")
* **维护者对新的贡献者的态度:** 从我的经验来看,大部分开源贡献者都很乐于帮助他们项目里的新手。然而,当你问问题时,你也有可能遇到一些不太友好的人(甚至可能有点粗鲁)。不要因为这些人失去信心。他们只是因为在比他们经验更丰富的人那儿得不到发泄的机会。还有很多其他人愿意提供帮助。
* **审阅过程/结构:** 你的拉取请求将被你的同事和有经验的开发者查看和更改很多次——这就是你学习软件开发最主要的方式。一个具有严格审阅过程的项目使您能够通过编写生产级代码来作为开发人员成长。
* **一个稳健的<ruby>持续整合<rt>continuous integration</rt></ruby>管道:** 开源项目会向新手们介绍持续整合和部署服务。一个稳健的 CI 管道将帮助你学习阅读和理解 CI 日志。它也将带给你处理失败的测试案例和代码覆盖率问题的经验。
* **参加编程项目 (例如 [Google Summer Of Code][1]):** 参加组织证明了你乐于对一个项目的长期发展做贡献。他们也会给新手提供一个机会来获得现实世界中的开发经验,从而获得报酬。大多数参加这些项目的组织都欢迎新人加入。
* **维护者对新的贡献者的态度:** 从我的经验来看,大部分开源贡献者都很乐于帮助他们项目里的新手。然而,当你问问题时,你也有可能遇到一些不太友好的人(甚至可能有点粗鲁)。不要因为这些人失去信心。他们只是因为在比他们经验更丰富的人那儿得不到发泄的机会而已。还有很多其他人愿意提供帮助。
* **审阅过程/机制:** 你的拉取请求将经历几遍你的同伴和有经验的开发者的查看和更改——这就是你学习软件开发最主要的方式。一个具有严格审阅过程的项目使您在编写生产级代码的过程中成长。
* **一个稳健的<ruby>持续集成<rt>continuous integration</rt></ruby>管道:** 开源项目会向新手们介绍持续集成和部署服务。一个稳健的 CI 管道将帮助你学习阅读和理解 CI 日志。它也将带给你处理失败的测试用例和代码覆盖率问题的经验。
* **参加编程项目(例如 [Google Summer Of Code][1]** 参加组织证明了你乐于对一个项目的长期发展做贡献。他们也会给新手提供一个机会来获得现实世界中的开发经验,从而获得报酬。大多数参加这些项目的组织都欢迎新人加入。
### 7 对新手友好的组织
* [coala (Python)][7]
* [oppia (Python, Django)][8]
* [DuckDuckGo (Perl, JavaScript)][9]
* [OpenGenus (JavaScript)][10]
* [Kinto (Python, JavaScript)][11]
* [FOSSASIA (Python, JavaScript)][12]
* [Kubernetes (Go)][13]
### 关于作者
[![](https://opensource.com/sites/default/files/styles/profile_pictures/public/pictures/img_20180309_001440858.jpg?itok=tG8yvrJF)][22] Palash Nigam - 我是一个印度计算机科学专业本科生,十分乐于参与开源软件的开发,我在 GitHub 上花费了大部分的时间。我现在的兴趣包括 web 后端开发,区块链,和 All things python.[更多关于我][14]
[![](https://opensource.com/sites/default/files/styles/profile_pictures/public/pictures/img_20180309_001440858.jpg?itok=tG8yvrJF)][22]
Palash Nigam - 我是一个印度计算机科学专业本科生,十分乐于参与开源软件的开发,我在 GitHub 上花费了大部分的时间。我现在的兴趣包括 web 后端开发,区块链,和 All things python。[更多关于我][14]
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/4/get-started-open-source-project
作者:[ Palash Nigam ][a]
作者:[Palash Nigam][a]
译者:[lonaparte](https://github.com/lonaparte)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -0,0 +1,86 @@
协同编辑器的历史性清单
======
按时间顺序快速列出主要协同编辑器的演变。
正如任何这样的清单一样,它必定会在一开始便提到被誉为“<ruby>[所有演示之母][25]<rt>the mother of all demos</rt></ruby>”,在这个演示里<ruby>[道格·恩格尔巴特][26]<rt>Doug Engelbart</rt></ruby>早在 1968 年就描述了几乎所有软件的详尽清单。这不仅包括协同编辑器,还包括图形、编程和数学编辑器。
一切都始于那个演示,只不过软件的实现跟不上硬件的发展罢了。
> 软件发展的速度比硬件提升的速度慢。——沃斯定律
闲话少说,这里是我找到的可圈可点的协同编辑器的清单。我说“可圈可点”的意思是它们具有可圈可点的特征或实现细节。
| 项目 | 日期 | 平台 | 说明 |
| --- | --- | --- | --- |
| [SubEthaEdit][1] | 2003-2015 | 仅 Mac|我能找到的首个协同的、实时的、多光标的编辑器, [有个在 Emacs 上的逆向工程的尝试][2]却没有什么结果。 |
| [DocSynch][3] | 2004-2007 | | 建立于 IRC 之上! |
| [Gobby][4] | 2005 至今 | C多平台 | 首个开源、稳固可靠的实现。 仍然存在!众所周知 [libinfinoted][5] 协议很难移植到其他编辑器中(例如: [Rudel][6] 不能在 Emacs 上实现此协议)。 2017 年 1 月发行的 0.7 版本添加了也许可以改善这种状况的 Python 绑定。 值得注意的插件: 自动保存到磁盘。|
| [Ethercalc][27] | 2005 至今 | WebJavaScript | 首个电子表格,随同 [Google Docs][28]。 |
| [moonedit][7] | 2005-2008 | | 原网站已关闭。其他用户的光标可见并且会模仿击键的声音。 包括一个计算器和音乐定序器。 |
| [synchroedit][8] | 2006-2007 | | 首个 Web 应用。|
| [Inkscape][29] | 2007-2011 | C++ | 首个具备协同功能的图形编辑器其背后的“whiteboard” 插件构建于 Jabber 之上,现已停摆。|
| [Abiword][30] | 2008 至今|C++| 首个文字处理器。|
| [Etherpad][9] | 2008 至今 | Web |首款稳定的 Web 应用。 最初在 2008 年被开发时是一款大型 Java 应用,在 2009 年被谷歌收购并开源,然后在 2011 年被用 Node.JS 重写。使用广泛。|
| [Wave][31]|2009-2010|Web Java| 在大一统协议的尝试上失败。|
| [CRDT][10] | 2011 | 特定平台| 在不同电脑间可靠地复制一个文件的数据结构的标准。 |
| [Operational transform][11] | 2013 | 特定平台| 与 CRDT 类似,然而确切地说,两者是不同的。 |
| [Floobits][12] | 2013 至今 | | 商业软件,但有对各种编辑器的开源插件。 |
| [LibreOffice Online][32]| 2015至今| Web| 免费的 Google docs 替代品,现已集成到 [Nextcloud][33] |
| [HackMD][13] | 2015 至今| | 商业软件,[开源][14]。灵感来自于(已被 Dropbox 收购的) hackpad。 |
| [Cryptpad][15] | 2016 至今 | Web ? | Xwiki 的副产品。服务器端的加密的、“零知识” 产品。|
| [Prosemirror][16] | 2016 至今 | Web Node.JS | “试图架起消除 Markdown 文本编辑和传统的所见即所得编辑器之间隔阂的桥梁。”不是完全意义上的编辑器,而是一种可以用来构建编辑器的工具。 |
| [Qill][17] | 2013 至今 | Web Node.JS | 富文本编辑器,同时也是 JavaScript 编辑器。不确定是否是协同式的。 |
| [Teletype][19] | 2017 至今 | WebRTC Node.JS | 为 GitHub 的 [Atom 编辑器][20] 引入了“门户”的思路 使得访客可以夸多个文档跟踪主人的操作。访问介绍服务器后使用实时通讯的点对点技术P2P基于 CRDT。 |
| [Tandem][21] | 2018 至今 | Node.JS | Atom、 Vim、Neovim、 Sublime 等的插件。 使用中继来设置基于 CRDT 的 P2P 连接。多亏 Debian 开发者的参与,[可疑证书问题][22]已被解决,这使它成为很有希望在未来被遵循的标准。 |
### 其他清单
* [Emacs 维基][23]
* [维基百科][24]
--------------------------------------------------------------------------------
via: https://anarc.at/blog/2018-06-26-collaborative-editors-history/
作者:[Anacr][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[ZenMoore](https://github.com/ZenMoore)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://anarc.at
[1]:https://www.codingmonkeys.de/subethaedit/
[2]:https://www.emacswiki.org/emacs/SubEthaEmacs
[3]:http://docsynch.sourceforge.net/
[4]:https://gobby.github.io/
[5]:http://infinote.0x539.de/libinfinity/API/libinfinity/
[6]:https://www.emacswiki.org/emacs/Rudel
[7]:https://web.archive.org/web/20060423192346/http://www.moonedit.com:80/
[8]:http://www.synchroedit.com/
[9]:http://etherpad.org/
[10]:https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type
[11]:http://operational-transformation.github.io/
[12]:https://floobits.com/
[13]:https://hackmd.io/
[14]:https://github.com/hackmdio/hackmd
[15]:https://cryptpad.fr/
[16]:https://prosemirror.net/
[17]:https://quilljs.com/
[18]:https://nextcloud.com/collaboraonline/
[19]:https://teletype.atom.io/
[20]:https://atom.io
[21]:http://typeintandem.com/
[22]:https://github.com/typeintandem/tandem/issues/131
[23]:https://www.emacswiki.org/emacs/CollaborativeEditing
[24]:https://en.wikipedia.org/wiki/Collaborative_real-time_editor
[25]:https://en.wikipedia.org/wiki/The_Mother_of_All_Demos
[26]:https://en.wikipedia.org/wiki/Douglas_Engelbart
[27]:https://ethercalc.net/
[28]:https://en.wikipedia.org/wiki/Google_docs
[29]:http://wiki.inkscape.org/wiki/index.php/WhiteBoard
[30]:https://en.wikipedia.org/wiki/AbiWord
[31]:https://en.wikipedia.org/wiki/Apache_Wave
[32]:https://wiki.documentfoundation.org/Development/LibreOffice_Online
[33]:https://nextcloud.com/collaboraonline/

View File

@ -1,271 +0,0 @@
translating----hoppipolla-
3 Python command-line tools
======
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-lead-tool-box.png?itok=NrJYb417)
This article was co-written with [Lacey Williams Henschel][1].
Sometimes the right tool for the job is a command-line application. A command-line application is a program that you interact with and run from something like your shell or Terminal. [Git][2] and [Curl][3] are examples of command-line applications that you might already be familiar with.
Command-line apps are useful when you have a bit of code you want to run several times in a row or on a regular basis. Django developers run commands like `./manage.py runserver` to start their web servers; Docker developers run `docker-compose up` to spin up their containers. The reasons you might want to write a command-line app are as varied as the reasons you might want to write code in the first place.
For this month's Python column, we have three libraries to recommend to Pythonistas looking to write their own command-line tools.
### Click
[Click][4] is our favorite Python package for command-line applications. It:
* Has great documentation filled with examples
* Includes instructions on packaging your app as a Python application so it's easier to run
* Automatically generates useful help text
* Lets you stack optional and required arguments and even [several commands][5]
* Has a Django version ([][6]
`django-click`
) for writing management commands
Click uses its `@click.command()` to declare a function as a command and specify required or optional arguments.
```
# hello.py
import click
@click.command()
@click.option('--name', default='', help='Your name')
def say_hello(name):
    click.echo("Hello {}!".format(name))
if __name__ == '__main__':
    hello()
```
The `@click.option()` decorator declares an [optional argument][7], and the `@click.argument()` decorator declares a [required argument][8]. You can combine optional and required arguments by stacking the decorators. The `echo()` method prints results to the console.
```
$ python hello.py --name='Lacey'
Hello Lacey!
```
### Docopt
[Docopt][9] is a command-line application parser, sort of like Markdown for your command-line apps. If you like writing the documentation for your apps as you go, Docopt has by far the best-formatted help text of the options in this article. It isn't our favorite command-line app library because its documentation throws you into the deep end right away, which makes it a little more difficult to get started. Still, it's a lightweight library that is very popular, especially if exceptionally nice documentation is important to you.
`help` and `version` flags.
Docopt is very particular about how you format the required docstring at the top of your file. The top element in your docstring after the name of your tool must be "Usage," and it should list the ways you expect your command to be called (e.g., by itself, with arguments, etc.). Usage should includeandflags.
The second element in your docstring should be "Options," and it should provide more information about the options and arguments you identified in "Usage." The content of your docstring becomes the content of your help text.
```
"""HELLO CLI
Usage:
    hello.py
    hello.py <name>
    hello.py -h|--help
    hello.py -v|--version
Options:
    <name>  Optional name argument.
    -h --help  Show this screen.
    -v --version  Show version.
"""
from docopt import docopt
def say_hello(name):
    return("Hello {}!".format(name))
if __name__ == '__main__':
    arguments = docopt(__doc__, version='DEMO 1.0')
    if arguments['<name>']:
        print(say_hello(arguments['<name>']))
    else:
        print(arguments)
```
At its most basic level, Docopt is designed to return your arguments to the console as key-value pairs. If I call the above command without specifying a name, I get a dictionary back:
```
$ python hello.py
{'--help': False,
 '--version': False,
 '<name>': None}
```
This shows me I did not input the `help` or `version` flags, and the `name` argument is `None`.
But if I call it with a name, the `say_hello` function will execute.
```
$ python hello.py Jeff
Hello Jeff!
```
Docopt allows both required and optional arguments and has different syntax conventions for each. Required arguments should be represented in `ALLCAPS` or in `<carets>`, and options should be represented with double or single dashes, like `--name`. Read more about Docopt's [patterns][10] in the docs.
### Fire
[Fire][11] is a Google library for writing command-line apps. We especially like it when your command needs to take more complicated arguments or deal with Python objects, as it tries to handle parsing your argument types intelligently.
Fire's [docs][12] include a ton of examples, but I wish the docs were a bit better organized. Fire can handle [multiple commands in one file][13], commands as methods on [objects][14], and [grouping][15] commands.
Its weakness is the documentation it makes available to the console. Docstrings on your commands don't appear in the help text, and the help text doesn't necessarily identify arguments.
```
import fire
def say_hello(name=''):
    return 'Hello {}!'.format(name)
if __name__ == '__main__':
  fire.Fire()
```
Arguments are made required or optional depending on whether you specify a default value for them in your function or method definition. To call this command, you must specify the filename and the function name, more like Click's syntax:
```
$ python hello.py say_hello Rikki
Hello Rikki!
```
You can also pass arguments as flags, like `--name=Rikki`.
### Bonus: Packaging!
Click includes instructions (and highly recommends you follow them) for [packaging][16] your commands using `setuptools`.
To package our first example, add this content to your `setup.py` file:
```
from setuptools import setup
setup(
    name='hello',
    version='0.1',
    py_modules=['hello'],
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        hello=hello:say_hello
    ''',
)
```
Everywhere you see `hello`, substitute the name of your module but omit the `.py` extension. Where you see `say_hello`, substitute the name of your function.
Then, run `pip install --editable` to make your command available to the command line.
You can now call your command like this:
```
$ hello --name='Jeff'
Hello Jeff!
```
By packaging your command, you omit the extra step in the console of having to type `python hello.py --name='Jeff'` and save yourself several keystrokes. These instructions will probably also work for the other libraries we mentioned.
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/5/3-python-command-line-tools
作者:[Jeff Triplett][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/laceynwilliams
[1]:https://opensource.com/users/laceynwilliams
[2]:https://git-scm.com/
[3]:https://curl.haxx.se/
[4]:http://click.pocoo.org/5/
[5]:http://click.pocoo.org/5/commands/
[6]:https://github.com/GaretJax/django-click
[7]:http://click.pocoo.org/5/options/
[8]:http://click.pocoo.org/5/arguments/
[9]:http://docopt.org/
[10]:https://github.com/docopt/docopt#usage-pattern-format
[11]:https://github.com/google/python-fire
[12]:https://github.com/google/python-fire/blob/master/docs/guide.md
[13]:https://github.com/google/python-fire/blob/master/docs/guide.md#exposing-multiple-commands
[14]:https://github.com/google/python-fire/blob/master/docs/guide.md#version-3-firefireobject
[15]:https://github.com/google/python-fire/blob/master/docs/guide.md#grouping-commands
[16]:http://click.pocoo.org/5/setuptools/

View File

@ -1,87 +0,0 @@
translating---geekpi
Stop merging your pull requests manually
======
![](https://julien.danjou.info/content/images/2018/06/github-branching.png)
If there's something that I hate, it's doing things manually when I know I could automate them. Am I alone in this situation? I doubt so.
Nevertheless, every day, they are thousands of developers using [GitHub][1] that are doing the same thing over and over again: they click on this button:
![Screen-Shot-2018-06-19-at-18.12.39][2]
This does not make any sense.
Don't get me wrong. It makes sense to merge pull requests. It just does not make sense that someone has to push this damn button every time.
It does not make any sense because every development team in the world has a known list of pre-requisite before they merge a pull request. Those requirements are almost always the same, and it's something along those lines:
* Is the test suite passing?
* Is the documentation up to date?
* Does this follow our code style guideline?
* Have N developers reviewed this?
As this list gets longer, the merging process becomes more error-prone. "Oops, John just clicked on the merge button while there were not enough developer that reviewed the patch." Rings a bell?
In my team, we're like every team out there. We know what our criteria to merge some code into our repository are. That's why we set up a continuous integration system that runs our test suite each time somebody creates a pull request. We also require the code to be reviewed by 2 members of the team before it's approbated.
When those conditions are all set, I want the code to be merged.
Without clicking a single button.
That's exactly how [Mergify][3] started.
![github-branching-1][4]
[Mergify][3] is a service that pushes that merge button for you. You define rules in the `.mergify.yml` file of your repository, and when the rules are satisfied, Mergify merges the pull request.
No need to press any button.
Take a random pull request, like this one:
![Screen-Shot-2018-06-20-at-17.12.11][5]
This comes from a small project that does not have a lot of continuous integration services set up, just Travis. In this pull request, everything's green: one of the owners reviewed the code, and the tests are passing. Therefore, the code should be already merged: but it's there, hanging, chilling, waiting for someone to push that merge button. Someday.
With [Mergify][3] enabled, you'd just have to put this `.mergify.yml` a the root of the repository:
```
rules:
default:
protection:
required_status_checks:
contexts:
- continuous-integration/travis-ci
required_pull_request_reviews:
required_approving_review_count: 1
```
With such a configuration, [Mergify][3] enables the desired restrictions, i.e., Travis passes, and at least one project member reviewed the code. As soon as those conditions are positive, the pull request is automatically merged.
We built [Mergify][3] as a **free service for open-source projects**. The [engine powering the service][6] is also open-source.
Now go [check it out][3] and stop letting those pull requests hang out one second more. Merge them!
If you have any question, feel free to ask us or write a comment below! And stay tuned — as Mergify offers a few other features that I can't wait to talk about!
--------------------------------------------------------------------------------
via: https://julien.danjou.info/stop-merging-your-pull-request-manually/
作者:[Julien Danjou][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://julien.danjou.info/author/jd/
[1]:https://github.com
[2]:https://julien.danjou.info/content/images/2018/06/Screen-Shot-2018-06-19-at-18.12.39.png
[3]:https://mergify.io
[4]:https://julien.danjou.info/content/images/2018/06/github-branching-1.png
[5]:https://julien.danjou.info/content/images/2018/06/Screen-Shot-2018-06-20-at-17.12.11.png
[6]:https://github.com/mergifyio/mergify-engine

View File

@ -1,3 +1,6 @@
translating---geekpi
Sosreport A Tool To Collect System Logs And Diagnostic Information
======

View File

@ -1,90 +0,0 @@
如何记录你在终端中执行的所有操作
======
![](https://www.ostechnix.com/wp-content/uploads/2017/03/Record-Everything-You-Do-In-Terminal-720x340.png)
几天前,我们发布了一个解释如何[**保存终端中的命令并按需使用**][1]的指南。对于那些不想记忆冗长的 Linux 命令的人来说,这非常有用。今天,在本指南中,我们将看到如何使用 **script**命令记录你在终端中执行的所有操作。你可能已经在终端中运行了一个命令或创建了一个目录或者安装了一个程序。script 命令会保存你在终端中执行的任何操作。如果你想知道你几小时或几天前做了什么,那么你可以查看它们。我知道我知道,我们可以使用上/下箭头或 history 命令查看以前运行的命令。但是你无法查看这些命令的输出。但是script 命令记录并显示完整的终端会话活动。
script 命令会在终端中创建你所做的所有事件的 typescript。无论你是安装程序创建目录/文件还是删除文件夹,一切都会被记录下来,包括命令和相应的输出。这个命令读对那些想要一份交互式会话拷贝作为作业证明的人有用。无论莫是学生还是导师,你都可以将所有在终端中执行的操作和所有输出复制一份。
### 在Linux中使用 script 命令记录终端中的所有内容
script 命令预先安装在大多数现代 Linux 操作系统上。所以,我们不用担心安装。
让我们继续看看如何实时使用它
运行以下命令启动终端会话记录。
```
$ script -a my_terminal_activities
```
其中,**-a** 标志用于将输出追加到文件或 typescript并保留以前的内容。上述命令会记录你在终端中执行的所有操作并将输出追加到名为 **my_terminal_activities** 的文件中,并将其保存在当前工作目录中。
示例输出:
```
Script started, file is my_terminal_activities
```
现在,在终端中运行一些随机的 Linux 命令。
```
$ mkdir ostechnix
$ cd ostechnix/
$ touch hello_world.txt
$ cd ..
$ uname -r
```
运行所有命令后,使用以下命令结束 script 命令的会话:
```
$ exit
```
**示例输出:**
```
exit
Script done, file is my_terminal_activities
```
如你所见,终端活动已存储在名为 **my_terminal_activities** 的文件中,并将其保存在当前工作目录中。
要查看你的终端活动,只需在任何编辑器中打开此文件,或者使用 cat 命令直接显示它。
```
$ cat my_terminal_activities
```
**示例输出:**
正如你在上面的输出中看到的script 命令记录了我所有的终端活动,包括 script 命令的开始和结束时间。真棒,不是吗?使用 script 命令的原因不仅仅是记录命令,还有命令的输出。简单地说,脚本命令将记录你在终端上执行的所有操作。
### 结论
就像我说的那样,脚本命令对于想要保留其终端活动记录的学生,教师和 Linux 用户非常有用。尽管有很多 CLI 和 GUI 可用来执行此操作,但 script 命令是记录终端会话活动的最简单快捷的方式。
就是这些。希望这有帮助。如果你发现本指南有用,请在你的社交,专业网络上分享,并**支持 OSTechNix**。
干杯!
--------------------------------------------------------------------------------
via: https://www.ostechnix.com/record-everything-terminal/
作者:[SK][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://www.ostechnix.com/author/sk/
[1]:https://www.ostechnix.com/save-commands-terminal-use-demand/

View File

@ -0,0 +1,196 @@
3个 Python 命令行工具
======
![](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc-lead-tool-box.png?itok=NrJYb417)
这篇文章是与 [Lacey Williams Hensche][1] 共同撰写的。
有时对于某项工作来说一个命令行工具就足以胜任。命令行工具是一个交互程序,类似你的 shell 或者终端。[Git][2] 和 [Curl][3] 就是两个你也许已经很熟悉的命令行工具。
当你有一小段代码需要在一行中执行多次或者经常性地被执行命令行工具会很实用。Django 开发者执行 `./manage.py runserver` 命令来启动他们的网络服务器Docker 开发者执行 `docker-compose up` 来启动他们的容器。你想要写一个命令行工具的原因可能和你一开始想写代码的原因有很大不同。
对于这个月的 Python 专栏,我们有 3 个库想介绍给希望为自己编写命令行工具的 Python 使用者。
### Click
[Click][4] 是我们最爱的用来开发命令行工具的 Python 包。其:
* 有一个富含例子的出色文档
* 包含说明如何将命令行工具打包成一个更加易于执行的 Python 应用程序
* 自动生成实用的帮助文本
* 使你能够叠加使用可选和必要参数,甚至是 [多个命令][5]
* 有一个 Django 版本( [`django-click`][6] )来编写管理命令
Click 使用 `@click.command()` 去声明一个函数作为命令,同时可以指定必要和可选参数。
```
# hello.py
import click
@click.command()
@click.option('--name', default='', help='Your name')
def say_hello(name):
    click.echo("Hello {}!".format(name))
if __name__ == '__main__':
    hello()
```
`@click.option()` 修饰器声明了一个 [可选参数][7] 并且 `@click.argument()` 修饰器声明了一个 [必要参数][8]。你可以通过叠加修饰器来组合可选和必要参数。`echo()` 方法将结果打印到控制台。
```
$ python hello.py --name='Lacey'
Hello Lacey!
```
### Docopt
[Docopt][9] 是一个命令行工具解析器,类似于命令行工具的 Markdown。如果你喜欢流畅地编写应用文档在本文推荐的库中 Docopt 有着最好的格式化帮助文本。它不是我们最爱的命令行工具开发包的原因是它的文档犹如把人扔进深渊,使你开始使用时会有一些小困难。然而,它仍是一个轻量级广受欢迎的库,特别是当一个漂亮的说明文档对你来说很重要的时候。
Docopt 对于如何格式化文章开头的 docstring 是很特别的。在工具名称后面的 docsring 中顶部元素必须是“Usage:”并且需要列出你希望命令被调用的方式比如自身调用使用参数等等。Usage 需要包含 **help****version** 标记。
docstring 中的第二个元素是“Options:”对于在“Usages:”中提及的可选项和参数,它应当提供更多的信息。你的 docstring 的内容变成了你帮助文本的内容。
```
"""HELLO CLI
Usage:
    hello.py
    hello.py <name>
    hello.py -h|--help
    hello.py -v|--version
Options:
    <name>  Optional name argument.
    -h --help  Show this screen.
    -v --version  Show version.
"""
from docopt import docopt
def say_hello(name):
    return("Hello {}!".format(name))
if __name__ == '__main__':
    arguments = docopt(__doc__, version='DEMO 1.0')
    if arguments['<name>']:
        print(say_hello(arguments['<name>']))
    else:
        print(arguments)
```
在最基本的层面Docopt 被设计用来返回你的参数键值对。如果我不指定名字调用上面的命令,我会得到一个字典的返回:
```
$ python hello.py
{'--help': False,
 '--version': False,
 '<name>': None}
```
这里可看到我没有输入 `help``version` 标记并且 `name` 参数是 `None`
但是如果我带着一个 name 参数调用,`say_hello` 函数就会执行了。
```
$ python hello.py Jeff
Hello Jeff!
```
Docopt 允许同时制定必要和可选参数,且各自有着不同的语法约定。必要参数需要在 `ALLCAPS``<carets>` 中展示,而可选参数需要单双横杠显示,就像‘--like。更多内容可以阅读 Docopt 有关 [patterns][10] 的文档。
### Fire
[Fire][11] 是谷歌的一个命令行工具开发库。尤其令人喜欢的是当你的命令需要更多复杂参数或者处理 Python 对象时,它会聪明地尝试解析你的参数类型。
Fire 的 [文档][12] 包括了海量的样例但是我希望这些文档能被更好地组织。Fire 能够处理 [同一个文件中的多条命令][13]、使用 [对象][14] 的方法作为命令和 [组][15] 命令。
它的弱点在于输出到控制台的文档。命令行中的 docstring 不会出现在帮助文本中,并且帮助文本也不一定标识出参数。
```
import fire
def say_hello(name=''):
    return 'Hello {}!'.format(name)
if __name__ == '__main__':
  fire.Fire()
```
参数是必要还是可选取决于你是否在函数或者方法定义中为其指定了一个默认值。要调用命令,你必须指定文件名和函数名,比较类似 Click 的语法:
```
$ python hello.py say_hello Rikki
Hello Rikki!
```
你还可以像标记一样传参,比如 `--name=Rikki`
### 额外奖赏:打包!
Click 包含了使用 `setuptools` [打包][16] 命令行工具的使用说明(强烈推荐按照说明操作)。
要打包我们第一个例子中的命令行工具,将以下内容加到你的 `setup.py` 文件里:
```
from setuptools import setup
setup(
    name='hello',
    version='0.1',
    py_modules=['hello'],
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        hello=hello:say_hello
    ''',
)
```
任何你看见 `hello` 的地方,使用你自己的模块名称替换掉,但是要记得忽略`.py` 后缀名。将 `say_hello` 替换成你的函数名称。
然后,执行 `pip install --editable` 来使你的命令在命令行中可用。
现在你可以调用你的命令,就像这样:
```
$ hello --name='Jeff'
Hello Jeff!
```
通过打包你的命令,你可以省掉在控制台键入 `python hello.py --name='Jeff'` 这种额外的步骤以减少键盘敲击。这些指令也很可能可在我们提到的其他库中使用。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/5/3-python-command-line-tools
作者:[Jeff Triplett][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[hoppipolla-](https://github.com/hoppipolla-)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://opensource.com/users/laceynwilliams
[1]:https://opensource.com/users/laceynwilliams
[2]:https://git-scm.com/
[3]:https://curl.haxx.se/
[4]:http://click.pocoo.org/5/
[5]:http://click.pocoo.org/5/commands/
[6]:https://github.com/GaretJax/django-click
[7]:http://click.pocoo.org/5/options/
[8]:http://click.pocoo.org/5/arguments/
[9]:http://docopt.org/
[10]:https://github.com/docopt/docopt#usage-pattern-format
[11]:https://github.com/google/python-fire
[12]:https://github.com/google/python-fire/blob/master/docs/guide.md
[13]:https://github.com/google/python-fire/blob/master/docs/guide.md#exposing-multiple-commands
[14]:https://github.com/google/python-fire/blob/master/docs/guide.md#version-3-firefireobject
[15]:https://github.com/google/python-fire/blob/master/docs/guide.md#grouping-commands
[16]:http://click.pocoo.org/5/setuptools/

View File

@ -0,0 +1,85 @@
停止手动合并你的 pull 请求
======
![](https://julien.danjou.info/content/images/2018/06/github-branching.png)
如果有什么我讨厌的东西,那就是当我知道我可以自动化它们时,但我手动进行了操作。只有我有这种情况么?我很怀疑。
尽管如此,他们每天都有数千名使用 [GitHub][1] 的开发人员一遍又一遍地做同样的事情:他们点击这个按钮:
![Screen-Shot-2018-06-19-at-18.12.39][2]
这没有任何意义。
不要误解我的意思。合并 pull 请求是有意义的。只是每次点击这个该死的按钮是没有意义的。
这样做没有意义因为世界上的每个开发团队在合并 pull 请求之前都有一个已知的先决条件列表。这些要求几乎总是相同的,而且这些要求也是如此:
* 是否通过测试?
* 文档是否更新了?
* 这是否遵循我们的代码风格指南?
* 是否有 N 位开发人员对此进行审查?
随着此列表变长,合并过程变得更容易出错。 “糟糕John 点了合并按钮,但没有足够的开发人员审查补丁。” 要发出警报么?
在我的团队中,我们就像外面的每一支队伍。我们知道我们将一些代码合并到我们仓库的标准是什么。这就是为什么我们建立一个持续集成系统,每次有人创建一个 pull 请求时运行我们的测试。我们还要求代码在获得批准之前由团队的 2 名成员进行审查。
当这些条件全部设定好时,我希望代码被合并。
而不用点击一个按钮。
这正是启动 [Mergify][3] 的原因。
![github-branching-1][4]
[Mergify][3] 是一个为你按下合并按钮的服务。你可以在仓库的 .mergify.yml 中定义规则当规则满足时Mergify 将合并该请求。
无需按任何按钮。
随机抽取一个请求,就像这样:
![Screen-Shot-2018-06-20-at-17.12.11][5]
这来自一个小型项目,没有很多持续集成服务,只有 Travis。在这个 pull 请求中,一切都是绿色的:其中一个所有者审查了代码,并且测试通过。因此,该代码应该被合并:但是它还在那里挂起这,等待某人有一天按下合并按钮。
使用 [Mergify][3] 后,你只需将 `.mergify.yml` 放在仓库的根目录即可:
```
rules:
default:
protection:
required_status_checks:
contexts:
- continuous-integration/travis-ci
required_pull_request_reviews:
required_approving_review_count: 1
```
通过这样的配置,[Mergify][3] 可以实现所需的限制,即 Travis 通过并且至少有一个项目成员审阅了代码。只要这些条件是肯定的pull 请求就会自动合并。
我们为将 [Mergify][3] **在开源项目中作为一个免费服务**。[提供服务的引擎][6]也是开源的。
现在去[尝试它][3],并停止让这些 pull 请求挂起一秒钟。合并它们!
如果你有任何问题,请随时在下面向我们提问或写下评论!并且敬请期待 - 因为 Mergify 还提供了其他一些我迫不及待想要介绍的功能!
--------------------------------------------------------------------------------
via: https://julien.danjou.info/stop-merging-your-pull-request-manually/
作者:[Julien Danjou][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://julien.danjou.info/author/jd/
[1]:https://github.com
[2]:https://julien.danjou.info/content/images/2018/06/Screen-Shot-2018-06-19-at-18.12.39.png
[3]:https://mergify.io
[4]:https://julien.danjou.info/content/images/2018/06/github-branching-1.png
[5]:https://julien.danjou.info/content/images/2018/06/Screen-Shot-2018-06-20-at-17.12.11.png
[6]:https://github.com/mergifyio/mergify-engine

View File

@ -1,76 +0,0 @@
协同编辑器的历史性发明
======
不妨按时间顺序快速列出在主要协同编辑器上付出的努力。
正如任何如此的清单一样,它必定会在一开始便提到受人尊敬的所有编辑器的先祖,道格·恩格尔巴特描述了在那期间什么基本是 1968 年来所写的所有可能软件的详尽清单。这不仅包括协同编辑器,还包括图形、编程和数学编辑器。
那个示范之后的所有编辑器仅仅是为了弥补硬件发展的加速度的更缓慢的实现。
> 软件加快的速度比硬件加快的速度慢。——沃斯定律
因此没有进一步的麻烦的话,这里是我找到的可圈可点的协同编辑器的清单。我说“可圈可点”的意思是他们具有可圈可点的特征或者实现细节。
| 项目 | 日期 | 平台 | 说明 |
| --- | --- | --- | --- |
| [SubEthaEdit][1] | 2003-2015? | 仅 Mac|首次协同, 实时的, 我能找到的多指针编辑器, [在 Emacs 上的逆向工程的尝试。][2] |
| [DocSynch][3] | 2004-2007 | ? | 在互联网交互式聊天程序之上构造! [(!)](https://anarc.at/smileys/idea.png)|
| [Gobby][4] | 2005 至今 | C, 多平台 | 首次开放,实现稳固可靠。 仍然存在!众所周知 ("[libinfinoted][5]") 协议很难移植到其他编辑器中 (例如: [Rudel][6] 不能在 Emacs 上实现此协议。 2017 年 1 月发行的 0.7 版本添加了也许可以改善这种状况的 Python 捆绑。 有趣的插件: 自动保存到磁盘。|
| [moonedit][7] | 2005-2008? | ? | 原网站已关闭。其他用户的光标可见并且会模仿击键的声音。 计算器和音乐定序器。 |
| [synchroedit][8] | 2006-2007 | ? |首款网络应用。|
| [Etherpad][9] | 2008 至今 | 网络 |首款稳定的网络应用。 最初在 2008 年被开发为一款大型 Java 应用,在 2009 年被谷歌获取并开源,然后在 2011 年被用 Node.JS 重写。广泛使用。|
| [CRDT][10] | 2011 | 特定平台| 对在不同电脑间可靠地复制一个文件的数据结构是标准的。 |
| [Operational transform][11] | 2013 | 特定平台| 与 CRDT 类似, 然而, 确切地说, 两者是不同的。 |
| [Floobits][12] | 2013 至今 | ? | 对不同编辑器是商业的但开源的插件。 |
| [HackMD][13] | 2015 至今| ? | 商业的但是[开源][14]。受 hackpad 的启发( hackpad 已被 Dropbox 收购)。 |
| [Cryptpad][15] | 2016 至今 | 网络? |Xwiki 的副产品。加密的, 在服务器"零知识"。|
| [Prosemirror][16] | 2016 至今 | 网络, Node.JS | "试图架起 Markdown 文本编辑和 传统 WYSIWYG 编辑器之间隔阂的桥梁。"不是完全意义上的编辑器,但是一种可以用来构建编辑器的工具。 |
| [Qill][17] | 2013 至今 | 网络, Node.JS | 富文本编辑器,同时支持 JavaScript.不确定是否是协同式的。 |
| [Nextcloud][18] | 2017 至今 | Web |一种类似谷歌文档的文档。 |
| [Teletype][19] | 2017 至今 | WebRTC, Node.JS | 为 GitHub 的[ Atom 编辑器][20] 引入了 "可移植"的想法,这种想法使访客可以跟踪主人在对多个文档做什么.访问介绍服务器后使用实时通讯的点对点技术( P2P ),基于 CRDT. |
| [Tandem][21] | 2018 至今 | Node.JS? | Atom, Vim, Neovim, Sublime 等的插件。 使用中继安装基于 CRDT 的 P2P 连接。多亏 Debian 开发者的参与,[可疑证书问题][22]已被解决,这使它成为很有希望在未来被遵循的标准。 |
### 其他清单
* Emacs 维基
* 维基百科
--------------------------------------------------------------------------------
via: https://anarc.at/blog/2018-06-26-collaborative-editors-history/
作者:[Anacr][a]
选题:[lujun9972](https://github.com/lujun9972)
译者:[ZenMoore](https://github.com/ZenMoore)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://anarc.at
[1]:https://www.codingmonkeys.de/subethaedit/
[2]:https://www.emacswiki.org/emacs/SubEthaEmacs
[3]:http://docsynch.sourceforge.net/
[4]:https://gobby.github.io/
[5]:http://infinote.0x539.de/libinfinity/API/libinfinity/
[6]:https://www.emacswiki.org/emacs/Rudel
[7]:https://web.archive.org/web/20060423192346/http://www.moonedit.com:80/
[8]:http://www.synchroedit.com/
[9]:http://etherpad.org/
[10]:https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type
[11]:http://operational-transformation.github.io/
[12]:https://floobits.com/
[13]:https://hackmd.io/
[14]:https://github.com/hackmdio/hackmd
[15]:https://cryptpad.fr/
[16]:https://prosemirror.net/
[17]:https://quilljs.com/
[18]:https://nextcloud.com/collaboraonline/
[19]:https://teletype.atom.io/
[20]:https://atom.io
[21]:http://typeintandem.com/
[22]:https://github.com/typeintandem/tandem/issues/131
[23]:https://www.emacswiki.org/emacs/CollaborativeEditing
[24]:https://en.wikipedia.org/wiki/Collaborative_real-time_editor
[25]:https://en.wikipedia.org/wiki/The_Mother_of_All_Demos
[26]:https://en.wikipedia.org/wiki/Douglas_Engelbart