3

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 posited 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

  • 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 '16 at 8:20
3

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).

  • 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 '16 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 '16 at 8:26
  • 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 '18 at 18:16

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.