[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/eat eac1165a1a 1/2: Support directory tracking with OSC 7
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/eat eac1165a1a 1/2: Support directory tracking with OSC 7 |
Date: |
Wed, 30 Nov 2022 14:58:49 -0500 (EST) |
branch: elpa/eat
commit eac1165a1ab716a065424a031de97f707ee48d6b
Author: Akib Azmain Turja <akib@disroot.org>
Commit: Akib Azmain Turja <akib@disroot.org>
Support directory tracking with OSC 7
* eat.el: Require 'url'.
* eat.el (eat-enable-directory-tracking): New user option.
* eat.el (eat--t-term): New slots: 'cwd' and 'set-cwd-fn'.
* eat.el (eat--t-set-cwd, eat-term-cwd): New function.
* eat.el (eat-term-set-cwd-function): New function and
generalized variable.
* eat.el (eat--t-handle-output): Handle OSC 7.
* eat.el (eat--set-cwd): New function.
* eat.el (eat-exec): Use 'eat--set-cwd' to change current
working directory.
* eat.el (eat--eshell-invocation-directory): New variable,
local in Eshell buffers when 'eat-eshell-mode' is enabled.
* eat.el (eat--eshell-setup-proc-and-term): Save the invocation
directory of process.
* eat.el (eat--eshell-cleanup): Revert working directory to
invocation directory.
* eat.el (eat--eshell-local-mode): When enabling, make
'eat--eshell-invocation-directory' local variable and kill when
disabling.
* eat-tests.el (eat-test-set-cwd): New test.
* eat.texi (Directory Tracking): New chapter.
---
eat-tests.el | 24 +++++++++++++++++
eat.el | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
eat.texi | 33 +++++++++++++++++++++++
3 files changed, 136 insertions(+), 6 deletions(-)
diff --git a/eat-tests.el b/eat-tests.el
index 396504df03..414929761e 100644
--- a/eat-tests.el
+++ b/eat-tests.el
@@ -5748,6 +5748,30 @@ Write plain text and newline to move cursor."
"frob")
:cursor '(1 . 4))))
+(ert-deftest eat-test-set-cwd ()
+ "Test setting current working directory."
+ (eat--tests-with-term '()
+ (let ((cwd default-directory))
+ (should (string= (eat-term-cwd (terminal)) default-directory))
+ (setf (eat-term-set-cwd-function (terminal))
+ (lambda (term dir)
+ (should (eq term (terminal)))
+ (setq cwd dir)))
+ ;; file://HOST/PATH/.
+ (output (format "\e]7;file://%s/foo/bar/\e\\" (system-name)))
+ (should (string= cwd "/foo/bar/"))
+ (should (string= (eat-term-cwd (terminal)) "/foo/bar/"))
+ ;; file://HOST/PATH (note the missing trailing slash).
+ (output (format "\e]7;file://%s/bar/baz\a" (system-name)))
+ (should (string= cwd "/bar/baz/"))
+ (should (string= (eat-term-cwd (terminal)) "/bar/baz/"))
+ ;; file://SOME-OTHER-HOST/PATH/
+ (output (format "\e]7;file://%s/baz/foo/\e\\"
+ (if (string= (system-name) "foo") "bar" "foo")))
+ (should (string= cwd "/bar/baz/"))
+ (should (string= (eat-term-cwd (terminal)) "/bar/baz/"))
+ (should-term :cursor '(1 . 1)))))
+
;;;;; Input Event Tests.
diff --git a/eat.el b/eat.el
index 56c511d459..d3252e485e 100644
--- a/eat.el
+++ b/eat.el
@@ -81,6 +81,7 @@
(require 'cl-lib)
(require 'ansi-color)
(require 'shell)
+(require 'url)
;;;; User Options.
@@ -139,6 +140,16 @@ This is left disabled for security reasons."
:group 'eat-ui
:group 'eat-eshell)
+(defcustom eat-enable-directory-tracking t
+ "Non-nil means do directory tracking.
+
+When non-nil, Eat will track the working directory of program. You
+need to configure the program to send current working directory
+information."
+ :type 'boolean
+ :group 'eat-ui
+ :group 'eat-eshell)
+
(defconst eat--cursor-type-value-type
(let ((cur-type
'(choice
@@ -647,6 +658,9 @@ For example: when THRESHOLD is 3, \"*foobarbaz\" is
converted to
(begin nil :documentation "Beginning of terminal.")
(end nil :documentation "End of terminal area.")
(title "" :documentation "The title of the terminal.")
+ (cwd
+ default-directory
+ :documentation "The working directory of the terminal.")
(bell-fn
(1value #'ignore)
:documentation "Function to ring the bell.")
@@ -662,6 +676,9 @@ For example: when THRESHOLD is 3, \"*foobarbaz\" is
converted to
(set-title-fn
(1value #'ignore)
:documentation "Function to set title.")
+ (set-cwd-fn
+ (1value #'ignore)
+ :documentation "Function to set the current working directory.")
(grab-mouse-fn
(1value #'ignore)
:documentation "Function to grab mouse.")
@@ -2189,6 +2206,25 @@ MODE should be one of nil and `x10', `normal',
`button-event',
;; Inform the UI.
(funcall (eat--t-term-set-title-fn eat--t-term) eat--t-term title))
+(defun eat--t-set-cwd (url)
+ "Set the working directory of terminal to URL.
+
+URL should be a URL in the format \"file://HOST/CWD/\"; HOST can be
+empty."
+ (message "%S" url)
+ (let ((obj (url-generic-parse-url url)))
+ (when (and (string= (url-type obj) "file")
+ (or (null (url-host obj))
+ (string= (url-host obj) (system-name))))
+ (let ((dir (expand-file-name
+ (file-name-as-directory
+ (url-unhex-string (url-filename obj))))))
+ ;; Update working directory.
+ (setf (eat--t-term-cwd eat--t-term) dir)
+ ;; Inform the UI.
+ (funcall (eat--t-term-set-cwd-fn eat--t-term)
+ eat--t-term dir)))))
+
(defun eat--t-send-device-attrs (params format)
"Return device attributes.
@@ -2701,6 +2737,11 @@ DATA is the selection data encoded in base64."
(let title (zero-or-more anything))
string-end)
(eat--t-set-title title))
+ ;; OSC 7 ; <t> ST.
+ ((rx string-start ?7 ?\;
+ (let url (zero-or-more anything))
+ string-end)
+ (eat--t-set-cwd url))
;; OSC 10 ; ? ST.
("10;?"
(eat--t-report-foreground-color))
@@ -2971,6 +3012,24 @@ FUNCTION), where FUNCTION is the function to set title."
(gv-define-setter eat-term-set-title-function (function terminal)
`(setf (eat--t-term-set-title-fn ,terminal) ,function))
+(defun eat-term-cwd (terminal)
+ "Return the current working directory of TERMINAL."
+ (eat--t-term-cwd terminal))
+
+(defun eat-term-set-cwd-function (terminal)
+ "Return the function used to set the working directory of TERMINAL.
+
+The function is called with two arguments, TERMINAL and the new
+\(current) working directory of TERMINAL. The function should not
+change point and buffer restriction.
+
+To set it, use (`setf' (`eat-term-set-cwd-function' TERMINAL)
+FUNCTION), where FUNCTION is the function to set title."
+ (eat--t-term-set-cwd-fn terminal))
+
+(gv-define-setter eat-term-set-cwd-function (function terminal)
+ `(setf (eat--t-term-set-cwd-fn ,terminal) ,function))
+
(defun eat-term-grab-mouse-function (terminal)
"Return the function used to grab the mouse.
@@ -4185,6 +4244,12 @@ selection, or nil if none."
"Ring the bell."
(ding t))
+(defun eat--set-cwd (_ cwd)
+ "Set CWD as the current working directory (`default-directory')."
+ (when eat-enable-directory-tracking
+ (ignore-errors
+ (cd-absolute cwd))))
+
;;;;; Major Mode.
@@ -4488,7 +4553,8 @@ same Eat buffer. The hook `eat-exec-hook' is run after
each exec."
#'eat--grab-mouse
(eat-term-manipulate-selection-function eat--terminal)
#'eat--manipulate-kill-ring
- (eat-term-ring-bell-function eat--terminal) #'eat--bell)
+ (eat-term-ring-bell-function eat--terminal) #'eat--bell
+ (eat-term-set-cwd-function eat--terminal) #'eat--set-cwd)
;; Crank up a new process.
(let* ((size (eat-term-size eat--terminal))
(process-environment
@@ -4702,6 +4768,9 @@ PROGRAM can be a shell command."
;;;;; Process Handling.
+(defvar eat--eshell-invocation-directory nil
+ "The directory from where the current process was started.")
+
(defvar eshell-last-output-start) ; In `esh-mode'.
(defvar eshell-last-output-end) ; In `esh-mode'.
@@ -4732,7 +4801,8 @@ PROGRAM can be a shell command."
(defun eat--eshell-setup-proc-and-term (proc)
"Setup process PROC and a new terminal for it."
(unless (or eat--terminal eat--process)
- (setq eat--process proc)
+ (setq eat--process proc
+ eat--eshell-invocation-directory default-directory)
(process-put proc 'adjust-window-size-function
#'eat--adjust-process-window-size)
(setq eat--terminal (eat-term-make (current-buffer)
@@ -4745,20 +4815,22 @@ PROGRAM can be a shell command."
#'eat--grab-mouse
(eat-term-manipulate-selection-function eat--terminal)
#'eat--manipulate-kill-ring
- (eat-term-ring-bell-function eat--terminal) #'eat--bell)
+ (eat-term-ring-bell-function eat--terminal) #'eat--bell
+ (eat-term-set-cwd-function eat--terminal) #'eat--set-cwd)
(when-let* ((window (get-buffer-window nil t)))
(with-selected-window window
(eat-term-resize eat--terminal (window-max-chars-per-line)
(window-text-height))))
(eat-term-redisplay eat--terminal)
- (make-local-variable 'eshell-output-filter-functions)
- (setq eshell-output-filter-functions '(eat--eshell-output-filter))
+ (setq-local eshell-output-filter-functions
+ '(eat--eshell-output-filter))
(eat-eshell-semi-char-mode)))
(defun eat--eshell-cleanup ()
"Cleanup everything."
(when eat--terminal
(let ((inhibit-read-only t))
+ (cd-absolute eat--eshell-invocation-directory)
(goto-char (eat-term-end eat--terminal))
(unless (or (= (point) (point-min))
(= (char-before) ?\n))
@@ -4923,7 +4995,8 @@ sane 2>%s ; if [ $1 = .. ]; then shift; fi; exec \"$@\""
eat--mouse-grabbing-type
eat--pending-output-chunks
eat--output-queue-first-chunk-time
- eat--process-output-queue-timer)))
+ eat--process-output-queue-timer
+ eat--eshell-invocation-directory)))
(cond
(eat--eshell-local-mode
(mapc #'make-local-variable locals)
diff --git a/eat.texi b/eat.texi
index 1b7f4b0f97..3dbe0586bb 100644
--- a/eat.texi
+++ b/eat.texi
@@ -70,6 +70,7 @@ Advanced Customizations
* Cursor Types:: Cursor can displayed in many forms.
* Mouse Tracking:: Eat tracks mouse, but this can be changed.
* Clipboard:: Integrating kill ring with terminal.
+* Directory Tracking:: Tracking the working directory of program.
* Colors:: Eat can show more than sixteen million colors.
* Fonts:: Eat can show up to sixty font different fonts.
* Blinking Text:: Annoying blinking texts.
@@ -470,6 +471,38 @@ non-@code{nil}, programs can receive the kill ring
contents. This is
disabled by default for security reasons.
@end defopt
+@node Directory Tracking
+@cindex directory tracking
+@cindex tracking directory
+@cindex working directory tracking
+@cindex tracking working directory
+@cindex cwd tracking
+@cindex tracking cwd
+@chapter Directory Tracking
+
+Eat can track the current working directory of the program. This also
+works in Eshell, but after the program exits, the current working
+directory is changed back to the directory from where the program was
+invoked.
+
+To track, Eat needs the program to send this information. So, to
+enable directory tracking, you'll need to setup your shell. You'll
+need to arrange that your shell sends appropriate escape sequence at
+each prompt, for example with the command:
+
+@example
+printf "\\e]7;file://%s%s\\e\\\\" "$HOSTNAME" "$PWD"
+@end example
+
+If you don't want Eat to track your program's working directory, you
+can set the following to nil:
+
+@vindex eat-enable-directory-tracking
+@defopt eat-enable-directory-tracking
+This controls directory tracking. When set to non-@code{nil}, Eat
+tracks the current working directory of programs.
+@end defopt
+
@node Colors
@cindex colors
@cindex customizing colors