0

I recently realized something weird regarding usability of goto-char using GNU Emacs:

M-x goto-char
Go to char: 0x1000
Please enter a number (OP note: didn't work)
M-x goto-char
Go to char: (* 4 1024)
Please enter a number (OP note: didn't work)

I didn't have to use such a construct for the last 20 years of GNU Emacs usage, but I now need to deal with binary files using nhexl-mode and I can't find a good way to jump to specific addresses using hexadecimal (bonus: if it could be specified in a link such as org-mode link to a file:hex-address).

I can't imagine this very basic thing such as input a Lisp expression inside a value input is not possible.

3
  • 5
    "input a Lisp expression" --- In Elisp, 0x1000 is written "#x1000" instead of "0x1000"
    – shynur
    Commented Mar 26, 2023 at 10:53
  • And goto-char #x1000 is working properly! Thanks!
    – Robert
    Commented Mar 27, 2023 at 1:07
  • 1
    See also C-h i g (elisp)Integer Basics
    – phils
    Commented Mar 27, 2023 at 1:51

2 Answers 2

2

[@Shynur has already pointed out, both in a comment and in an answer, the syntax for a hexadecimal number which you can use directly in the goto-char interactive prompt. The following answer is concerned solely with the second part of the question: being able to use a Lisp expression in the interactive prompt.]

How a command gets its input is specified by using an interactive specification. E.g. goto-char has an "N" interactive spec[1]:

n -- Number read using minibuffer.

N -- Numeric prefix arg, or if none, do like code ‘n’.

That's probably general enough for 99.99% of the interactive uses of goto-char (e.g. and FWIW, I have never needed a calculator in order to get the position).

For use in Lisp programs, you can certainly pass whatever complicated expression you want as the argument to goto-char, as long as it returns some position. Here's an example from a recent question:

   ...
   (goto-char (progn 
                  (skip-syntax-forward "^ " (line-end-position))
                  (point)))
   ...

Finally, if you want to be able to have a calculator available, you can follow @Shynur's answer, or you can do something like this:

(defun my/goto-char-with-calculator (res)
   (interactive "XType a Lisp expression that evaluates to a number: ")
   (goto-char res))

The doc string of interactive says:

X -- Lisp expression read and evaluated.

So you can say e.g M-x my/goto-char-with-calculator and type an arbitrary Lisp expression that evaluates to a positive integer, e.g (+ 1000 -992) a.k.a 8 or more usefully (+ (point) 10) to advance 10 character positions past the current point in the buffer.


[1] goto-char is actually written in C and implemented in editfns.c, so I should have said: goto-char has the equivalent of an "N" interactive spec. It is actually implemented by specifying the function call that will do the argument handling: (goto-char--read-natnum-interactive \"Go to char: \"). But that's a detail...

5

I can't imagine this very basic thing such as input a Lisp expression inside a value input is not possible.

It is because there is no need to do that. In Emacs, this behavior can be changed easily:

(defun Robert-goto-char ()
  (interactive)
  (funcall #'goto-char (call-interactively 'eval-expression)))

You might put it in your .emacs.


Here are 2 examples:

M-x Robert-goto-char
Eval: #x1000
M-x Robert-goto-char
Eval: (* 4 1024)

Redefining goto-char is not recommended, because behaviors of some Elisp code may depend on this function.

Also see 2.4.15 Primitive Function Type:

we discourage redefinition of primitive functions

1
  • 2
    Moreover, you can just use the correct hexadecimal syntax with M-x goto-char itself.
    – phils
    Commented Mar 26, 2023 at 22:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.