emacs-elpa-diffs
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]