From: Jim Porter Date: Tue, 10 Oct 2023 03:25:28 +0000 (-0700) Subject: Add a new Eshell special reference type for markers X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=64aa01f60ad17af2bd438895a19343f3c369bc43;p=emacs.git Add a new Eshell special reference type for markers * lisp/eshell/esh-arg.el (eshell-get-marker, eshell-insert-marker) (eshell-complete-marker-ref): New functions... (eshell-special-ref-alist): ... Add them to the new "marker" entry. * test/lisp/eshell/esh-arg-tests.el (esh-arg-test/special-reference/marker) (esh-arg-test/special-reference/nested) (esh-arg-test/special-reference/lisp-form): * test/lisp/eshell/em-cmpl-tests.el (em-cmpl-test/special-ref-completion/type) (em-cmpl-test/special-ref-completion/marker): New tests. * doc/misc/eshell.texi (Arguments): Document the new special ref type. * etc/NEWS: Announce this change (bug#66458). --- diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index b5cc9faeec2..e8aa8cdc6a3 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -400,6 +400,14 @@ Return the buffer named @var{name}. This is equivalent to @samp{$(get-buffer-create "@var{name}")} (@pxref{Creating Buffers, , , elisp, The Emacs Lisp Reference Manual}). +@item # +Return a marker at @var{position} in the buffer @var{buffer-or-name}. +@var{buffer-or-name} can either be a string naming a buffer or an +actual buffer object. This is roughly equivalent to creating a new +marker and calling @samp{$(set-marker marker @var{position} +@var{buffer-or-name})} (@pxref{Moving Markers, , , elisp, The Emacs +Lisp Reference Manual}). + @item # Return the process named @var{name}. This is equivalent to @samp{$(get-process "@var{name}")} (@pxref{Process Information, , , diff --git a/etc/NEWS b/etc/NEWS index e6c47660522..29744d3ad77 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -430,6 +430,14 @@ appropriate, but still allow piping the output elsewhere if desired. For more information, see the "(eshell) Built-ins" node in the Eshell manual. ++++ +*** New special reference type '#'. +This special reference type returns a marker at 'POSITION' in +'BUFFER'. You can insert it by typing or using the new interactive +command 'eshell-insert-marker'. You can also insert markers of any +type with the new command 'eshell-insert-special-reference'. See the +"(eshell) Arguments" node in the Eshell manual for more details. + +++ *** New splice operator for Eshell dollar expansions. Dollar expansions in Eshell now let you splice the elements of the diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el index d5fcabccb14..2bdfdff8a3a 100644 --- a/lisp/eshell/esh-arg.el +++ b/lisp/eshell/esh-arg.el @@ -169,7 +169,11 @@ treated as a literal character." '(("buffer" (creation-function eshell-get-buffer) (insertion-function eshell-insert-buffer-name) - (completion-function eshell-complete-buffer-ref))) + (completion-function eshell-complete-buffer-ref)) + ("marker" + (creation-function eshell-get-marker) + (insertion-function eshell-insert-marker) + (completion-function eshell-complete-marker-ref))) "Alist of special reference types for Eshell. Each entry is a list of the form (TYPE (KEY VALUE)...). TYPE is the name of the special reference type, and each KEY/VALUE pair @@ -717,5 +721,26 @@ single argument." "Perform completion for buffer references." (pcomplete-here (mapcar #'buffer-name (buffer-list)))) +(defun eshell-get-marker (position buffer-or-name) + "Return the marker for character number POSITION in BUFFER-OR-NAME. +BUFFER-OR-NAME can be a buffer or a string. If a string and a +live buffer with that name exists, use that buffer. If no such +buffer exists, create a new buffer with that name and use it." + (let ((marker (make-marker))) + (set-marker marker (string-to-number position) + (get-buffer-create buffer-or-name)))) + +(defun eshell-insert-marker (position buffer-name) + "Insert a marker into the current buffer at point. +This marker will point to POSITION in BUFFER-NAME." + (interactive "nPosition: \nBName of buffer: ") + (insert-and-inherit "#")) + +(defun eshell-complete-marker-ref () + "Perform completion for marker references." + (pcomplete-here) + (pcomplete-here (mapcar #'buffer-name (buffer-list)))) + (provide 'esh-arg) ;;; esh-arg.el ends here diff --git a/test/lisp/eshell/em-cmpl-tests.el b/test/lisp/eshell/em-cmpl-tests.el index 29a41625d5e..dd3c338ac54 100644 --- a/test/lisp/eshell/em-cmpl-tests.el +++ b/test/lisp/eshell/em-cmpl-tests.el @@ -243,14 +243,17 @@ See ." "echo $(eshell/echo")))) (ert-deftest em-cmpl-test/special-ref-completion/type () - "Test completion of the start of special references like \"#." (with-temp-eshell (should (equal (eshell-insert-and-complete "echo hi > # # # # # # #\". @@ -282,6 +285,31 @@ See ." (format "echo hi > # " (string-replace " " "\\ " bufname)))))))) +(ert-deftest em-cmpl-test/special-ref-completion/marker () + "Test completion of special references like \"#\". +See ." + (let (bufname) + (with-temp-buffer + (setq bufname (rename-buffer "my-buffer" t)) + ;; Complete the buffer name in various forms. + (with-temp-eshell + (should (equal (eshell-insert-and-complete + "echo hi > # # " bufname)))) + (with-temp-eshell + (should (equal (eshell-insert-and-complete + "echo hi > # #> " bufname)))) + (with-temp-eshell + (should (equal (eshell-insert-and-complete + "echo hi > # #> " bufname)))) + ;; Partially-complete the "buffer" type name. + (with-temp-eshell + (should (equal (eshell-insert-and-complete + "echo hi > # #." diff --git a/test/lisp/eshell/esh-arg-tests.el b/test/lisp/eshell/esh-arg-tests.el index 0e07d107562..1eb8e08b883 100644 --- a/test/lisp/eshell/esh-arg-tests.el +++ b/test/lisp/eshell/esh-arg-tests.el @@ -118,6 +118,17 @@ treated literally, as a backslash and a newline." (format "echo #" (buffer-name)) (current-buffer)))) +(ert-deftest esh-arg-test/special-reference/marker () + "Test that \"#\" refers to a marker in the buffer \"buf\"." + (with-temp-buffer + (rename-buffer "my-buffer" t) + (insert "hello") + (let ((marker (make-marker))) + (set-marker marker 1 (current-buffer)) + (eshell-command-result-equal + (format "echo #" (buffer-name)) + marker)))) + (ert-deftest esh-arg-test/special-reference/quoted () "Test that '#' refers to the buffer \"foo bar\"." (with-temp-buffer @@ -129,6 +140,20 @@ treated literally, as a backslash and a newline." (format "echo #" (buffer-name)) (current-buffer)))) +(ert-deftest esh-arg-test/special-reference/nested () + "Test that nested special references work correctly." + (with-temp-buffer + (rename-buffer "my-buffer" t) + (insert "hello") + (let ((marker (make-marker))) + (set-marker marker 1 (current-buffer)) + (eshell-command-result-equal + (format "echo #>" (buffer-name)) + marker) + (eshell-command-result-equal + (format "echo #>" (buffer-name)) + marker)))) + (ert-deftest esh-arg-test/special-reference/var-expansion () "Test that variable expansion inside special references works." (with-temp-buffer @@ -141,6 +166,19 @@ treated literally, as a backslash and a newline." "echo #" (current-buffer))))) +(ert-deftest esh-arg-test/special-reference/lisp-form () + "Test that Lisp forms inside special references work." + (with-temp-eshell + (let ((marker (make-marker)) + eshell-test-value) + (set-marker marker 1 (current-buffer)) + (eshell-insert-command + "setq eshell-test-value #") + (should (equal eshell-test-value marker)) + (eshell-insert-command + "setq eshell-test-value #>") + (should (equal eshell-test-value marker))))) + (ert-deftest esh-arg-test/special-reference/special-characters () "Test that \"#<...>\" works correctly when escaping special characters." (with-temp-buffer