背景介绍
我时常需要登录多台ssh服务器,修改服务上的配置文件、执行各种维护命令等,而我又是一个emacs 用户,虽然 也时常使用vim来编辑配置文件等,但当进行大段修改或粘贴复制时,总感觉没emacs用着顺手。所以折腾了这套配置分享给大家。
Features
- 使用 ~/.ssh/config 来维护常用ssh列表 (可以给host起易记的别名)
- 使用 consult-dir 在emacs 中列出 ~/.ssh/config 中所有的host列表, 并快速使用tramp进入dired目录
- 终端下 zsh+fzf 也可以快速从hosts列表中选择要登录的服务器
- 在使用tramp 编辑远程文件时,可以快速打开一个终端(kitty),并跳转到远程文件所在的目录
- 在终端(kitty) 执行命令时,也可快速使用emacs+tramp+dired 进入当前目录,以便 编辑目录下的文件
~/.ssh/config 格式如下
Host jxfluoji
Hostname 10.2.0.171
User jixiuf
Port 22
emacs 中使用tramp+dired快速打开服务器上的文件目录
我是https://github.com/minad/consult用户,https://github.com/karthink/consult-dir 是它的一个第3方扩展包 ,
关于recentf 的一些配置
(defun vmacs-recentf-keep-p (file)
"Return non-nil if FILE should be kept in the recent list.
It handles the case of remote files as well."
(cond
((file-remote-p file nil t) (file-readable-p file))
((file-remote-p file) nil) ;不记录 tramp path
((file-readable-p file))))
;; 不记录tramp打开的远程文件目录
;; (emacs退出后将会把tramp的从recentf中清空,但退出之前,依然有相应的记录)
(setq recentf-keep '(vmacs-recentf-keep-p))
;; Track opened directories
(defun recentf-track-opened-dir ()
(and default-directory
(recentf-add-file default-directory)))
;; 进入的dired 目录也记入 recentf 中,
(add-hook 'dired-mode-hook #'recentf-track-opened-dir)
consult-dir 相关配置
将 consult-dir–source-tramp-ssh 加入 consult-dir-sources 中 详细如下:
(setq consult-dir-project-list-function #'(lambda()nil)) ;不使用 consult-dir--source-project
;; (setq consult-dir-project-list-function #'consult-dir-project-dirs)
(setq-default consult-dir-sources
'(consult-dir--source-default
consult-dir--source-recentf
;; consult-dir--source-project
consult-dir--source-tramp-ssh))
(define-key minibuffer-local-completion-map (kbd "C-j") #'consult-dir)
;; 替代 原始的 C-xd
(define-key global-map (kbd "C-x d") #'consult-dir)
;; dired模式下 "," 快速访问最近访问的目录
(define-key dired-mode-map "," 'consult-dir)
效果如动图:
zsh+fzf
实现 ssh+空格后按tab键补全~/.ssh/config中所有的host
function ssh-fzf () {
local selected_host=$(grep "Host " ~/.ssh/config |grep -v "^#" | cut -b 6- | fzf --query "$2")
if [ -n "$selected_host" ]; then
BUFFER="ssh ${selected_host}"
zle accept-line
fi
# zle reset-prompt
zle fzf-redraw-prompt
}
zle -N ssh-fzf
user-complete(){
case $BUFFER in
"" ) # 空行填入 "cd "
zle fzf-cdr-widget
;;
"ssh " ) # TAB + 空格 ssh补全
zle ssh-fzf
;;
* )
zle expand-or-complete ;;
esac
}
zle -N user-complete
bindkey "\t" user-complete
效果如下:
使用tramp 编辑远程文件时,可以快速打开一个终端(kitty),并跳转到远程文件所在的目录
要实现这个功能需要实现以下几点:
- 要能从emacs 和title中获取到当前tramp 访问的 user,host path 等信息
- 能按下一个按键后能执行一个脚本以启动kitty (通过xremap)
- 启动一个新的kitty 终端 要能ssh到相应host后并cd 到相应path
第1点 可通过修改frame-title-format
来暴露相关信息
(setq frame-title-format '("「"mode-line-buffer-identification "」(" (:propertize ("" mode-name) ) ") " mode-line-misc-info " GNU/Emacs<" (:eval (expand-file-name default-directory)) ">") )
第2点 我使用是 hyprland +xremap 来实现 按键绑定
super-C-d: { launch: ["hyprctl","dispatch","exec","hypr-run-or-raise --floating --float-only 'dterm|Alacritty|kitty|org.wezfurlong.wezterm' -- term.sh --class=dterm --working-directory=$(hypr-cwd||echo $HOME)"] }
如果kitty 窗口已经存在 则直接在其窗口中执行 ssh +cd 等命令 跳转到相应目录
只多了一个 --cd 的参数
super-C-t: { launch: ["hypr-run-or-raise", "--cd","--floating","--","dterm|Alacritty|kitty|org.wezfurlong.wezterm","term.sh --class=dterm --working-directory=$(hypr-cwd||echo $HOME) "] }
里面涉及到以下几个脚本 :
term.sh : 对kitty的包装
hypr-cwd : 获取当前working directory (可通过配置获取到emacs 或终端的title中current-working-directory相关信息)
另外需要用到 dotool 命令 以模拟在终端中按下某些键以粘贴 复制到primary中的cd 等命令(这块似乎有bug ,应该跟执行这段代码时 已经按下的键会影响模拟发送的键有关)
在终端(kitty) 执行命令时,也可快速使用emacs+tramp+dired 进入当前目录,以便 编辑目录下的文件
需要能从终端的title 中 获取到 user host path 等信息: 使其window title 符合 user@host:/path/ 的格式 比如说 远程服务器的bashrc 中加入以下内容
case $TERM in
xterm*|vte*)
PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME}" "${PWD/#$HOME/~}"'
;;
screen*)
PROMPT_COMMAND='printf "\033k%s@%s:%s\033\\" "${USER}" "${HOSTNAME}" "${PWD/#$HOME/~}"'
;;
esac
我的xremap 关于 kitty 相关配置,即在 kitty 中按下C-cC-j
后将调用 open-with
这个脚本
open-with
ec 对emacsclient的封装
- name: kitty
application:
only: [dterm,kitty]
remap:
C-c:
remap:
C-j: { launch: ["open-with"]}
效果如下:
另外再提供了一个一键使用sudo 编辑当前文件的命令,
比如当我以普通用户使用tramp打开远程文件时,
一键切换为使用root 用户来打开
即 C-xC-f /-:you@remotehost|sudo:remotehost:/path/to/file RET
使用sudo编辑本机文件也是一样效果,本质是使用 :
/sudo:root@localhost:/etc
效果如下: