锈❤️emacs
该项目不再维护。如果您正在寻找基于生锈的Emacs叉,可以看一下Emacs-NG。但是,该叉子不是要替换C代码库,而是要使用Rost Rust的生态系统提供其他功能。
由社区驱动的野生港口生锈的港口。
目录
为什么要emacs?
Emacs将改变您对编程的看法。
emacs是完全内省的。您总是可以找出“当我按下此按钮时运行什么代码?”。
Emacs是一个增量的编程环境。没有编辑编译运行周期。甚至没有编辑周期。您可以执行代码片段,并逐渐将它们变成完成的项目。您的编辑和解释器之间没有区别。
emacs是一个可变的环境。您可以通过建议设置变量,调整功能,或重新定义整个功能。没有什么是禁止的。
Emacs提供无需应用程序的功能。功能并没有将功能全部集成到您的emacs实例中。令人惊讶的是,这有效。是否曾经想使用相同的摘要工具来编写C ++类以及电子邮件?
Emacs充满了令人难以置信的软件概念,这些概念尚未成为主流。例如:
- 许多平台都有一个项目剪贴板。 Emacs有一个无限的剪贴板。
- 如果您取消更改,然后继续编辑,则无法重做原始更改。 Emacs允许撤消任何历史状态,甚至允许基于树的历史探索。
- EMACS支持反向变量搜索:您可以找到具有给定值的变量。
- 您可以执行代码的结构编辑,从而可以进行更改而无需打破语法。这适用于Lisps(Paredit)和非Lisps(SmartParens)。
- 许多应用程序都使用模态GUI:例如,在发现和重新安置操作期间,您无法进行其他编辑。 Emacs提供递归编辑,使您可以暂停您当前的工作,执行其他编辑,然后继续原始任务。
Emacs具有文档文化。 EMACS包括使用手册,LISP编程手册,Pervasive Docstrings,甚至是互动教程。
Emacs具有广泛的生态系统。如果您想用利基语言编辑代码,则可能有一个Emacs软件包。
Emacs对好主意没有垄断,还有其他出色的工具。尽管如此,我们认为Emacs学习曲线有回报。
为什么要生锈?
生锈是C的绝佳选择。
Rust具有出色的学习曲线。该文档非常出色,如果您陷入困境,社区将非常有帮助。
生锈具有出色的工具。编译器提出了很好的建议,单位测试框架很好,RustFMT有助于确保格式化优美和一致。
生锈的包装故事很棒。重复使用可用的出色库很容易,并且很容易将代码分解为他人的利益。我们可以用维护良好的Rust库中的EMAC中的整个C文件。
用生锈编写的代码很容易与c互操作。这意味着我们可以在过程的每个步骤中递增生锈,并在每个步骤中具有一个工作的emacs。
Rust提供了许多编译时间检查,从而使快速编写的代码(即使使用多线程)更容易。这也使新来者更容易做出贡献。
尝试一下。我们认为您会喜欢的。
为什么要叉?
Emacs是一种广泛使用的工具,具有悠久的历史,广泛的平台支持和强大的向后兼容性要求。可以理解的是,核心团队在做出深远的变化方面持谨慎态度。
在EMACS社区中,朝分叉是尝试不同方法的长期传统。著名的emacs叉子包括Xemacs,Guile Emacs和Emacs-jit。
也有单独的ELISP实现,例如Deuce,Jemacs和El Compilador。
通过分叉,我们可以探索新的发展方法。我们可以使用集成CI使用拉的请求工作流。
我们可以丢弃旧平台和编译器。 remacs永远不会在MS-DOS上运行,没关系。
Emacs的想法与EMAC的当前实施之间存在区别。分叉使我们能够探索更多的emacs-y。
入门
要求
-
您将需要安装生锈。文件Rust-Toolchain表示已安装的版本。这会自动发生,因此不要手动覆盖工具链。重要的是:每当工具链更新时,您都必须手动重新安装RustFMT。
-
您将需要C编译器和工具链。在Linux上,您可以做类似的事情:
apt install build-essential automake clang libclang-dev
在MacOS上,您需要Xcode。
-
Linux:
apt install texinfo libjpeg-dev libtiff-dev \\ libgif-dev libxpm-dev libgtk-3-dev gnutls-dev \\ libncurses5-dev libxml2-dev libxt-dev
macos:
brew install gnutls texinfo autoconf
要使用MakeInfo的已安装版本,而不是内置的(/usr/bin/makeinfo),您需要确保/usr/usr/local/opt/opt/texinfo/bin在路径中/usr/bin之前。 mojave install libxml2标头with:open/library/developer/commandlinetools/packages/macos_sdk_headers_for_for_macos_10.14.pkg
建立开发环境
如果您不想打扰上述设置,则可以使用提供的Docker环境。确保您有Docker 1.12+和Docker-Compose 1.8+可用。
旋转环境运行
docker-compose up -d
您第一次运行此命令时,Docker将构建图像。此后,任何后续的启动都将在不到一秒钟的时间内发生。如果此命令由于需要绝对路径而失败,请确保在调用命令之前设置PWD环境变量:
PWD= $( pwd ) docker-compose up -d
带有remacs的工作目录将安装在容器中的相同路径下,因此编辑主机机器上的文件将自动反映在容器中。要构建remacs ,请使用构建带有docker-compose exec remacs前缀的remacs的步骤,这将确保命令在容器内部执行。
建筑物remacs
$ ./autogen.sh $ ./configure --enable-rust-debug $ make
对于发布构建,请勿通过 – 可启用lust debug。
Makefile Obeys Cargo的Rustflags变量可以通过CARGO_FLAGS传递给货物。
例如:
$ make CARGO_FLAGS= \" -vv \" RUSTFLAGS= \" -Zunstable-options --cfg MARKER_DEBUG \"
运行remacs
您现在可以运行闪亮的新remacs !
remacs starts up quickly.
# RUST_BACKTRACE is optional, but useful if your instance crashes.
$ RUST_BACKTRACE=1 src/ remacs -q\”>
# Using -q to ignore your .emacs.d, so remacs starts up quickly. # RUST_BACKTRACE is optional, but useful if your instance crashes. $ RUST_BACKTRACE=1 src/ remacs -q
设计目标
兼容性: remacs不应破坏现有的ELISP代码,理想情况下也提供相同的FFI。
利用生锈本身: remacs应该充分利用Rust,以确保代码强大且性能。
利用Rust生态系统: remacs应尽可能使用现有的Rust板条箱,并在我们的代码中创建新的,单独的板条箱可以使他人受益。
伟大的文档:Emacs拥有出色的文档, remacs应该没有什么不同。
进步
在这一点上,我们专注于将LISP功能从C到Rust的移植。目前,Rust中有642个功能,C中有823个功能(2019年5月)。
我们在Wiki中有一个进度部分,并且项目中还有一系列长期目标列表。
移植ELISP原始功能
首先要看的是ATAN函数的C实现。它需要一个可选的第二个参数,这使它变得有趣。另一方面,复杂的数学位是由标准库处理的。这使我们可以专注于移植过程而不会因数学而分心。
我们给出的LISP值作为参数是标记的指针;在这种情况下,它们是要加倍的指针。代码必须检查标签并按照指针检索实际值。请注意,此代码调用C型宏(称为Defun),该宏可减少一些样板。宏声明一个称为撒旦的静态变量,该变量持有元数据,Lisp编译器将需要成功调用此功能,例如DocString和FATAN函数的指针,这是C实施的命名:
DEFUN ( \"atan\" , Fatan , Satan , 1 , 2 , 0 , doc : /* Return the inverse tangent of the arguments. If only one argument Y is given, return the inverse tangent of Y. If two arguments Y and X are given, return the inverse tangent of Y divided by X, i.e. the angle in radians between the vector (X, Y) and the x-axis. */ ) ( Lisp_Object y , Lisp_Object x ) { double d = extract_float ( y ); if ( NILP ( x )) d = atan ( d ); else { double d2 = extract_float ( x ); d = atan2 ( d , d2 ); } return make_float ( d ); }
extract_float检查标签(如果不是双重的标签,请发出“无效参数”错误),并返回实际值。 NILP检查标签是否表示这是一个无效的值,这表明用户根本没有提供第二个参数。
接下来,看看当前的生锈实现。它还必须采用一个可选的参数,并且还调用了一个(Rust)宏以减少声明该功能的静态数据的样板。但是,它还需要照顾我们需要进行的所有类型转换和检查,以处理参数并返回值:
/// Return the inverse tangent of the arguments. /// If only one argument Y is given, return the inverse tangent of Y. /// If two arguments Y and X are given, return the inverse tangent of Y /// divided by X, i.e. the angle in radians between the vector (X, Y) /// and the x-axis # [ lisp_fn ( min = \"1\" ) ] pub fn atan ( y : EmacsDouble , x : Option < EmacsDouble > ) -> EmacsDouble { match x { None => y . atan ( ) , Some ( x ) => y . atan2 ( x ) } }
您可以看到我们不必检查我们的参数是否是正确的类型,lisp_fn Macro生成的代码为我们做到了。我们还要求第二个参数为选项<emacsDouble>。这是一个有效双重或根本没有指定的值的生锈类型。我们使用匹配语句来处理这两种情况。
该代码要好得多,以至于很难相信宏的实现多么简单。它只是在参数和返回值上调用.into();当派遣此方法调用正确实现时,该编译器将完成其余的工作。
贡献
欢迎拉请请求,无需版权分配。该项目属于行为锈法。
有很多事情要做!我们在这里保留一份低悬挂水果的清单,以便您可以轻松选择一个。您可以在移植食谱中找到信息,或在我们的Gitter频道中寻求帮助。
