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!

2 Answers2

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.

Drew
  • 75,699
  • 9
  • 109
  • 225
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.

dev1223
  • 241
  • 1
  • 10