I use these commands to skip words but stop around symbols,
(defun reluctant-forward (&optional arg)
"Skip spaces and tabs following the point, then move past all
characters with the same syntax class.
Do it ARG times if ARG is positive, or -ARG times in the opposite
direction if ARG is negative. ARG defaults to 1."
(interactive "^p")
(if (> arg 0)
(dotimes (_ arg)
(when (looking-at-p "[ \t]")
(skip-chars-forward " \t"))
(unless (= (point) (point-max))
(forward-same-syntax)))
(dotimes (_ (- arg))
(when (looking-back "[ \t]")
(skip-chars-backward " \t"))
(unless (= (point) (point-min))
(forward-same-syntax -1)))))
(defun reluctant-backward (&optional arg)
"Skip spaces and tabs preceding the point, then move before all
characters with the same syntax class.
Do it ARG times if ARG is positive, or -ARG times in the opposite
direction if ARG is negative. ARG defaults to 1."
(interactive "^p")
(reluctant-forward (- arg)))
and I've bound them to M-left
and M-right
:
(global-set-key (kbd "M-<right>") #'reluctant-forward) ; replaces ‘right-word’.
(global-set-key (kbd "M-<left>") #'reluctant-backward) ; replaces ‘left-word’.
Here are the places where reluctant-forward
would place the point if called repeatedly starting from within the square brackets
int main(int argc, char *args[|])|
|{|
|int| a| =| 45|;|
|printf|(|"|%i|"|,| a|)|;|
|}|
Notice that as it is it stops at the beginning of the first word that follows a newline (e.g. at the beginning of printf
), differently from what you asked. I should be able to fix that if you want.
Update
I thought I had to fiddle with syntax classes, instead it was just a matter of adding the newline to the characters to skip.
(defun reluctant-forward (&optional arg)
"Skip whitespace following the point, then move past all
characters with the same syntax class.
Do it ARG times if ARG is positive, or -ARG times in the opposite
direction if ARG is negative. ARG defaults to 1."
(interactive "^p")
(if (> arg 0)
(dotimes (_ arg)
(when (looking-at-p "[ \t\n]")
(skip-chars-forward " \t\n"))
(unless (= (point) (point-max))
(forward-same-syntax)))
(dotimes (_ (- arg))
(when (looking-back "[ \t\n]")
(skip-chars-backward " \t\n"))
(unless (= (point) (point-min))
(forward-same-syntax -1)))))
(defun reluctant-backward (&optional arg)
"Skip whitespace preceding the point, then move before all
characters with the same syntax class.
Do it ARG times if ARG is positive, or -ARG times in the opposite
direction if ARG is negative. ARG defaults to 1."
(interactive "^p")
(reluctant-forward (- arg)))
Stops from |[])
to printf|
:
int main(int argc, char *args|[|])|
{|
int| a| =| 45|;|
printf|("%i", a);
}
Update 2
Not as tested as the other version (I might have missed some corner cases) but it seems to do what you want
(defun reluctant-forward (&optional arg)
"Move point to the end of the next word or string of
non-word-constituent characters.
Do it ARG times if ARG is positive, or -ARG times in the opposite
direction if ARG is negative. ARG defaults to 1."
(interactive "^p")
(if (> arg 0)
(dotimes (_ arg)
;; First, skip whitespace ahead of point
(when (looking-at-p "[ \t\n]")
(skip-chars-forward " \t\n"))
(unless (= (point) (point-max))
;; Now, if we're at the beginning of a word, skip it…
(if (looking-at-p "\\sw")
(skip-syntax-forward "w")
;; …otherwise it means we're at the beginning of a string of
;; symbols. Then move forward to another whitespace char,
;; word-constituent char, or to the end of the buffer.
(if (re-search-forward "\n\\|\\s-\\|\\sw" nil t)
(backward-char)
(goto-char (point-max))))))
(dotimes (_ (- arg))
(when (looking-back "[ \t\n]")
(skip-chars-backward " \t\n"))
(unless (= (point) (point-min))
(if (looking-back "\\sw")
(skip-syntax-backward "w")
(if (re-search-backward "\n\\|\\s-\\|\\sw" nil t)
(forward-char)
(goto-char (point-min))))))))
(defun reluctant-backward (&optional arg)
"Move point to the beginning of the previous word or string of
non-word-constituent characters.
Do it ARG times if ARG is positive, or -ARG times in the opposite
direction if ARG is negative. ARG defaults to 1."
(interactive "^p")
(reluctant-forward (- arg)))
Stops (starting from the beginning, and using reluctant-forward
with positive ARG
):
int| main|(|int| argc|,| char| *|args|[])|
{|
int| a| =| 45|;|
printf|("%|i|",| a|);|
}|