1

The documentation shown with Ctrl h k up states:

<up> runs the command previous-line (found in global-map), which is an
interactive byte-compiled Lisp function in ‘simple.el’.

It is bound to C-p and <up>.

(previous-line &optional ARG TRY-VSCROLL)

Move cursor vertically up ARG lines.
Interactively, vscroll tall lines if ‘auto-window-vscroll’ is enabled.
Non-interactively, use TRY-VSCROLL to control whether to vscroll tall
lines: if either ‘auto-window-vscroll’ or TRY-VSCROLL is nil, this
function will not vscroll.

ARG defaults to 1.

If there is no character in the target line exactly over the current column,
the cursor is positioned after the character in that line that spans this
column, or at the end of the line if it is not long enough.

If the variable ‘line-move-visual’ is non-nil, this command moves
by display lines.  Otherwise, it moves by buffer lines, without
taking variable-width characters or continued lines into account.
See M-x previous-logical-line for a command that always moves by buffer lines.

The command C-x C-n can be used to create
a semipermanent goal column for this command.
Then instead of trying to move exactly vertically (or as close as possible),
this command moves to the specified goal column (or as close as possible).
The goal column is stored in the variable ‘goal-column’, which is nil
when there is no goal column.  Note that setting ‘goal-column’
overrides ‘line-move-visual’ and causes this command to move by buffer
lines rather than by display lines.

  This function is for interactive use only;
  in Lisp code use `forward-line' with negative argument instead.
  Probably introduced at or before Emacs version 29.1.

The usual behavior of &optional values is that their default value is nil, but the default value for ARG is stated to be 1.

What is then the default value of TRY-VSCROLL?

Drew
  • 75,699
  • 9
  • 109
  • 225
Claudio
  • 410
  • 2
  • 11
  • 1
    “*The usual behavior of `&optional` values is that their default value is `nil`, but the default value for `ARG` is stated to be `1`.*” --- [13.2.3 Features of Argument Lists](https://www.gnu.org/software/emacs/manual/html_node/elisp/Argument-List.html): “*the body of the function is free to consider `nil` an abbreviation for some other meaningful value.*” – shynur Apr 14 '23 at 10:47
  • @Shynur : **yes** exactly. I know. Therefore the documentation should ALWAYS provide the information which value will be actually used if not given. By the way it's worth to know in this context that: **elisp does not provide means allowing a function to know if a value was provided or not in case the provided value is `nil`** . What you state in your comment is only the consequence of that. – Claudio Apr 14 '23 at 11:06
  • @Shynur : if the documentation does not state which value will be used in case you don't provide it, then you are forced to look at the source code to find it out. Knowing that will maybe be the key to the answer to your question about inconsistent scrolling behavior. – Claudio Apr 14 '23 at 11:10
  • @Shynur : it's not possible for me to deduct from the documentation of `cl-defun` how to accomplish **elisp allows you to implement this functionality**. Can you provide a short code example demonstrating this? – Claudio Apr 14 '23 at 11:17
  • I think our discussion is getting sidetracked and I will delete my irrelevant comments. |||| “*Can you provide a short code example*” --- `(cl-defun f (&optional (a 233 supplied-p)) supplied-p)` – shynur Apr 14 '23 at 11:29
  • Thanks ... the code example works :) . So *yes, elisp allows to implement the functionality of detecting if a parameter was passed or not*. – Claudio Apr 14 '23 at 12:23
  • Deleting the comments is maybe not a good idea - they provide useful information, even if not directly related to the question. – Claudio Apr 14 '23 at 12:24
  • Emacs docs is not the first to use the following reasonable idea: if it is an exception, mention it in the doc. If it is not an exception, do not mention it in the doc. So the doc for `previous-line` mentions that the default value of `ARG` is 1, because that is specific to this function and an exception to the rule. It does not say anything about `TRY-VSCROLL` because it is no exception: it follows the general rule. OTOH, if you find a case where an exception is *NOT* documented, feel free to submit a doc bug report. – NickD Apr 14 '23 at 18:38
  • @NickD: yes, it makes sense and I would not ask this question if not trying to find an answer to a question about a weird scrolling behavior: https://emacs.stackexchange.com/questions/76649/why-doesnt-scroll-margin-work/76818 . In other words are you as good as *SURE* that there can't be any effect able to make this obvious deduction rule obsolete? And if you have to look for the answer in the source code it's maybe a good idea to wait for response from someone who just knows it out of the box forced in the past hunting for a bug to find it out himself. – Claudio Apr 14 '23 at 19:33

1 Answers1

1

Didn't read all your comments. But the doc string says two things that are relevant: (1) ARG defaults to 1 and (2) this command is only for interactive use.

However, IMHO, it would be better if the doc said that interactively ARG is the numeric prefix argument. And that always defaults to 1, not nil.` IOW, when used interactively the cursor moves backward one line.

The doc is also less than ideal by saying, on the one hand, that the command should only be used interactively (that's a guideline), and on the other hand, providing info about the behavior defined by the arguments when the function is called from Lisp. That's all OK, but it isn't expressed as clearly as it could be, IMO.

When called from Lisp, all optional args default to nil, always.

According to this doc, when called from Lisp, non-nil argument TRY-VSCROLL means the function tries to "vscroll tall lines".

Unfortunately, this doc (as well as the doc for function line-move, which is what previous-line calls in this case to do the job) says nothing about what the verb "vscroll" means.

Not only that, but there's nothing in the Emacs manual about what "vscroll" means. The Elisp manual doesn't use it as a verb, as far as I can see, but searching for it and gathering bits of info here and there from the search hits, I get the impression that it has to do with scrolling the window vertically by pixels. (I may be wrong about that).

A guess is that the doc for this function (and for line-move) evolved over time to try to accommodate additions such as argument TRY-VSCROLL, and it was never rewritten well to clearly describe the behavior. Someone (TM) may have added TRY-SCROLL without rewriting the whole doc string accordingly. Just a guess.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • In order to be able to proof myself that *"when called from Lisp all optional args default to `nil`, always"* I need to know what does it mean *called from Lisp"*? What is the mechanism allowing a Lisp function (coded in elisp or in C as elisp object) to "know" if it was called by a key processing event or from textual code? – Claudio Apr 14 '23 at 19:42
  • Try function `called-interactively-p`. It's not 100% sure, though. – Drew Apr 14 '23 at 20:00
  • My own first intuitive guess about what TRY-VSCROLL could mean was that it is a flag telling if scrolling should be involved at all (not only moving the point a line up) and the TRY conveys the idea that scrolling is not always possible (for example with point at the first line). Anyway ... trying to guess is not a good idea violating one of the rules (it's OK to delete them from the question ... it doesn't really belong there and ... it was probably already read by all who it was addressed at). – Claudio Apr 14 '23 at 20:05
  • Yes, that's what I meant by my guess also: try to scroll the window as the cursor moves (and not just when needed to keep the cursor in the window). – Drew Apr 14 '23 at 20:14
  • It seems that it is possible to "call from elisp" pretending an interactive call by using the `execute-command` function to invoke an interactive function run. This leads me to the conclusion that "called from elisp" means a direct call of the function without any other "helper" ones to get it executed. – Claudio Apr 15 '23 at 03:55