5

I use evil-mode with Emacs and would like to accomplish this via evil-mode, but would be fine with doing it in an Emacs-centric way too. The subject line explains it well, but here is a post in which a Vim user posted the same question as mine and received the Vim-centric answer (several actually): How do I move vertically until reaching a non-whitespace character?

Another useful link, similar to that provided above: Move to the next row which has non-white space character in the same column in VIM?

Thanks in advance.

UPDATE: I decided I'd write a function to do this and it was surprisingly easy:

(defun jump-down-to-non-whitespace-char-in-same-column ()
  (interactive)
  (next-line)
  (while (or (= (char-after (point)) 32)
             (= (char-after (point)) 10))
    (next-line)))

I guess I'd still like to know if there is a way to do it with evil-mode anyway just because I am curious, so I won't answer my own question yet.

UPDATE 2: I prefer the following version instead as now I use evil-next-line and evil-previous-line which behave more consistently the way I want:

(defun jump-down-to-non-whitespace-char-in-same-column ()
  (interactive)
  (evil-next-line)
  (while (or (= (char-after (point)) 32)
            (= (char-after (point)) 10))
    (evil-next-line)))

(defun jump-up-to-non-whitespace-char-in-same-column ()
  (interactive)
  (evil-previous-line)
  (while (or (= (char-after (point)) 32)
            (= (char-after (point)) 10))
    (evil-previous-line)))

Then in my evil-leader config I use "c d" jump-down-to-non-whitespace-char-in-same-column and "c u" jump-up-to-non-whitespace-char-in-same-column

1
  • I suggest moving your own answers to actual answers, and maybe expand a bit on the difference between the first and the "evil" versions.
    – YoungFrog
    May 6, 2016 at 8:20

1 Answer 1

4

I use the following :

(defun next-line-non-empty-column (arg)
  "Find next line, on the same column, skipping those that would
end up leaving point on a space or newline character."
  (interactive "p")
  (let* ((hpos (- (point) (point-at-bol)))
         (re (format "^.\\{%s\\}[^\n ]" hpos)))
    (cond ((> arg 0)
           (forward-char 1) ; don't match current position (can only happen at column 0)
           (re-search-forward re))
          ((< arg 0)
           (forward-char -1)           ; don't match current position.
           (re-search-backward re)
           (goto-char (match-end 0))))
    ;; now point is after the match, let's go back one column.
    (forward-char -1)))
(defun previous-line-non-empty-column (arg)
  ""
  (interactive "p")
  (next-line-non-empty-column (- arg)))
(global-set-key (kbd "C-S-n") 'next-line-non-empty-column)
(global-set-key (kbd "C-S-p") 'previous-line-non-empty-column)

IIRC I went for the regexp way because of performance reasons. Not saying that this is the best implementation, but it was better than my previous one (don't remember what it was).

3
  • Thanks @YoungFrog, appreciate it. Nice to have a regexp solution. I'll try to remember to give some points to you when my rep here grows.
    – Joe
    May 6, 2016 at 5:57
  • Please note that this will not match exactly your code (with next-line) when visual-line-mode is on (and truncate-lines is nil) : if you have a very long lines which wraps, your code will stop on the next visual line, whereas this code will not. (I don't know how evil-next-line behaves.)
    – YoungFrog
    May 6, 2016 at 8:26
  • 1
    This is something that never occurred to me but now that I've added it I'm using it a lot -- thanks!
    – glucas
    Mar 2, 2018 at 18:16

Your Answer

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

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