elvish 0.18 简易评测

可能是elvish的问题,我用mintty也是会闪,表现为一些字符好像被鼠标选中然后取消选中了的样子,mintty是对标xterm的

同一个 Windows Terminal 版本,我用 HEAD 和 0.19.2 都没问题。建议检查 Windows Terminal 的渲染设置。

多谢提醒,开了下面这个设置后,基本不会闪了,只有命令从红色变成绿色的时候会闪一下,还有长按Backspace 删除字符的时候会有点闪。总的来说,不影响使用了。 :+1:

这个问题估计是 elvish 在每个输入都重新绘制屏幕,检查用户输入的命令是否合法。

闪的问题应该是 Windows Terminal 的问题,Powershell 下在重新绘制屏幕时也是会闪的。

感觉Elvish有了下面这两个功能,就不大需要 autosuggetstions 了。

1 个赞

输入字符时在 Windows Terminal 会闪的问题,是 Terminal的原因,不是 Shell 的问题。

目前最新的 Windows Terminal Preview v1.18.1462 已经修复了。

Nushell 也有同样问题。

我用Window Terminal里面的 WSL Ubuntu 也出现了闪的情况。

换成预览版的 Windows Terminal, 一点都不闪 :smile:

写了一个GNU TeXmacs的Elvish插件:

现在只能执行单行的命令

我觉得这种 map func data 并不友好,同样是函数式编程,在Scala里面可以:

data.map(func)

我觉得这样更友好。倒装的写法,其实并不那么易读

@xiaq 能否考虑让 Elvish 有更友好的函数式编程的写法,你是否赞同Scala这种写法更易读易写?

然后Scheme的语法,会导致末尾有很多)))))))

Elvish 里可以用 pipeline 写成

put .* | each {|f| print $f; du -sh $f}
1 个赞

这里的 | 在实现上是使用了IO吧?

比较喜欢类似这样的语法,(这是我参考Scala的语法写的)

(put .*).foreach { f =>
  print $f
  du -sh $f
}

然后,沿用Elvish的既有的语法的话,我个人希望是这样的:

(put .*):each { |f|
  print $f
  du -sh $f
}

希望有这样的设计:

[ 1 2 3 4 ] : each { |f|
  echo $f
}

这里的 : 表示,each是可以作用在list上面的一个函数。

今天在公司Cat Talk这个环节,和同事探讨 Elvish

尝试写一个filter的实现:

fn filter {|pred l|
  var res = []
  for e $l {
    if ($pred $e) {
      set res = (conj $res $e)
    }
  }
  put $res
}

# filter {|x| > $x 3} [1 2 3 4 5 6]


each {|x|
  echo "rm -rf " $x
} (filter {|png_file|
  if ?(test -f $png_file) { put $true } else { put $false }
} [(each {|x|
  echo $x.elv
} [1 2 3 args each])])

感觉还是有一些罗嗦,我是指 [], {}, () 这些符号的组合。我的实现应该有不少地方还是可以优化一下的

按照我在上面的设计,我比较期望的语法是这样的:

[1 2 3 args each] : each { |x|
  put $x.png       # append `.png` to each element
} : filter { |x| 
  os.exists $x     # check if $E:PWD/$x exists 
} : each { |x|
  rm -rf $x           # remove the png files
}

另外反馈一个新手入门的问题:

反馈一个最近学习 Elvish 的坑点: https://elv.sh/ref/language.html

如果只看 Language Specification的话,会发现,想在一个列表中append一个元素,在文档(语言的标准)里面没有提供,然后需要跳转到内置函数里面去寻找对应的内置函数,比如conj

https://elv.sh/ref/builtin.html

然后这个页面的排序方式就是按字母排序(alphabet),找相关函数还是比较费劲的

put [1 2 3 args] | each $fn

就可以了

不需要关注这种实现细节, 因为语言设计者不想给你其他选择。

最主要的是,用 put 和 | 已经可以完成的事,还要再加操作只会影响正交性。

@xiaq 倒是要催一下 disown 的实现,从 elvish 用 & 开一个 emacs 结果关闭终端会把 emacs 杀掉很麻烦

@sadhen

有的 @LdBeth 也提到了……

Re #92| 用来传值用的是 Go channel,不通过文件 IO。| 的实现原则上可以完全抽象化,类似于 Clojure 的 seq。不过对于 Elvish 的应用场景来说,channel 带来的性能损失不重要。

Re #93:比较 idiomatic 的写法是 stream processing 就输出 stream of values,这样不需要用到 conj

fn filter {|pred @rest|
  each {|x|
    if ($pred $x) {
      put $x
    }
  } $@rest
}

put 1 5 6 2 | filter {|x| > $x 3}
filter {|x| > $x 3} [1 5 6 2]

Re #94:这个似乎没比现在 pipeline 的写法要短多少?

Reference 里面的东西对学习确实不是很友好。暂时没时间写教程……

@LdBeth bash -c 'emacs & disown $!' :slight_smile:

1 个赞

@aqua0210 命令变色的时候会闪是因为 Elvish 不缓存外部命令 lookup 的结果,然后 Windows 的 PATH 里面很容易有各种垃圾,然后 disk IO 也慢……把 PATH 清一下可能会快很多。

当然治本的办法还是引入缓存……

这个新的写法超赞!Elvish牛逼!

然后这个还是 Go Channel,从这个意义上,我觉得 Elvish 作为一门通用的脚本语言(类似于Lua),也是非常赞的。我有一位同事,他非常希望 Scala 能有 Goroutine,希望能有一门语言结合Go和Scala优点。

然后,我个人最近开始用 Elvish 之后,非常希望能实现一门类似于Lua的embedded script language,有一些内置的数据类型,然后语法尽可能和Scala保持一致。

PATH 清一下可能会快很多。

我写的Elvish脚本,第一句话就是:

set paths = [
   /path/to/1
   /path/to/2
]

能够低成本的得到一个干净的shell脚本执行环境,真的超赞!