Created
July 31, 2023 17:56
-
-
Save genegoykhman/09868acd369b3fae866be6446997de9f to your computer and use it in GitHub Desktop.
Enabled TRAMP completion for Docker containers at the end of a multi-hop connection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; -*- mode: lisp-interaction; -*- | |
;; Load tramp variables | |
(require 'tramp) | |
;; Disable TRAMP caching so we don't see unavailable containers | |
(setq tramp-completion-use-cache nil) | |
;; My tramp completion function, that tries to set the correct | |
;; default-directory so we run "docker" on the remote host | |
(defun my-tramp-container-completion-function (program) | |
"List running containers available for connection. | |
PROGRAM is the program to be run for \"ps\", either | |
`tramp-docker-program' or `tramp-podman-program'. | |
This function is used by `tramp-set-completion-function', please | |
see its function help for a description of the format." | |
(when-let ((default-directory (if tramp-last-hop-directory | |
tramp-last-hop-directory | |
tramp-compat-temporary-file-directory)) | |
(raw-list (shell-command-to-string | |
(concat program " ps --format '{{.ID}}\t{{.Names}}'"))) | |
(lines (split-string raw-list "\n" 'omit)) | |
(names (mapcar | |
(lambda (line) | |
(when (string-match | |
(rx bol (group (1+ nonl)) | |
"\t" (? (group (1+ nonl))) eol) | |
line) | |
(or (match-string 2 line) (match-string 1 line)))) | |
lines))) | |
(mapcar (lambda (name) (list nil name)) (delq nil names)))) | |
;; Adds my completion function to TRAMP completion functions list | |
(add-to-list 'tramp-completion-function-alist | |
`("docker" | |
(tramp-container--completion-function ,tramp-docker-program) | |
(my-tramp-container-completion-function ,tramp-docker-program))) | |
(defun my-tramp-docker-host-path (orig) | |
;; Strips off "|docker" suffix from ORIG allowing | |
;; it to be converted to a tramp-file using TRAMP's path functions. | |
(let ((regexp "\\(.*\\)|docker")) | |
(if (string-match regexp orig) | |
(concat (match-string 1 orig) ":/") | |
orig))) | |
;; When TRAMP handles completions, first set tramp-last-hop-directory | |
;; so that my completion function can set it before running the Docker executable | |
(defun my-tramp-set-docker-default-directory (filename directory) | |
(setq tramp-last-hop-directory nil) | |
(let ((my-host-path (my-tramp-docker-host-path directory))) | |
(when (tramp-tramp-file-p my-host-path) | |
(setq tramp-last-hop-directory (tramp-make-tramp-file-name | |
(tramp-dissect-file-name my-host-path)))))) | |
(advice-add #'tramp-completion-handle-file-name-all-completions :before #'my-tramp-set-docker-default-directory) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment