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).
This commit is contained in:
Jim Porter 2023-10-09 20:25:28 -07:00
parent 69e8333210
commit 64aa01f60a
5 changed files with 110 additions and 3 deletions

View file

@ -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 #<marker @var{position} @var{buffer-or-name}>
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 #<process @var{name}>
Return the process named @var{name}. This is equivalent to
@samp{$(get-process "@var{name}")} (@pxref{Process Information, , ,

View file

@ -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 '#<marker POSITION BUFFER>'.
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

View file

@ -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 "#<marker " (number-to-string position) " "
(eshell-quote-argument buffer-name) ">"))
(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

View file

@ -243,14 +243,17 @@ See <lisp/eshell/esh-cmd.el>."
"echo $(eshell/echo"))))
(ert-deftest em-cmpl-test/special-ref-completion/type ()
"Test completion of the start of special references like \"#<buffer\".
"Test completion of the start of special reference types like \"#<buffer\".
See <lisp/eshell/esh-arg.el>."
(with-temp-eshell
(should (equal (eshell-insert-and-complete "echo hi > #<buf")
"echo hi > #<buffer ")))
(with-temp-eshell
(should (equal (eshell-insert-and-complete "echo hi > #<proc")
"echo hi > #<process "))))
"echo hi > #<process ")))
(with-temp-eshell
(should (equal (eshell-insert-and-complete "echo hi > #<mark")
"echo hi > #<marker "))))
(ert-deftest em-cmpl-test/special-ref-completion/implicit-buffer ()
"Test completion of special references like \"#<buf>\".
@ -282,6 +285,31 @@ See <lisp/eshell/esh-arg.el>."
(format "echo hi > #<buffer %s> "
(string-replace " " "\\ " bufname))))))))
(ert-deftest em-cmpl-test/special-ref-completion/marker ()
"Test completion of special references like \"#<marker 1 buf>\".
See <lisp/eshell/esh-arg.el>."
(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 > #<marker 1 my-buf")
(format "echo hi > #<marker 1 %s> " bufname))))
(with-temp-eshell
(should (equal (eshell-insert-and-complete
"echo hi > #<marker 1 #<my-buf")
(format "echo hi > #<marker 1 #<%s>> " bufname))))
(with-temp-eshell
(should (equal (eshell-insert-and-complete
"echo hi > #<marker 1 #<buffer my-buf")
(format "echo hi > #<marker 1 #<buffer %s>> " bufname))))
;; Partially-complete the "buffer" type name.
(with-temp-eshell
(should (equal (eshell-insert-and-complete
"echo hi > #<marker 1 #<buf")
"echo hi > #<marker 1 #<buffer "))))))
(ert-deftest em-cmpl-test/variable-ref-completion ()
"Test completion of variable references like \"$var\".
See <lisp/eshell/esh-var.el>."

View file

@ -118,6 +118,17 @@ treated literally, as a backslash and a newline."
(format "echo #<buffer %s>" (buffer-name))
(current-buffer))))
(ert-deftest esh-arg-test/special-reference/marker ()
"Test that \"#<marker N buf>\" 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 #<marker 1 %s>" (buffer-name))
marker))))
(ert-deftest esh-arg-test/special-reference/quoted ()
"Test that '#<buffer \"foo bar\">' refers to the buffer \"foo bar\"."
(with-temp-buffer
@ -129,6 +140,20 @@ treated literally, as a backslash and a newline."
(format "echo #<buffer '%s'>" (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 #<marker 1 #<%s>>" (buffer-name))
marker)
(eshell-command-result-equal
(format "echo #<marker 1 #<buffer %s>>" (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 #<buffer \"$eshell-test-value\">"
(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 #<marker 1 (current-buffer)>")
(should (equal eshell-test-value marker))
(eshell-insert-command
"setq eshell-test-value #<marker 1 #<buffer (buffer-name)>>")
(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