gabesoft / evil-mc

Multiple cursors implementation for evil-mode
MIT License
383 stars 35 forks source link

[Question] how to make this function work for multiple cursors? #125

Open adasium opened 2 years ago

adasium commented 2 years ago

Here the function chom/toggle-thing replaces using regexp matches defined in chom/toggle-thing-alist. For exmaple (visual . ("test" . "tested")) says: in visual mode check if selected region is equal to "test" and replace it with "tested".

I don't know if there is some function that is not compatible with evil-mc or there's something else I'm missing. I tried modifying evil-mc-custom-known-commands with different functions like evil-mc-execute-call-with-region-or-pos but it didn't produce expected result.

To reproduce: select two words "test" - one with real and one with fake cursor press C-l (my binding) or interactively call chom/toggle-thing.

Expected result: both "test" are changed to "tested"

Actual result: real cursor's "test" changed to "tested", fake cursor's "test" stayed as is

  (defun chom/toggle-thing/get ()
    (when (evil-normal-state-p)
      (evil-visual-state)
      (evil-find-char 1 (string-to-char ")"))
      (evil-forward-char)  ;; don't know why but it works
      (exchange-point-and-mark)
      (evil-find-char-backward 1 (string-to-char "."))
      (activate-mark)))

  (setq chom/pre-toggle-thing-alist '(
                                      (symbol . ("get" . chom/toggle-thing/get))
                                      ))
  (setq chom/toggle-thing-alist '(
                                  (symbol . ("True" . "False"))
                                  (symbol . ("False" . "True"))
                                  (visual . ("test" . "tested"))
                                  (visual . ("\\[\\(.*\\)\\]" . ".get(\\1)"))
                                  (visual . (".get(\\(.*\\),.*)" . "[\\1]"))
                                  (visual . (".get(\\(.*\\))" . "[\\1]"))
                                  ))

  (defun chom/toggle-thing--find-match (source &optional beg end)
    (let ((beg (or beg (region-beginning)))
          (end (or end (region-end))))
      (setq deactivate-mark nil)
      (find-if (lambda (x) (or (and
                                (equal (car x) 'visual)
                                (use-region-p)
                                (string-match (cadr x)
                                              (buffer-substring-no-properties beg end)))
                               (and (thing-at-point (car x))
                                    (string-match (cadr x) (thing-at-point (car x))))))
               source)))

  (defun chom/toggle-thing ()
    "https://github.com/dalanicolai/dala-emacs-lisp/blob/master/evil-switch.el"
    (interactive)
    (let ((beg (region-beginning))
          (end (region-end))
          (pre-action (chom/toggle-thing--find-match chom/pre-toggle-thing-alist)))
      (if pre-action
          (funcall (cddr pre-action)))
      (let* ((beg (region-beginning))
             (end (region-end))
             (match (chom/toggle-thing--find-match chom/toggle-thing-alist beg end)))
        (if match
            (progn
              (let ((bounds (if (and (equal (car match) 'visual) (use-region-p))
                                (cons beg end)
                              (bounds-of-thing-at-point (car match)))))
                (goto-char (car bounds))
                (setq deactivate-mark  nil)
                (if (re-search-forward (cadr match) (cdr bounds) nil)
                    (replace-match (cddr match)))))))))
  (bind-key "C-l" 'chom/toggle-thing)