在doom-emacs lounge 看到了eshell,https://www.reddit.com/r/emacs/comments/6y3q4k/yes_eshell_is_my_main_shell/ ambrevar给出了用eshell的理由。这点很重要:
It’s important to understand that shells are not (or should not be) semantically bound to terminal emulator restrictions.
可以用ivy代替fzf,更加方便编辑/搜索的buffer代替| awk
| grep
尝试适应这个,但几点比较难受的地方
eshell-previous-prompt
C-c C-p 无效。应该是因为设置了text properties的inhibit-line-move-field-capture
和field
的原因。我用了这个hack:
(with-eval-after-load 'em-prompt
(defun eshell-previous-prompt (n)
"Move to end of Nth previous prompt in the buffer.
See `eshell-prompt-regexp'."
(interactive "p")
(beginning-of-line) ; Don't count prompt on current line.
;; PATCH beginning-of-line does not move across the prompt
(backward-char)
(eshell-next-prompt (- n))))
不支持input redirection。支持pipe cat file | command
,input redirection也应该是能支持的。Emacs-general 里jgkamat | maybe I'll stop being lazy and actually put a weekend into it one day
有个想法,cooked mode应用程序可以从minibuffer读入stdin
补全。可以调用fish,比如这个包emacs-fish-completion 。
但它是用于pcomplete.el
的,补全选项出现在*Completions*
buffer中,不好看。可能还得再套一个company-pcomplete.el
。有些fish补全命令可能会卡,猜测可能会做些DNS查询之类的事,比如fish -c 'complete -C"rsync -"'
如果有个利用zsh completion,直接提供company的包就好了
另外求一些eshell配置,介绍点workflow等
我暂时抄+写了这些:
(defun +eshell/quit-or-delete-char (arg)
(interactive "p")
(if (and (eolp) (looking-back eshell-prompt-regexp nil))
(eshell-life-is-too-much)
(delete-char arg)))
;; PATCH no git
(defun +eshell-prompt ()
(concat (propertize (abbreviate-file-name (eshell/pwd)) 'face 'eshell-prompt)
(propertize " λ " 'face 'font-lock-constant-face)))
(defun eshell/l (&rest args) (eshell/ls "-l" args))
(defun eshell/e (file) (find-file file))
(defun eshell/md (dir) (eshell/mkdir dir) (eshell/cd dir))
(defun eshell/ft (&optional arg) (treemacs arg))
(defun eshell/up (&optional pattern)
(let ((p (locate-dominating-file
(f-parent default-directory)
(lambda (p)
(if pattern
(string-match-p pattern (f-base p))
t)))
))
(eshell/pushd p)))
;; PATCH counsel-esh-history
(defun my/ivy-eshell-history ()
(interactive)
(require 'em-hist)
(let* ((start-pos (save-excursion (eshell-bol) (point)))
(end-pos (point))
(input (buffer-substring-no-properties start-pos end-pos))
(command (ivy-read "Command: "
(delete-dups
(when (> (ring-size eshell-history-ring) 0)
(ring-elements eshell-history-ring)))
:initial-input input)))
(setf (buffer-substring start-pos end-pos) command)
(end-of-line)))
(defun my/eshell-init-keymap ()
(evil-define-key 'insert eshell-mode-map
(kbd "C-d") #'+eshell/quit-or-delete-char
(kbd "C-r") #'my/ivy-eshell-history
(kbd "C-p") #'eshell-previous-input
(kbd "C-n") #'eshell-next-input
(kbd "<tab>") (lambda () (interactive) (pcomplete-std-complete))
))
(add-hook 'eshell-first-time-mode-hook #'my/eshell-init-keymap)
8 个赞
我的主力Shell 一直是Eshell, 因为我的系统包括Windows/Linux/Mac, 我需要一个跨平台shell
資源:
Master Emacs 的master eshell
Reddit 上面關於的帖子
Youtube 的介紹
https://www.reddit.com/r/emacs/comments/6y3q4k/yes_eshell_is_my_main_shell/
https://www.reddit.com/r/emacs/comments/5qh2sd/using_emacs_27_shell_and_eshell/
插件:
我的配置:
;;; package --- Summary -*- lexical-binding: t; -*-
;;; code:
;;; Commentary:
;;; https://www.emacswiki.org/emacs/EshellFunctions
(defun ramsay/eshell-maybe-bol ()
"Go to the beginning of command line,or begining of line."
(interactive)
(let ((p (point)))
(eshell-bol)
(if (= p (point))
(beginning-of-line))))
(defun eshell/unpack (file &rest args)
"Unpack FILE with ARGS using default command."
(let ((command (some (lambda (x)
(if (string-match-p (car x) file)
(cadr x)))
'((".*\.tar.bz2" "tar xjf")
(".*\.tar.gz" "tar xzf")
该文件已被截断。 显示原文
我之前发过关于Eshell 的帖子:
我的主力Shell 是Eshell, 但是平时我也会用Zsh, 而fzf 是一个非常好用的命令行工具,用了fzf 搜索命令:
[Peek 2017-12-16 10-29]
回到 Eshell 下面,我觉得我应该也能实现类似的功能的, 因为我用的是Ivy/Counsel, 用一个counsel-esh-history 命令支持使用Ivy来搜索历史命令,但是不能像fzf 那样可以从用户输入获取命令的一部分,然后再进行过滤匹配,所以我自己拿了counsel-esh-history 的源码来修改了一下,改成了fzf 那样:
[Peek 2017-12-16 10-30]
下面是源码:
(defun samray/esh-history ()
"Interactive search eshell history."
(interactive)
(require 'em-hist)
(save-excursion
(let* ((start-pos (eshell-bol))
(end-pos (point-at-eol))
(input (buff…
截图:
特性:
类似fish 的补全
与Emacs 的完美结合
跨平台
可以使用shell 或者lisp 的语法来编写eshell 脚本
具备主流shell(如bash) 大部分功能
不足:
不支持输入的重定向
对top 这些强交互命令支持不好
缺乏文档
话说,为什么有点链接没有实现缩略图详情的
补充:附加一些我自己日常的Eshell 玩法,之前回帖的时候没有想起来,现在用到又想起来了
在Eshell
执行着命令,例如ls/cd
等,然后突然想打开某个文件,可以直接在Eshell 使用Emacs 打开目录或者文件,而不需要再在编辑区使用 C-x C-f
打开文件。
比如我在Eshell
窗口 用 cargo new
命令新建了一个Rust 项目了,然后在另外一个打开这个目录/文件。
因为我经常用到dired-other-window
和 find-file-other-window
, 我就直接用shell 的形式建了alias:
alias fow "find-file-other-window $1"
alias dow "dired-other-window $1"
意义重大的是 :这样就可以将Emacs 的函数当作shell 命令来玩,使Eshell 的shell命令集数量大大增加. @MaskRay
再补充:
Eshell 虽说不支持输入重定向,但是Eshell 支持重定向到Emacs, 比如文件,缓冲区,甚至变量:
cat mylog.log >> #<buffer *scratch*>
4 个赞
哈哈,真爱生命,远离emacs terminal emulator。
Eshell 偶尔快速用 shell 或者 Windows 的时候用,和 Emacs 自身结合得挺好,但是总有一种性能有问题的感觉,简单用用没啥问题。Linux/Mac 下还是习惯用某个终端模拟器 + zsh。Emacs 自带的终端模拟器都不太行,像 Neovim,VSCode 之类的都自带很好的 terminal 了。现在 emacs-vterm 只处于“勉强可用”的状态,如果作者(或者其他人)能继续开发还是有希望的。
我平常在 macOS 下就是使用 VimR 的终端的,开个 Jupyter-console 使用体验(包含按键绑定)和 Terminal 应用中没区别。
Emacs 中 shell 的主要缺点是性能低下,对强交互命令支持不好。
前几天 讨论 Emacs 26 新增加的特性时 ,我注意到有个更新:eshell 支持 24 位真彩色啦。不过感觉并没有什么用,不太明白 Emacs 上游为啥不把精力投入到 libvte 上,就是死磕 eshell。
libvte 这个相对于 term 有什么优势吗?我看到好多人在说。。。
PS:如果用的是 Linux 并且对 窗口管理器感兴趣的话可以试试 exwm, 可以直接在 emacs 打开其他的终端如:gnome-terminal
根据这份 讨论 24 位真彩支持的 gist 描述:
有好几个新晋的、较受欢迎的终端模拟器,比如 sakura、xfce4-terminal、Terminator、Tilix……还有你提到的 gnome-terminal,都是基于 libvte 做的。哦,还有 neovim 内嵌终端也是基于 libvte 的。
相对 Emacs 的 term 主要优势是速度快吧,而且没有明显毛病。
奇怪,對於單個單詞的命令,如echo<point>
、ls<point>
,在point處回車一次無效,兩次才執行命令,關掉company-mode則修復。回車應該是被company-mode捕獲了
有个问题,我在 eshell 里开了一个 Ruby 的 irb,怎么在 irb 里使用 tab 补全?
LdBeth
2018 年3 月 26 日 03:34
10
因為一个是 shell,一个是 Term,完全两回事
你用过ansi-term吗?
~/.emacs
(defun bash (buffer-name)
(interactive (list (read-from-minibuffer "Buffer Name:"
nil nil nil nil nil)))
(ansi-term "/bin/bash" (if (string= "" buffer-name) nil buffer-name)))
然后M-x bash就可以了。我还通过这种方式emacs里面用过vim,还有sudo vim、sudo apt update之类suduoer命令。
参考Running Shells in Emacs .
Emacs 下的各种终端方案都试过了。eshell 和 ansi-term 是我偶尔还会用的。ansi-term 和 Neovim, Atom 和 VSCode 的 terminal 比起来差距很大(个人观感,包括兼容性和速度)。
1 个赞
我最近也迁移到eshell了。
补充一个:
(defun moon-validate-command ()
"Validate eshell command."
(save-excursion
(beginning-of-line)
(re-search-forward (format "%s\\([^ ]*\\)" eshell-prompt-regexp)
(line-end-position)
t)
(let ((beg (match-beginning 1))
(end (match-end 1))
(command (match-string 1)))
(put-text-property beg end
'face `(:foreground ,(if (executable-find command)
"#98C379"
"red"))))))
(add-hook 'eshell-mode-hook (lambda ()
"Add `moon-validate-command' to `post-command-hook'."
(add-hook 'post-command-hook #'moon-validate-command t t)))
另外counsel有一个counsel-switch-to-shell-buffer
,抄来改巴改巴就能用在eshell上:
(defun counsel-switch-to-eshell-buffer ()
"Switch to a shell buffer, or create one."
(interactive)
(ivy-read "Eshell buffer: " (counsel--buffers-with-mode #'eshell-mode)
:action #'counsel--switch-to-shell
:caller 'counsel-switch-to-shell-buffer))
配合我之前发帖提到的buffer名字同步pwd:
(defun eshell-sync-dir-buffer-name ()
"Change eshell buffer name by directory change."
(when (equal major-mode 'eshell-mode)
(rename-buffer (format "Esh: %s"
(propertize
(abbreviate-file-name default-directory)
'face `(:foreground ,lunary-pink)))
t)))
(add-hook 'eshell-directory-change-hook #'eshell-sync-dir-buffer-name)
(add-hook 'eshell-mode-hook #'eshell-sync-dir-buffer-name)
还有一个fish那种autosuggest好像没人提到:
5 个赞
ycz926
2018 年8 月 13 日 14:30
16
感觉eshell还好,在部署站点时,在新buffer的eshell里ssh上去,然后切换回原来的buffer继续写代码,不需要开新标签