elvish 0.18 简易评测

oil 和 elvish 最大的区別: oil 从 bash 继承太多语法了,免不了 「一堆不明所以的字符命令」。

现在新用户都是用工具比如 pandoc 从 markdown 之类的生成 roff。几乎没人会写 troff 了。我不觉得这些人有多保守,只是单纯懶而已,

管道一直都可以传二进制,也一直都支持不连续的 stream,你用的是什么牌子的 unix?

懒是理所应当的,尤其是没人买单的时候。任何时候都要讲切换成本。成本/收益,否则公司要破产的。

你引用的话是我说明数据校验必要性的。不能指望一个程序接收任何数据,也不能指望它能满足所有场景。也不能所有应用搞标准化。

那个 find 的例子感觉是编程实践的问题,和管道基本无关。提供 -print0 参数对数据格式化,已经是满足兼容性并解决问题的挺好方案了。对常用场景输入输出标准化,我是支持的。

你只注意到 JSON,但这个只是一个副产品,

真正有意思点在 pipe 能传数据,也就是說,elvish 的 pipe 可以用来实现 FORTH 一样的 concatenative programming

从某种程度上,elvish 和 APL 有点像,利用 pipe 和各种 construct 不用 for loop 就能完成很多工作。

挺好。挺有意思的特性。

你这个第三点很有吸引力。我打算尝试一下 elvish as pl。

我之前调研过 Next Generation Shell,设计思想应该和 elvish 比较像。但是比起这种另起炉灶自己搞一套编程语言的 shell,我更喜欢 xonsh 这种,在兼容 POSIX shell / Bash 的基础上,用已有的编程语言(如 xonsh 用的是 Python)扩充表达能力的 shell。

P.S. 我最近业余时间正在开发一个库,使用 Tcl 作为 shell 的扩充编程语言,加上补全、历史等必要特性,并以 loadable builtin 的形式加载到 Bash、zsh 等现有 shell 解释器中。旨在尽可能不打破用户使用习惯和现有生态中插件、脚本兼容性的前提下,提升 shell 的使用效率和体验。之后会开源出来,和大家进一步讨论。

1 个赞

我搞不清楚 oil 和 xonsh 有啥区别。。

编程语言扩展的 shell 感觉都不怎么好。写 shell 的很多场景都是粗快。正经的编程语言很多都快不了,比如所有的调用都需要 () ,所有的字符串都得 “”。 数据流从左到右处理,管道的方式比较自然。试了下 elvish。感觉设计的很有想法,一眼就能看出作者做了很多思考。实时编译提示这点也很好,这下没有粗,只有快了。

ngs 和 xonsh 的设计都缺少 elvish 寛广的眼界,还停留在命令式思維。

比如 xonsh 的 for loop 是抄 python 的

for filename in `.*`:
    print(filename)
    du -sh @(filename)

用 elvish 写就是 each {|f| print $f; du -sh $f} [.*],用 lisp 表示就是 (mapc (lambda (f) (print f) (du -sh f)) (collect ".*")),对习慣函数式思维的用户非常友好。

而 elvish 还有 each 命令的变种 peach,能很方便地提供并行化。放以前还要用 GNU parallel 来实现这功能。

>> ~ $ peach { |x| sleep 1; put $x } [1 2 3 4 5]
▶ 4
▶ 1
▶ 2
▶ 5
▶ 3
>> ~ $ peach { |x| sleep 1; put $x } [1 2 3 4 5]
▶ 4
▶ 2
▶ 3
▶ 5
▶ 1

xonsh 就是 python3 ?

xonsh 就是 python3 加上 shell 相关的 DSL。

python 吧,只能说我是不太喜欢的,有得选我宁可 APL。

@fengche : 编程语言扩展的 shell 感觉都不怎么好。写 shell 的很多场景都是粗快。 正经的编程语言很多都快不了,比如所有的调用都需要 () ,所有的字符串都得 “”

是的,这就是为什么大多数通用编程语言的 REPL 都不适合作为 shell 使用。这也是 xonsh 令人诟病之处。Python 的语法设计或许更易读,但写起来(特别是作为 shell 写起来)并不顺手。

我最终选择了 Tcl 来做 shell 的扩展,正是因为它避开了传统的通用编程语言在 shell 场景下的诸多弊端。

首先是字符串字面量的问题。Tcl 的设计思想就是 everything is a string,任何一个对象,它首先一定是一个字符串,其次它才可以在解释器实现里有其他的内部表示来用作优化手段。这是符合人们使用 shell 的直觉和习惯的 。所以使用字符串的时候自然无需 quote(除非有 whitespace 等特殊字符)。这一点也是和 POSIX shell 高度一致的。

同时,Tcl 里的函数调用不是常见的 func1(func2(foo), func3(bar)) 这种写法,而是 func1 [func2 foo] [func3 bar],更像是没有最外层括号的 Lisp(当然这里有人会说 Tcl 的 list 和 Lisp 的 list 行为不一致,所以不能说 Tcl 像没有最外层括号的 Lisp,但讽刺的是,如果用纯函数式的写法,Tcl 的 list 和 Lisp 的 list 的行为几乎是完全一致的)。这样的写法,也符合人们使用 shell 的习惯。

@LdBeth : 用 elvish 写就是 each {|f| print $f; du -sh $f} [.*] , 用 lisp 表示就是 (mapc (lambda (f) (print f) (du -sh f)) (collect ".*")) , 对习慣函数式思维的用户非常友好。

用 Tcl 写是 foreach f [glob *] { puts $f; du -sh $f }。如果一定要满足“函数式思维”的话,可以写一个简单的 wrapper:

proc each {f l} {
    foreach i $l {
        apply $f $i
    }
}

然后就可以这样写了:each {f { puts $f; du -sh $f }} [glob *][1]

我选择 Tcl 作为 shell 的扩充语言,这也是原因之一。因为它在语法简单,对 shell 友好的同时,也能包容多种编程范式,满足不同人的思维习惯。

@LdBeth : 而 elvish 还有 each 命令的变种 peach ,能很方便地提供并行化。 放以前还要用 GNU parallel 来实现这功能。

并行化确实是一个有用的特性。好在 Tcl 原生线程安全,并有成熟的多线程库。实现类似的命令也是比较 trivial 的。


[1]: 需要把这里的 du 前加上 uplevel 2,或者改一下内置的 unknown 命令的实现,才能正常执行(原因参考 init.tcl 中 unknown 命令实现)。可见 Tcl 不能完全直接当作 shell 用。

1 个赞

https://wryun.github.io/es-shell/

有人关注过这个 shell 吗?他的特色是 a shell with higher-order functions

Es is an extensible Unix shell with first class functions, lexical scope, exceptions, and rich return values (i.e., functions can return values other than just numbers). Es’s extensibility comes from the ability to modify and extend the shell’s builtin services, such as path searching and redirection. Like the Plan 9 shell rc, it is great for both interactive use and for scripting, particularly since its quoting rules are much less baroque than the C or Bourne shells. – Paul Haahr

这些功能 elvish 都有。反而 plan9 的 shell 连䃼全都没有。

我今天意外把 mv dir ~/ 打成 rm dir ~/ 了,结果 elvish 配置没了,(幸好有 50GB 的无损音乐挡了下,另外就是 Wanderlust 配置没了,其它没什么损失,音乐也都有备份)。

想趁机換个 shell,先把 ksh 配起来用了。

2 个赞

给 rm 写个 alias :laughing:

啊,又见到推荐 elvish 的了。我记得我18年尝新过。 elvish 是托尔金创作的语言,见到以这个为名挺新奇的,用了一段时间。不过当时应该很初期?体验不好(另外还体验了 xonsh 一段时间,最终用回了 zsh。

所以我已经日常用 0.19 (beta 版)用了半年多,体会如下:

  1. namespace 是个不好的设计
  2. 䃼全多少有点难用
  3. 越像正经编程语言越不适合做 shell

目前决定用 mksh,从头自己写配置。

有没有试过 nushell 如何呢?虽然看起来很实验,但感觉挺有意思的

看到依赖一堆要200MB就不想试了

Scheme不错,但是语法对Parser友好,对人类却并不友好。我觉得可以基于Guile,设计一套对人类比较友好的DSL。