config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

lsp-iedit.el (5283B)


      1 ;;; lsp-iedit.el --- `iedit' integration -*- lexical-binding: t -*-
      2 ;;
      3 ;; Copyright (C) 2020 emacs-lsp maintainers
      4 ;;
      5 ;; This program is free software; you can redistribute it and/or modify
      6 ;; it under the terms of the GNU General Public License as published by
      7 ;; the Free Software Foundation, either version 3 of the License, or
      8 ;; (at your option) any later version.
      9 
     10 ;; This program is distributed in the hope that it will be useful,
     11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 ;; GNU General Public License for more details.
     14 
     15 ;; You should have received a copy of the GNU General Public License
     16 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     17 
     18 ;;; Commentary:
     19 
     20 ;; This module provides features that allow starting `iedit' on various
     21 ;; different lsp-based, semantic units (like documentHighlights, and
     22 ;; linkedEditingRanges in the future).
     23 
     24 ;;; Code:
     25 
     26 (require 'lsp-mode)
     27 (require 'dash)
     28 
     29 (declare-function iedit-make-occurrence-overlay "iedit-lib" (begin end))
     30 (declare-function iedit-start-buffering "iedit-lib" ())
     31 (declare-function iedit-lib-start "iedit-lib" (mode-exit-func))
     32 (declare-function iedit-done "iedit" ())
     33 (declare-function evil-multiedit-mode "evil-multiedit" (mode))
     34 (declare-function evil-iedit-state "evil-iedit-state" ())
     35 
     36 (defvar iedit-mode)
     37 (defvar iedit-auto-buffering)
     38 (defvar iedit-occurrences-overlays)
     39 (defvar iedit-occurrence-keymap)
     40 (defvar iedit-mode-occurrence-keymap)
     41 (defvar evil-multiedit--dont-recall)
     42 
     43 (defun lsp-iedit--on-ranges (ranges)
     44   "Start an `iedit' operation using RANGES.
     45 RANGES shall be a list of lsp-`&Range's. They can be acquired
     46 from various lsp protocol requests, e.g.
     47 `textDocument/documentHighlight', ...."
     48   (require 'iedit)
     49   (unless (seq-empty-p ranges)
     50     (mapc (-lambda ((&RangeToPoint :start :end))
     51             (push (iedit-make-occurrence-overlay start end)
     52                   iedit-occurrences-overlays))
     53           ranges)
     54     ;; See `iedit-start'; TODO: upstream this
     55     (setq iedit-occurrence-keymap iedit-mode-occurrence-keymap)
     56     (setq iedit-mode t)
     57     (when iedit-auto-buffering
     58       (iedit-start-buffering))
     59     (iedit-lib-start 'iedit-done)
     60     (run-hooks 'iedit-mode-hook)
     61     (add-hook 'before-revert-hook 'iedit-done nil t)
     62     (add-hook 'kbd-macro-termination-hook 'iedit-done nil t)
     63     (add-hook 'change-major-mode-hook 'iedit-done nil t)
     64     (add-hook 'iedit-aborting-hook 'iedit-done nil t)
     65     (message "%d occurrences of \"%s\""
     66              (seq-length ranges)
     67              (lsp--range-text (lsp-seq-first ranges)))))
     68 
     69 ;; iedit
     70 
     71 ;;;###autoload
     72 (defun lsp-iedit-highlights ()
     73   "Start an `iedit' operation on the documentHighlights at point.
     74 This can be used as a primitive `lsp-rename' replacement if the
     75 language server doesn't support renaming.
     76 
     77 See also `lsp-enable-symbol-highlighting'."
     78   (interactive)
     79   (let ((highlights (lsp-request "textDocument/documentHighlight"
     80                                  (lsp--text-document-position-params)))
     81         (-compare-fn (-lambda ((&Location :range (&Range :start l-start :end l-end))
     82                                (&Location :range (&Range :start r-start :end r-end)))
     83                        (and (lsp--position-equal l-start r-start)
     84                             (lsp--position-equal l-end   r-end)))))
     85     (lsp-iedit--on-ranges (mapcar #'lsp:document-highlight-range (-distinct highlights)))))
     86 
     87 ;;;###autoload
     88 (defun lsp-iedit-linked-ranges ()
     89   "Start an `iedit' for `textDocument/linkedEditingRange'"
     90   (interactive)
     91   (unless (lsp-feature? "textDocument/linkedEditingRange")
     92     (user-error "`textDocument/linkedEditingRange' is not supported by current server"))
     93 
     94   (-> (lsp-request "textDocument/linkedEditingRange" (lsp--text-document-position-params))
     95       (lsp:linked-editing-ranges-ranges)
     96       (or (user-error "No editing ranges found"))
     97       (lsp-iedit--on-ranges)))
     98 
     99 
    100 ;; evil-multi-edit
    101 
    102 ;;;###autoload
    103 (defun lsp-evil-multiedit-highlights ()
    104   "Start an `evil-multiedit' operation on the documentHighlights at point.
    105 This can be used as a primitive `lsp-rename' replacement if the
    106 language server doesn't support renaming.
    107 
    108 See also `lsp-enable-symbol-highlighting'."
    109   (interactive)
    110   (require 'evil-multiedit)
    111   (when (fboundp 'ahs-clear) (ahs-clear))
    112   (setq evil-multiedit--dont-recall t)
    113   (lsp-iedit-highlights)
    114   (evil-multiedit-mode +1))
    115 
    116 ;;;###autoload
    117 (defun lsp-evil-multiedit-linked-ranges ()
    118   "Start an `evil-multiedit' for `textDocument/linkedEditingRange'"
    119   (interactive)
    120   (require 'evil-multiedit)
    121   (when (fboundp 'ahs-clear) (ahs-clear))
    122   (setq evil-multiedit--dont-recall t)
    123   (lsp-iedit-linked-ranges)
    124   (evil-multiedit-mode +1))
    125 
    126 ;; evil-evil-state
    127 
    128 ;;;###autoload
    129 (defun lsp-evil-state-highlights ()
    130   "Start `iedit-mode'. for `textDocument/documentHighlight'"
    131   (interactive "P")
    132   (if (fboundp 'ahs-clear) (ahs-clear))
    133   (lsp-iedit-highlights)
    134   (evil-iedit-state))
    135 
    136 ;;;###autoload
    137 (defun lsp-evil-state-linked-ranges ()
    138   "Start `iedit-mode'. for `textDocument/linkedEditingRange'"
    139   (interactive "P")
    140   (if (fboundp 'ahs-clear) (ahs-clear))
    141   (lsp-iedit-linked-ranges)
    142   (evil-iedit-state))
    143 
    144 
    145 
    146 (lsp-consistency-check lsp-iedit)
    147 
    148 (provide 'lsp-iedit)
    149 ;;; lsp-iedit.el ends here