最近正在琢磨 Emacs 里的终端怎么用比较好,这次更新太涨姿势了!
施工完成了!
官方文档靠后的一些章节实用性比较高,比如
- Dealing with Emacs Trouble
- Abbrevs
- Merging Files with Emerge
- Customizing VC
- Maintaining Large Programs
里面的内容也很充实,就是感觉文字有些多(看不动。。),需要个班长来给我们划重点,感觉楼主可以胜任。
学习了,不过 !$
按起来有点不太方便,!!
还可以接受。
记下了!
扫了一遍,发现只是蜻蜓点水了一下……
我搞了好久才发现char-mode用term-raw-map
,line-mode用term-mode-map
,之前怎么bind key都不对劲。
对的,实际上 line-mode 不通用,只使用 char-mode 就好了。
我感觉 term-line-mode
可以改造一下,或者抄一下做一个新的 mode,启用的时候把 term 变成一个只读的普通 buffer,这样就可以用普通的快捷键浏览和复制东西了。
这个与 tmux 的那个浏览模式很像,我觉得可以再加个 copy-mode。如果是用 evil 的话那这个就显得有点多余了
evil-normal-state的时候char-mode会阻止光标移出当前命令的编辑区,要用line-mode才行。
(general-define-key
:states '(insert emacs)
:keymaps 'term-raw-map
"<escape>" (lambda! (term-line-mode) (evil-motion-state)))
(general-define-key
:states '(normal motion)
:keymaps 'term-mode-map
"a" (lambda! (evil-insert-state) (term-char-mode)))
mumu 的视频在哪呢?
参照楼主的教学,写了一个简单的配置。亮点:
-
my-term
命令:和term
差不多,但不会在开启时要你选一下 shell 程序(还有一些细节,具体看代码)。 -
my-term-yank
:可以直接在 char mode 下粘贴文本,比如用来粘贴复制来的命令或者路径。 -
my-term-browse-mode
:把终端变成一个只读的、可以浏览的、键位和平时一样的 buffer,方便我们浏览一个很长的输出或者复制东西。
用法:把下面的代码复制到你的配置中,阅读并修改 “Example config" 部分。用 M-x my-term
启动终端。
(require 'term)
;;; term.el tweaks
(defvar my-term-escape-keys
'("M-x")
"Escape keys for `my-term'.
Notice that if you enable minor modes in the term, keys defined
by them override `term-raw-map', so they also behave like they
are escaped.")
(defun my-term-remove-escape-char ()
"Undo changed by `term-set-escape-char'."
(when term-escape-char
(define-key term-raw-map term-escape-char 'term-send-raw)
(setq term-escape-char nil)))
(defun my-term-setup-escape-keys ()
"Set keys in `my-term-escape-keys' as escape chars in term."
(dolist (key my-term-escape-keys)
(define-key term-raw-map (kbd key) nil)))
(with-eval-after-load 'term
;; In term.el, `C-c' is explicitely escaped, in the top level scope, using
;; `term-set-escape-char'. It's a useless API because it undoes its previous
;; call, so you can't escape multiple chars (`ansi-term' works around it
;; using a hack). We undo it here because we have `my-term-escape-keys'
;; where you can specify more than 1 escaped keys.
(my-term-remove-escape-char)
(my-term-setup-escape-keys))
;;; `my-term' command
(defvar my-term-shell-program nil
"Shell program for `my-term'.
We need this because we may use a lightweight shell like dash for
inferior shell, but want bash/zsh for interactive shell.")
(defun my-term ()
"Start a terminal emulator in a new buffer.
This is like `term' but with several tweaks to make you happier."
(interactive)
(let ((prog (or my-term-shell-program
explicit-shell-file-name
(getenv "SHELL")
shell-file-name
(read-file-name "Shell executable: "
"/" nil t)))
(buf (generate-new-buffer "*term*")))
;; If the user calls `ansi-term' before, undo its call to
;; `term-set-escape-char'.
(when term-escape-char
(my-term-remove-escape-char)
(my-term-setup-escape-keys))
(with-current-buffer buf
(term-mode)
(term-exec buf (buffer-name) prog nil nil)
(term-char-mode))
(pop-to-buffer buf)))
;;; Helpers
(defvar my-term-browse-mode-map
(make-sparse-keymap)
"Keymap for `my-term-browse-mode'.")
(defun my-term-browse-mode ()
"Turn the terminal buffer into a read-only normal buffer."
(interactive)
;; Workaround: Without this code, there's a bug: Press `C-p' in char mode to
;; browse history, then `C-n' to go back, then `my-term-browse-mode', then
;; `C-n', you'll find a newline is produced. Call `term-char-mode', that
;; newline is sent to the shell. This is not a problem with
;; `my-term-browse-mode', since `term-line-mode' also has it.
(let ((inhibit-read-only t))
(save-excursion
(goto-char (point-max))
(while (eq (char-before) ?\n)
(delete-char -1))))
;; Idea: We could put a `read-only' property to the region before
;; `process-mark', so current input could be edited, but I think there's
;; little benefit.
(setq buffer-read-only t)
(remove-hook 'pre-command-hook #'term-set-goto-process-mark t)
(remove-hook 'post-command-hook #'term-goto-process-mark-maybe t)
(use-local-map my-term-browse-mode-map))
(defun my-term-yank ()
"Paste recent kill into terminal, in char mode."
(interactive)
(when-let ((text (current-kill 0))
;; Remove newlines at the beginning/end.))
(text (string-trim text "\n+" "\n+")))
(when (or (not (string-match-p "\n" text))
(y-or-n-p "You are pasting a multiline string. Continue? "))
(term-send-raw-string text))))
;;; Example config
;; Set this to your shell program, or delete this if you just want to use the
;; inferior (reads "default") shell.
(setq my-term-shell-program "/bin/bash")
;; Keys you don't want them to be captured by the terminal.
(setq my-term-escape-keys '("C-c" "C-x" "M-x"))
;; Call this after you set `my-term-escape-keys'
(my-term-setup-escape-keys)
;; Bind keys to use in char mode. Make sure you have the prefix key (`C-c' in
;; this example) in `my-term-escape-keys'.
(define-key term-raw-map (kbd "C-c b") 'my-term-browse-mode)
(define-key term-raw-map (kbd "C-M-v") 'my-term-yank)
;; Bind keys to use in browse mode.
(define-key my-term-browse-mode-map (kbd "C-c b") 'term-char-mode)
实际录到一半不想录了)
在 evil-collection 里也有个类似的实现,可以看一下
这个 my-term
是不是可以直接这样调用 (ansi-term my-term-shell-program)
就好了?或者直接用 shell-file-name
这个变量。
term.el
实际是有提供一个 paste 函数的 term-paste
,似乎不用再自己写 my-term-yank
了。原来my-term-yank
考虑了多行的情况)
在 evil-collection 里也有个类似的实现
我看到它是切换 char mode 和 line mode。我不想要 line mode,因为那个会用 term-mode-map
,按回车还是发送命令。我只想要一个普通的只读 buffer,所以写了 my-term-browse-mode
。
这个
my-term
是不是可以直接这样调用(ansi-term my-term-shell-program)
就好了?
是可以。写这个主要的原因是 term.el
自己 call 了一次 term-set-escape-char
, ansi-term
自己又会 call 一次,然后把 C-x
和 C-c
都 escape 了。我不想要它把 C-c
也 escape 掉,所以做了一些 hack,这样在 my-term-escape-keys
一处把想要 escape 的键位都设置好就行了。不纠结这个的话可以不用这个命令。
或者直接用
shell-file-name
这个变量。
我考虑的情况是 inferior shell 应该主要做非交互式使用。比如说有人可能希望 shell-command
之类的函数交给 dash
,交互式的用 bash
,所以提供了 my-term-shell-program
这个变量。
term.el
实际是有提供一个 paste 函数的term-paste
,似乎不用再自己写my-term-yank
了。
哈,我原来不知道,不过反正我写的比那个好用
请问一下,ispell/aspell 哪个命令是将生词加入个人词库的?
因为ispell-personal-dictionary
对应的文件格式是纯文本,所以可以直接编辑。
但是通常我是先通过 flyspell/ispell-region
发现哪里的单词有问题,然后再在那个单词上 M-x ispell-word (evil
用户的话直接按 zm) 然后按i
将单词插入至个人词典里的。可以 C-h f ispell-help 查看一下它完整功能。
感谢,根据你的指导搞定了。ispell-word
接 i
好用。不是很喜欢flyspell
弹窗的用法。Emacs 还是不弹窗比较好,除了 company
project.el
内置的project管理,在master branch里有很多改进.对我来说比projectile还爽一点
比如有project-switch-project
,可以通过completing-read
来像图一样操作,
还有project-display-buffer
等函数,对buffer的操作也不赖.
一个缺点就是不能和projectile一样根据cmake或者bazel等项目类型直接运行预设的命令,不过有project-shell
,project-eshell
,project-compile
,如果shell有预设的alias,使用体验也不会差很多,而且更灵活.
另一个缺点:
因为是直接回溯找.git .svn
等,所以不能处理symlink.
(vc-find-root dir ".git/")