3

I have a bunch of lines of text and I'm trying to insert text starting at a certain column on each line. For example:

'Some text'            This is ok
'Another longer text'  ask Ram
'weird stuff'          see other file
'more lines'
'even more lines'

I'd like to continue typing text on the further lines, at the same column as the previous lines. The part that's cumbersome is moving to the right place on each line.

Emacs has a way of moving to the same place on each line: set-goal-column. This would work if that column already existed on each line, but that's not the case here.

One way I can work around this (which I'm actually using) is to insert a lot of spaces on each line (replace-regexp $ with a few dozen spaces), then C-x C-n (set-goal-column), and use regular C-n to move between lines. But I'd like to know whether there's a clean way of achieving something better: of setting things up so that after set-goal-column, I can just use C-n to move to the next line, and Emacs will automatically insert the appropriate number of spaces if there weren't enough columns to start with.

  • Do you really want to insert spaces? Do you expect them to go away if you immediately move to the next line? And if so, what happens if the line already contained some whitespace? Maybe look to the artist-mode source code for inspiration for how to approach this without introducing permanent whitespace unnecessarily... – phils Oct 19 '17 at 2:17
  • 1
    This may also be of use to you: (when goal-column (move-to-column goal-column t)) – phils Oct 19 '17 at 2:19
  • FYI, I think line-move-to-column is what ultimately carries out the normal behaviour. – phils Oct 19 '17 at 2:26
  • @phils I don't mind inserting actual spaces; I anyway have a before-save-hook that strips trailing whitespace (and if I didn't, I wouldn't care about trailing whitespace, so that's not a problem either). And yes I had reached a similar conclusion from looking at the source code (following line-move-to-column etc), I think I need to change line-move-to-column which does (move-to-column col) to do (move-to-column col t) instead. Or maybe (when goal-column (move-to-column goal-column t)) as you suggested. Can you post that as an answer, along with how to “modify” line-move-to-column? – ShreevatsaR Oct 19 '17 at 2:31
1

Here is advice that should do what you want:

(defun goal-column-advice (&rest _args)
  "Advice inserting spaces when needed to obey `goal-column'.

This advice is intended as :after advice for commands
`previous-line' and `next-line'.  Normally, these commands will
attempt to obey any `goal-column' setting, but only on lines that
are long enough that the `goal-column' is not past the end of the
line.  This advice changes the advised command to instead pad the
line with spaces in this circumstance.  If `goal-column' is nil,
the command behaves as if it were not advised."
  (when goal-column (move-to-column goal-column t)))

(advice-add 'previous-line :after #'goal-column-advice)
(advice-add 'next-line     :after #'goal-column-advice)

Thanks to @phils for the comment pointing out the role of move-to-column.

As @phils also notes, this method does leave trailing whitespace in your buffer, which some people may not want. The OP doesn't seem to mind, but others may need to find a different solution.

  • Thanks for this! It didn't work for some reason, but then I realized it works if I change :force to t. BTW what do you think of the idea of using :override instead of :after in advice-add? – ShreevatsaR Oct 25 '17 at 21:49
  • You are absolutely right on both counts; I forgot to test after making the t => :force change, and the advice was initially going on next-line and previous-line, so I didn't notice that :override works too. Answer updated. – Aaron Harris Oct 26 '17 at 2:07
  • On second thought, :override isn't quite right, because we should call the original function if goal-column is not set. (In testing, it didn't seem to affect previous-line or next-line at all, though; nevertheless, we should do the right thing.) I've changed it to :around advice to correct this. – Aaron Harris Oct 26 '17 at 2:22
  • Okay, I did some more testing and found that none of the advice previously was working correctly on previous-line; the spaces were being added, but then point was being moved again after our advice. Putting the advice on line-move-1 fixes the problem, but needs to be :after advice again. Sorry for not doing more testing up front; I'm pretty sure this is right now. – Aaron Harris Oct 26 '17 at 2:55
  • Nope. The last version broke move-end-of-line (a.k.a. C-e) because that actually sets goal-column temporarily internally. I'm coming to the conclusion that the source is too tangled to try doing anything clever here; using :after advice on previous-line and next-line directly is probably the best way to go. – Aaron Harris Oct 26 '17 at 3:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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