4

I was not satisfied with the behavior of standard C-arrow and C-S-arrow, so I wrote this functions to replace standard ones.

(setq separators-regexp "[\-'\"();:,.\\/?!@#%&*+=]")

(defun forward-to-separator()
    "Move to the next separator like in the every NORMAL editor"
    (interactive)
    (let ((my-pos (re-search-forward separators-regexp)))
        (goto-char my-pos)))

(defun backward-to-separator()
    "Move to the previous separator like in the every NORMAL editor"
    (interactive)
    (let ((my-pos (re-search-backward separators-regexp)))
        (goto-char my-pos)))

(global-set-key (kbd "C-<right>") 'forward-to-separator)
(global-set-key (kbd "C-<left>") 'backward-to-separator)

But now I am facing a problem with shift selection: it actually just not working at all. So my question is: how can I select text using my new functions and shift key(C-S-arrow)?

My final code is here: https://gist.github.com/FirstTimeInForever/8303ac1918c81365991d7acf7a926bd8 I added C-<backspace> support and changed my regex. Now I can move cursor like in sublime text!

3
  • Why not just set a mark (C-<SPC>) from where you want to select and proceed to use your cursor movement functions? Aug 20, 2016 at 14:32
  • I know I can set a mark, but selecting text with shift is more comfortable for me.
    – user13047
    Aug 20, 2016 at 14:40
  • Excelent, do you know how to implement jumps over black characters ?
    – dev1223
    Nov 26, 2017 at 21:47

2 Answers 2

2

Use (interactive "^") instead of (interactive).

C-h f interactive tells you, way down near the bottom:

If the string begins with ^ and shift-select-mode is non-nil, Emacs first calls the function handle-shift-selection.

In your case, the commands do not take an argument. But you can still use a string argument to interactive, in this case "^", to make the command respect shift selection.

0
0

I upgraded your code so cursor navigation is now behaving a lot better then default setting in Atom editor. Mainly I added skipping blank spaces in file.

I highly recommend binding those to C-<right> and C-<left> because in CUA mode, C-S-<right> and C-S-<left> is automatically binded to skipped text selection so you can easily copy/remove as in other editors.

(require 'cl-macs)

(setq custom/separators-regexp
      "\\([]['\"(){};:,.\\/?!@#%&*+=^[:space:]\n-]\\|\\s_\\|\\`\\|‌​‌​\\'\\)")

(defun custom/position-normalize-forward (saved-pos my-pos)
  (if (>= (- my-pos saved-pos) 2)
      (progn
        (goto-char my-pos)
        (if (not (eq my-pos (point-max)))
            (progn
              (custom/backward-symbol))))
    (progn
      (goto-char my-pos))))

(defun custom/forward-symbol ()
  (interactive "^")
  (block custom/forward-symbol
    (let* ((saved-pos (point))
           (my-pos (re-search-forward custom/separators-regexp))
           (my-pos2 (custom/find-blank-space t saved-pos)))
      (if (> my-pos2 my-pos)
          (progn
            (goto-char (- my-pos2 1))
            (return-from custom/forward-symbol)))
      (if (eq my-pos 1)
          (progn
            (goto-char (+ my-pos 1))
            (setf my-pos (re-search-forward custom/separators-regexp))
            (custom/position-normalize-forward saved-pos my-pos))
        (custom/position-normalize-forward saved-pos my-pos)))))


(defun custom/position-normalize-backward (saved-pos my-pos)
  (if (>= (- saved-pos my-pos) 2)
      (progn
        (goto-char my-pos)
        (if (not (eq my-pos 1))
            (progn
              (custom/forward-symbol))))
    (progn
      (goto-char my-pos))))

(defun custom/backward-symbol ()
  (interactive "^")
  (block custom/backward-symbol
    (let* ((saved-pos (point))
           (my-pos (re-search-backward custom/separators-regexp))
           (my-pos2 (custom/find-blank-space nil saved-pos)))
      (if (< my-pos2 my-pos)
          (progn
            (goto-char (+ my-pos2 1))
            (return-from custom/backward-symbol)))
      (if (eq my-pos (point-max))
          (progn
            (goto-char (- my-pos 1))
            (setf my-pos (re-search-backward custom/separators-regexp))
            (custom/position-normalize-backward saved-pos my-pos))
        (custom/position-normalize-backward saved-pos my-pos)))))

(defun custom/find-blank-space (go-forward starting-pos)
  (let ((starting-char (string (char-after starting-pos)))
        (skipped-count 0)
        (increment (if go-forward 1 -1))
        (should-loop t))
    (if (or (equal starting-char " ")
            (equal starting-char "\t")
            (equal starting-char "\n"))
        (progn
          (while should-loop
            (if (or (equal (string (char-after (+ saved-pos skipped-count))) " ")
                    (equal (string (char-after (+ saved-pos skipped-count))) "\t")
                    (equal (string (char-after (+ saved-pos skipped-count))) "\n"))
                (setq skipped-count (+ skipped-count increment))
              (setq should-loop nil)))
          (+ starting-pos skipped-count))
      starting-pos)))

Hope it will help.

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.