-
Notifications
You must be signed in to change notification settings - Fork 6
/
mistty-osc7.el
136 lines (105 loc) · 4.86 KB
/
mistty-osc7.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
;;; mistty-osc7.el --- Add support for OSC 7 to term-mode -*- lexical-binding: t -*-
;; This program is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 3 of the
;; License, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see
;; `http://www.gnu.org/licenses/'.
;;; Commentary:
;;
;; This file defines a handler for OSC 7 code sequences that can be
;; registered in `mistty-osc-handlers' to allow shells to report
;; current directories to Emacs (dirtrack).
;;
(require 'url-util)
;;; Code:
(defcustom mistty-allow-tramp-paths t
"If true, allow generating TRAMP paths as shell-specified directory.
This affects directories set using OSC 7, which can then build
TRAMP remote paths based on the hostname specified in the file://
URL, using the default method.
This option doesn't affect hosts configured using
`mistty-host-to-tramp-path-alist'."
:group 'mistty
:type '(boolean))
(defcustom mistty-host-to-tramp-path-alist nil
"Maps hostnames to TRAMP paths.
This alist maps hosts as self-declared using OSC 7 to the TRAMP
path MisTTY should use for directory tracking.
This is useful for hosts that require a specific method to
connect to.
The values should be of the same form as the remote identifiers
returned by `file-remote-p', with method, user and host, for
example \"/ssh:example.com:\". Invalid values are ignored.
The values can also be nil to disable directory tracking for that
specific host.
Note that for the ssh method, it's often easier to add the
configuration option you need to a host to ~/.ssh/config."
:group 'mistty
:type '(alist :key-type (string :tag "Host")
:value-type (choice (string :tag "TRAMP Path")
(const nil))))
(defun mistty-osc7 (_ osc-seq)
"Store OSC-SEQ as path to the current directory.
OSC-SEQ must be a file:// URL pointing to a directory to be used
as the current directory for the current shell.
By default, only local paths are taken into account. To allow
remote paths, configure `mistty-allow-tramp-paths.
The remote paths that are generated by default use the default
TRAMP method, which can be configured using
`tramp-default-method' and `tramp-default-method-alist'. If that
doesn't work for some hosts, add them to
`mistty-host-to-tramp-path-alist'.
Such sequences are typically printed out by shells just before
printing a prompt by a command such as:
printf \"\\e]7;file://%s%s\\e\\\\\" \"$HOSTNAME\" \"$PWD\"
This can be used as a drop-in replacement for
`ansi-osc-directory-tracker', with the following tweaks:
- it decodes percent-encoded non-ASCII characters in the paths,
so such paths look better
- it has optional supports for remote paths."
(when (string-match "file://\\([^/]*\\)\\(/.*\\)" osc-seq)
(let ((hostname (url-unhex-string (match-string 1 osc-seq)))
(path (file-name-as-directory
(decode-coding-string
(url-unhex-string (match-string 2 osc-seq))
'utf-8
'nocopy)))
host-config
host-remote-path)
(when (or (string= hostname "")
(string= hostname "localhost"))
(setq hostname (system-name)))
(cond
;; Interpret path as being in the same TRAMP connection as
;; default-directory if the host names match. This is useful
;; for things like the sudo method, where the hostname is the
;; same, but accessed differently.
((equal (file-remote-p default-directory 'host) hostname)
(setq default-directory
(concat (file-remote-p default-directory) path)))
;; Interpret path as a straightforward local path.
((string= hostname (system-name))
(ignore-errors (cd-absolute path)))
;; Host disabled in mistty-host-to-tramp-path-alist. Do
;; nothing.
((and (setq host-config
(assoc hostname mistty-host-to-tramp-path-alist))
(null (cdr host-config))))
;; Using remote path from mistty-host-to-tramp-path-alist, if
;; it's valid.
((and (cdr host-config)
(setq host-remote-path (file-remote-p (cdr host-config))))
(setq default-directory (concat host-remote-path path)))
;; Generate default paths for a host, if enabled.
(mistty-allow-tramp-paths
(setq default-directory
(concat (file-remote-p (concat "/-:" hostname ":"))
path)))))))
(provide 'mistty-osc7)
;;; mistty-osc7.el ends here