consult-dir+ssh+kitty(terminal)+hyprland 分享如何高效的使用ssh+tramp

背景介绍

我时常需要登录多台ssh服务器,修改服务上的配置文件、执行各种维护命令等,而我又是一个emacs 用户,虽然 也时常使用vim来编辑配置文件等,但当进行大段修改或粘贴复制时,总感觉没emacs用着顺手。所以折腾了这套配置分享给大家。

Features

  1. 使用 ~/.ssh/config 来维护常用ssh列表 (可以给host起易记的别名)
  2. 使用 consult-dir 在emacs 中列出 ~/.ssh/config 中所有的host列表, 并快速使用tramp进入dired目录
  3. 终端下 zsh+fzf 也可以快速从hosts列表中选择要登录的服务器
  4. 在使用tramp 编辑远程文件时,可以快速打开一个终端(kitty),并跳转到远程文件所在的目录
  5. 在终端(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)

效果如动图: latest

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

效果如下:

latest

使用tramp 编辑远程文件时,可以快速打开一个终端(kitty),并跳转到远程文件所在的目录

要实现这个功能需要实现以下几点:

  1. 要能从emacs 和title中获取到当前tramp 访问的 user,host path 等信息
  2. 能按下一个按键后能执行一个脚本以启动kitty (通过xremap)
  3. 启动一个新的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) "] }

里面涉及到以下几个脚本 :

hypr-run-or-raise

term.sh : 对kitty的包装

hypr-cwd : 获取当前working directory (可通过配置获取到emacs 或终端的title中current-working-directory相关信息)

另外需要用到 dotool 命令 以模拟在终端中按下某些键以粘贴 复制到primary中的cd 等命令(这块似乎有bug ,应该跟执行这段代码时 已经按下的键会影响模拟发送的键有关) latest

在终端(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"]}

效果如下: latest

另外再提供了一个一键使用sudo 编辑当前文件的命令,

比如当我以普通用户使用tramp打开远程文件时,

一键切换为使用root 用户来打开 即 C-xC-f /-:you@remotehost|sudo:remotehost:/path/to/file RET

使用sudo编辑本机文件也是一样效果,本质是使用 : /sudo:root@localhost:/etc

lazy-sudo.el

conf-sudo.el

效果如下: latest

7 个赞