I write Sage code in basically two ways: library-like code and experiment code. Libraries is for code in Sage proper or for my own, more idiosyncratic library of amassed code. For this purpose, sage-mode is already pretty good, in particularly with the function sage-send-buffer.
For experimentation, however, I work similar to how one does in the Notebook: I get simple code creating lots of top-level objects, which are various instances of my library code, and I am interested in results of computations on these. Each such computations almost always span multiple lines of setup and post-processing. For most experiments, I also end up with a few specifically tailored helper-functions. Obviously, I don't want to write too much of such code directly in the sage-shell since I would loose it.
My solution is the following: I put such code in .sheet files and rarely write anything but names of objects directly in the shell.
I have the concept of "blocks", which is similar to one box of code in the Notebook. In source, I delimit these with ###-comment lines (and blank lines for overview). I then have a simple function sage-send-current-block for evaluation, as well as move functions sage-backward-block and sage-forward-block.
I also wrote sage-eval-next-block for when I am standing in the sage shell: it jumps to the last visited .sage/.sheet file, evaluates the current block, and returns to the shell. Since sage-send-current-block moves to the beginning of the next block after evaluation, repeatedly calling this sage-eval-next-block is a convenient way to evaluate several blocks in a row from the same source file.
I am intending this pull request as an RFC, so progress and fixes more easily can be discussed. I have also not created or modified a real Emacs package before, so I might have done something stupid. That said, I think the code works as intended.
You spotted a mistake in the forward/backward code. I'll describe now the
behaviour I desire, and your sharp Emacs eye can tell me if I succeeded with the
One is "inside" of a block whenever the cursor is not inside a delimiter or
just behind the first character of a delimiter.
When inside a block, ``sage-backward-block'' should take the cursor behind the
first character of the latest delimiter, whose end is before the point. That
is, if you're in the middle of a delimiter, go to the delimiter before it.
When inside a block, ``sage-forward-block'' should go to the start of the next
delimiter. I.e. if you're standing in the middle of a delimiter, go to the
beginning of the one after this.
When inside a block, ``sage-send-current-block'' will mark from backward-block to forward-block.
When just before a delimiter (i.e. "outside a block") sage-backward-block''
goes to the beginning of the previous delimiter.sage-forward-block'' goes
to the next. sage-send-current-block'' sends from just before the delimiter
we're on and untilsage-forward-block''.
Due to the above, sage-send-current-block will need a special case: it has to
behave differently than sage-backward-block if it is standing on a delimiter.
I think it is too invasive to override paragraph movement. You might well make a
rather long block, and in that case, would want to preserve paragraph moving. I
use Evil mode, so "}" is forward paragraph for me (and I use this all the time,
also when editing Sage code).
Can you suggest a different standard binding, more Pure Emacsy®?
I assume that the paragraph-moving functions should not push the mark? As an Evil user, I use the mark all the time for "history" of we're I've been, but that's not so Emacsy as far as I understand?
I looked through your changes and some made the code more robust, some more usable (like the args), and some I didn't quite get. Why, for example, do you prefer search-forward-regexp with third argument nil and then manually move the point to max-point, instead of having search-forward-regexp doing it itself?