Guest User

Untitled

a guest
May 27th, 2022
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 21.63 KB | None | 0 0
  1. (defun perform-replace-with-info (from-string replacements
  2.                           query-flag regexp-flag INFO-STRING  delimited-flag
  3.                           &optional repeat-count map start end backward region-noncontiguous-p)
  4.   "Versione modificata per accettare una stringa di spiegazione
  5. `info-string' per dare informazioni all'utente in merito alle
  6. sostituzioni che gli viene richiesto di valutare.
  7.  
  8. Per maggiori dettagli fare riferimento alla documentazione di `perform-replace'."
  9.   (or map (setq map query-replace-map))
  10.   (and query-flag minibuffer-auto-raise
  11.        (raise-frame (window-frame (minibuffer-window))))
  12.   (let* ((case-fold-search
  13.       (if (and case-fold-search search-upper-case)
  14.           (isearch-no-upper-case-p from-string regexp-flag)
  15.         case-fold-search))
  16.          (nocasify (not (and case-replace case-fold-search)))
  17.          (literal (or (not regexp-flag) (eq regexp-flag 'literal)))
  18.          (search-string from-string)
  19.          (real-match-data nil)       ; The match data for the current match.
  20.          (next-replacement nil)
  21.          ;; This is non-nil if we know there is nothing for the user
  22.          ;; to edit in the replacement.
  23.          (noedit nil)
  24.          (keep-going t)
  25.          (stack nil)
  26.          (search-string-replaced nil)    ; last string matching `from-string'
  27.          (next-replacement-replaced nil) ; replacement string
  28.                     ; (substituted regexp)
  29.          (last-was-undo)
  30.          (last-was-act-and-show)
  31.          (update-stack t)
  32.          (replace-count 0)
  33.          (skip-read-only-count 0)
  34.          (skip-filtered-count 0)
  35.          (skip-invisible-count 0)
  36.          (nonempty-match nil)
  37.      (multi-buffer nil)
  38.      (recenter-last-op nil) ; Start cycling order with initial position.
  39.  
  40.          ;; If non-nil, it is marker saying where in the buffer to stop.
  41.          (limit nil)
  42.          ;; Use local binding in add-function below.
  43.          (isearch-filter-predicate isearch-filter-predicate)
  44.          (region-bounds nil)
  45.  
  46.          ;; Data for the next match.  If a cons, it has the same format as
  47.          ;; (match-data); otherwise it is t if a match is possible at point.
  48.          (match-again t)
  49.  
  50.  
  51.      ;; *THE MAGIC*
  52.      ;; Aggiungo una stringa di spiegazione per dare informazioni
  53.      ;; all'utente in merito alle sostituzioni che gli viene
  54.      ;; richiesto di valutare:
  55.      (info-string (if INFO-STRING
  56.               (propertize
  57.                (concat INFO-STRING "\n\n")
  58.                'face '(:foreground "goldenrod"
  59.                            ;; :background "DarkGoldenrod1"
  60.                            ))
  61.             ""))
  62.          (message
  63.           (if query-flag
  64.           (concat ; <-- The magic
  65.            info-string ; <--
  66.            (apply 'propertize
  67.               (substitute-command-keys
  68.                "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")
  69.               minibuffer-prompt-properties)))))
  70.  
  71.     ;; Unless a single contiguous chunk is selected, operate on multiple chunks.
  72.     (when region-noncontiguous-p
  73.       (setq region-bounds
  74.             (mapcar (lambda (position)
  75.                       (cons (copy-marker (car position))
  76.                             (copy-marker (cdr position))))
  77.                     (funcall region-extract-function 'bounds)))
  78.       (add-function :after-while isearch-filter-predicate
  79.                     (lambda (start end)
  80.                       (delq nil (mapcar
  81.                                  (lambda (bounds)
  82.                                    (and
  83.                                     (>= start (car bounds))
  84.                                     (<= start (cdr bounds))
  85.                                     (>= end   (car bounds))
  86.                                     (<= end   (cdr bounds))))
  87.                                  region-bounds)))))
  88.  
  89.     ;; If region is active, in Transient Mark mode, operate on region.
  90.     (if backward
  91.     (when end
  92.       (setq limit (copy-marker (min start end)))
  93.       (goto-char (max start end))
  94.       (deactivate-mark))
  95.       (when start
  96.     (setq limit (copy-marker (max start end)))
  97.     (goto-char (min start end))
  98.     (deactivate-mark)))
  99.  
  100.     ;; If last typed key in previous call of multi-buffer perform-replace
  101.     ;; was `automatic-all', don't ask more questions in next files
  102.     (when (eq (lookup-key map (vector last-input-event)) 'automatic-all)
  103.       (setq query-flag nil multi-buffer t))
  104.  
  105.     (cond
  106.      ((stringp replacements)
  107.       (setq next-replacement replacements
  108.             replacements     nil))
  109.      ((stringp (car replacements)) ; If it isn't a string, it must be a cons
  110.       (or repeat-count (setq repeat-count 1))
  111.       (setq replacements (cons 'replace-loop-through-replacements
  112.                                (vector repeat-count repeat-count
  113.                                        replacements replacements)))))
  114.  
  115.     (when query-replace-lazy-highlight
  116.       (setq isearch-lazy-highlight-last-string nil))
  117.  
  118.     (push-mark)
  119.     (undo-boundary)
  120.     (unwind-protect
  121.     ;; Loop finding occurrences that perhaps should be replaced.
  122.     (while (and keep-going
  123.             (if backward
  124.             (not (or (bobp) (and limit (<= (point) limit))))
  125.               (not (or (eobp) (and limit (>= (point) limit)))))
  126.             ;; Use the next match if it is already known;
  127.             ;; otherwise, search for a match after moving forward
  128.             ;; one char if progress is required.
  129.             (setq real-match-data
  130.               (cond ((consp match-again)
  131.                  (goto-char (if backward
  132.                         (nth 0 match-again)
  133.                           (nth 1 match-again)))
  134.                  (replace-match-data
  135.                   t real-match-data match-again))
  136.                 ;; MATCH-AGAIN non-nil means accept an
  137.                 ;; adjacent match.
  138.                 (match-again
  139.                  (and
  140.                   (replace-search search-string limit
  141.                           regexp-flag delimited-flag
  142.                           case-fold-search backward)
  143.                   ;; For speed, use only integers and
  144.                   ;; reuse the list used last time.
  145.                   (replace-match-data t real-match-data)))
  146.                 ((and (if backward
  147.                       (> (1- (point)) (point-min))
  148.                     (< (1+ (point)) (point-max)))
  149.                       (or (null limit)
  150.                       (if backward
  151.                           (> (1- (point)) limit)
  152.                         (< (1+ (point)) limit))))
  153.                  ;; If not accepting adjacent matches,
  154.                  ;; move one char to the right before
  155.                  ;; searching again.  Undo the motion
  156.                  ;; if the search fails.
  157.                  (let ((opoint (point)))
  158.                    (forward-char (if backward -1 1))
  159.                    (if (replace-search search-string limit
  160.                                regexp-flag delimited-flag
  161.                                case-fold-search backward)
  162.                        (replace-match-data
  163.                     t real-match-data)
  164.                      (goto-char opoint)
  165.                      nil))))))
  166.  
  167.       ;; Record whether the match is nonempty, to avoid an infinite loop
  168.       ;; repeatedly matching the same empty string.
  169.       (setq nonempty-match
  170.         (/= (nth 0 real-match-data) (nth 1 real-match-data)))
  171.  
  172.       ;; If the match is empty, record that the next one can't be
  173.       ;; adjacent.
  174.  
  175.       ;; Otherwise, if matching a regular expression, do the next
  176.       ;; match now, since the replacement for this match may
  177.       ;; affect whether the next match is adjacent to this one.
  178.       ;; If that match is empty, don't use it.
  179.       (setq match-again
  180.         (and nonempty-match
  181.              (or (not regexp-flag)
  182.              (and (if backward
  183.                   (looking-back search-string nil)
  184.                 (looking-at search-string))
  185.                   (let ((match (match-data)))
  186.                 (and (/= (nth 0 match) (nth 1 match))
  187.                      match))))))
  188.  
  189.       (cond
  190.        ;; Optionally ignore matches that have a read-only property.
  191.        ((not (or (not query-replace-skip-read-only)
  192.              (not (text-property-not-all
  193.                (nth 0 real-match-data) (nth 1 real-match-data)
  194.                'read-only nil))))
  195.         (setq skip-read-only-count (1+ skip-read-only-count)))
  196.        ;; Optionally filter out matches.
  197.        ((not (funcall isearch-filter-predicate
  198.                           (nth 0 real-match-data) (nth 1 real-match-data)))
  199.         (setq skip-filtered-count (1+ skip-filtered-count)))
  200.        ;; Optionally ignore invisible matches.
  201.        ((not (or (eq search-invisible t)
  202.              ;; Don't open overlays for automatic replacements.
  203.              (and (not query-flag) search-invisible)
  204.              ;; Open hidden overlays for interactive replacements.
  205.              (not (isearch-range-invisible
  206.                (nth 0 real-match-data) (nth 1 real-match-data)))))
  207.         (setq skip-invisible-count (1+ skip-invisible-count)))
  208.        (t
  209.         ;; Calculate the replacement string, if necessary.
  210.         (when replacements
  211.           (set-match-data real-match-data)
  212.           (setq next-replacement
  213.             (funcall (car replacements) (cdr replacements)
  214.                  replace-count)))
  215.         (if (not query-flag)
  216.         (progn
  217.           (unless (or literal noedit)
  218.             (replace-highlight
  219.              (nth 0 real-match-data) (nth 1 real-match-data)
  220.              start end search-string
  221.              regexp-flag delimited-flag case-fold-search backward))
  222.           (setq noedit
  223.             (replace-match-maybe-edit
  224.              next-replacement nocasify literal
  225.              noedit real-match-data backward)
  226.             replace-count (1+ replace-count)))
  227.           (undo-boundary)
  228.           (let (done replaced key def)
  229.         ;; Loop reading commands until one of them sets done,
  230.         ;; which means it has finished handling this
  231.         ;; occurrence.  Any command that sets `done' should
  232.         ;; leave behind proper match data for the stack.
  233.         ;; Commands not setting `done' need to adjust
  234.         ;; `real-match-data'.
  235.         (while (not done)
  236.           (set-match-data real-match-data)
  237.                   (run-hooks 'replace-update-post-hook) ; Before `replace-highlight'.
  238.                   (replace-highlight
  239.            (match-beginning 0) (match-end 0)
  240.            start end search-string
  241.            regexp-flag delimited-flag case-fold-search backward)
  242.                   ;; Obtain the matched groups: needed only when
  243.                   ;; regexp-flag non nil.
  244.                   (when (and last-was-undo regexp-flag)
  245.                     (setq last-was-undo nil
  246.                           real-match-data
  247.                           (save-excursion
  248.                             (goto-char (match-beginning 0))
  249.                             (looking-at search-string)
  250.                             (match-data t real-match-data))))
  251.                   ;; Matched string and next-replacement-replaced
  252.                   ;; stored in stack.
  253.                   (setq search-string-replaced (buffer-substring-no-properties
  254.                                                 (match-beginning 0)
  255.                                                 (match-end 0))
  256.                         next-replacement-replaced
  257.                         (query-replace-descr
  258.                          (save-match-data
  259.                            (set-match-data real-match-data)
  260.                            (match-substitute-replacement
  261.                             next-replacement nocasify literal))))
  262.           ;; Bind message-log-max so we don't fill up the
  263.           ;; message log with a bunch of identical messages.
  264.           (let ((message-log-max nil)
  265.             (replacement-presentation
  266.              (if query-replace-show-replacement
  267.                  (save-match-data
  268.                    (set-match-data real-match-data)
  269.                    (match-substitute-replacement next-replacement
  270.                                  nocasify literal))
  271.                next-replacement)))
  272.             (message message
  273.                              (query-replace-descr from-string)
  274.                              (query-replace-descr replacement-presentation)))
  275.           (setq key (read-event))
  276.           ;; Necessary in case something happens during
  277.           ;; read-event that clobbers the match data.
  278.           (set-match-data real-match-data)
  279.           (setq key (vector key))
  280.           (setq def (lookup-key map key))
  281.           ;; Restore the match data while we process the command.
  282.           (cond ((eq def 'help)
  283.              (with-output-to-temp-buffer "*Help*"
  284.                (princ
  285.                 (concat "Query replacing "
  286.                     (if delimited-flag
  287.                     (or (and (symbolp delimited-flag)
  288.                          (get delimited-flag
  289.                                                       'isearch-message-prefix))
  290.                         "word ") "")
  291.                     (if regexp-flag "regexp " "")
  292.                     (if backward "backward " "")
  293.                     from-string " with "
  294.                     next-replacement ".\n\n"
  295.                     (substitute-command-keys
  296.                      query-replace-help)))
  297.                (with-current-buffer standard-output
  298.                  (help-mode))))
  299.             ((eq def 'exit)
  300.              (setq keep-going nil)
  301.              (setq done t))
  302.             ((eq def 'exit-current)
  303.              (setq multi-buffer t keep-going nil done t))
  304.             ((eq def 'backup)
  305.              (if stack
  306.                  (let ((elt (pop stack)))
  307.                    (goto-char (nth 0 elt))
  308.                    (setq replaced (nth 1 elt)
  309.                      real-match-data
  310.                      (replace-match-data
  311.                       t real-match-data
  312.                       (nth 2 elt))))
  313.                (message "No previous match")
  314.                (ding 'no-terminate)
  315.                (sit-for 1)))
  316.             ((or (eq def 'undo) (eq def 'undo-all))
  317.              (if (null stack)
  318.                              (progn
  319.                                (message "Nothing to undo")
  320.                                (ding 'no-terminate)
  321.                                (sit-for 1))
  322.                (let ((stack-idx         0)
  323.                                  (stack-len         (length stack))
  324.                                  (num-replacements  0)
  325.                                  (nocasify t) ; Undo must preserve case (Bug#31073).
  326.                                  search-string
  327.                                  next-replacement)
  328.                              (while (and (< stack-idx stack-len)
  329.                                          stack
  330.                                          (or (null replaced) last-was-act-and-show))
  331.                                (let* ((elt (nth stack-idx stack)))
  332.                                  (setq
  333.                                   stack-idx (1+ stack-idx)
  334.                                   replaced (nth 1 elt)
  335.                                   ;; Bind swapped values
  336.                                   ;; (search-string <--> replacement)
  337.                                   search-string (nth (if replaced 4 3) elt)
  338.                                   next-replacement (nth (if replaced 3 4) elt)
  339.                                   search-string-replaced search-string
  340.                                   next-replacement-replaced next-replacement
  341.                                   last-was-act-and-show nil)
  342.  
  343.                                  (when (and (= stack-idx stack-len)
  344.                                             (and (null replaced) (not last-was-act-and-show))
  345.                                             (zerop num-replacements))
  346.                    (message "Nothing to undo")
  347.                    (ding 'no-terminate)
  348.                    (sit-for 1))
  349.  
  350.                                  (when replaced
  351.                                    (setq stack (nthcdr stack-idx stack))
  352.                                    (goto-char (nth 0 elt))
  353.                                    (set-match-data (nth 2 elt))
  354.                                    (setq real-match-data
  355.                                          (save-excursion
  356.                                            (goto-char (match-beginning 0))
  357.                                            ;; We must quote the string (Bug#37073)
  358.                                            (looking-at (regexp-quote search-string))
  359.                                            (match-data t (nth 2 elt)))
  360.                                          noedit
  361.                                          (replace-match-maybe-edit
  362.                                           next-replacement nocasify literal
  363.                                           noedit real-match-data backward)
  364.                                          replace-count (1- replace-count)
  365.                                          real-match-data
  366.                                          (save-excursion
  367.                                            (goto-char (match-beginning 0))
  368.                                            (if regexp-flag
  369.                                                (looking-at next-replacement)
  370.                                              (looking-at (regexp-quote next-replacement)))
  371.                                            (match-data t (nth 2 elt))))
  372.                                    ;; Set replaced nil to keep in loop
  373.                                    (when (eq def 'undo-all)
  374.                                      (setq replaced nil
  375.                                            stack-len (- stack-len stack-idx)
  376.                                            stack-idx 0
  377.                                            num-replacements
  378.                                            (1+ num-replacements))))))
  379.                              (when (and (eq def 'undo-all)
  380.                                         (null (zerop num-replacements)))
  381.                                (message "Undid %d %s" num-replacements
  382.                                         (if (= num-replacements 1)
  383.                                             "replacement"
  384.                                           "replacements"))
  385.                                (ding 'no-terminate)
  386.                                (sit-for 1)))
  387.                (setq replaced nil last-was-undo t last-was-act-and-show nil)))
  388.             ((eq def 'act)
  389.              (or replaced
  390.                  (setq noedit
  391.                    (replace-match-maybe-edit
  392.                     next-replacement nocasify literal
  393.                     noedit real-match-data backward)
  394.                    replace-count (1+ replace-count)))
  395.              (setq done t replaced t update-stack (not last-was-act-and-show)))
  396.             ((eq def 'act-and-exit)
  397.              (or replaced
  398.                  (setq noedit
  399.                    (replace-match-maybe-edit
  400.                     next-replacement nocasify literal
  401.                     noedit real-match-data backward)
  402.                    replace-count (1+ replace-count)))
  403.              (setq keep-going nil)
  404.              (setq done t replaced t))
  405.             ((eq def 'act-and-show)
  406.              (unless replaced
  407.                (setq noedit
  408.                  (replace-match-maybe-edit
  409.                   next-replacement nocasify literal
  410.                   noedit real-match-data backward)
  411.                  replace-count (1+ replace-count)
  412.                  real-match-data (replace-match-data
  413.                           t real-match-data)
  414.                  replaced t last-was-act-and-show t)
  415.                (replace--push-stack
  416.                  replaced
  417.                  search-string-replaced
  418.                  next-replacement-replaced stack)))
  419.             ((or (eq def 'automatic) (eq def 'automatic-all))
  420.              (or replaced
  421.                  (setq noedit
  422.                    (replace-match-maybe-edit
  423.                     next-replacement nocasify literal
  424.                     noedit real-match-data backward)
  425.                    replace-count (1+ replace-count)))
  426.              (setq done t query-flag nil replaced t)
  427.              (if (eq def 'automatic-all) (setq multi-buffer t)))
  428.             ((eq def 'skip)
  429.              (setq done t update-stack (not last-was-act-and-show)))
  430.             ((eq def 'recenter)
  431.              ;; `this-command' has the value `query-replace',
  432.              ;; so we need to bind it to `recenter-top-bottom'
  433.              ;; to allow it to detect a sequence of `C-l'.
  434.              (let ((this-command 'recenter-top-bottom)
  435.                    (last-command 'recenter-top-bottom))
  436.                (recenter-top-bottom)))
  437.             ((eq def 'edit)
  438.              (let ((opos (point-marker)))
  439.                (setq real-match-data (replace-match-data
  440.                           nil real-match-data
  441.                           real-match-data))
  442.                (goto-char (match-beginning 0))
  443.                (save-excursion
  444.                  (save-window-excursion
  445.                    (recursive-edit)))
  446.                (goto-char opos)
  447.                (set-marker opos nil))
  448.              ;; Before we make the replacement,
  449.              ;; decide whether the search string
  450.              ;; can match again just after this match.
  451.              (if (and regexp-flag nonempty-match)
  452.                  (setq match-again (and (looking-at search-string)
  453.                             (match-data)))))
  454.             ;; Edit replacement.
  455.             ((eq def 'edit-replacement)
  456.              (setq real-match-data (replace-match-data
  457.                         nil real-match-data
  458.                         real-match-data)
  459.                    next-replacement
  460.                    (read-string "Edit replacement string: "
  461.                                             next-replacement)
  462.                    noedit nil)
  463.              (if replaced
  464.                  (set-match-data real-match-data)
  465.                (setq noedit
  466.                  (replace-match-maybe-edit
  467.                   next-replacement nocasify literal noedit
  468.                   real-match-data backward)
  469.                  replaced t)
  470.                (setq next-replacement-replaced next-replacement))
  471.              (setq done t))
  472.  
  473.             ((eq def 'delete-and-edit)
  474.              (replace-match "" t t)
  475.              (setq real-match-data (replace-match-data
  476.                         nil real-match-data))
  477.              (replace-dehighlight)
  478.              (save-excursion (recursive-edit))
  479.              (setq replaced t))
  480.             ;; Note: we do not need to treat `exit-prefix'
  481.             ;; specially here, since we reread
  482.             ;; any unrecognized character.
  483.             (t
  484.              (setq this-command 'mode-exited)
  485.              (setq keep-going nil)
  486.              (setq unread-command-events
  487.                    (append (listify-key-sequence key)
  488.                        unread-command-events))
  489.              (setq done t)))
  490.           (when query-replace-lazy-highlight
  491.             ;; Force lazy rehighlighting only after replacements.
  492.             (if (not (memq def '(skip backup)))
  493.             (setq isearch-lazy-highlight-last-string nil)))
  494.           (unless (eq def 'recenter)
  495.             ;; Reset recenter cycling order to initial position.
  496.             (setq recenter-last-op nil)))
  497.         ;; Record previous position for ^ when we move on.
  498.         ;; Change markers to numbers in the match data
  499.         ;; since lots of markers slow down editing.
  500.                 (when update-stack
  501.                   (replace--push-stack
  502.             replaced
  503.             search-string-replaced
  504.             next-replacement-replaced stack))
  505.                 (setq next-replacement-replaced nil
  506.                       search-string-replaced    nil
  507.                       last-was-act-and-show     nil))))))
  508.       (replace-dehighlight))
  509.     (or unread-command-events
  510.     (message "Replaced %d occurrence%s%s"
  511.          replace-count
  512.          (if (= replace-count 1) "" "s")
  513.          (if (> (+ skip-read-only-count
  514.                skip-filtered-count
  515.                skip-invisible-count) 0)
  516.              (format " (skipped %s)"
  517.                  (mapconcat
  518.                   'identity
  519.                   (delq nil (list
  520.                      (if (> skip-read-only-count 0)
  521.                          (format "%s read-only"
  522.                              skip-read-only-count))
  523.                      (if (> skip-invisible-count 0)
  524.                          (format "%s invisible"
  525.                              skip-invisible-count))
  526.                      (if (> skip-filtered-count 0)
  527.                          (format "%s filtered out"
  528.                              skip-filtered-count))))
  529.                   ", "))
  530.            "")))
  531.     (or (and keep-going stack) multi-buffer)))
Advertisement
Add Comment
Please, Sign In to add comment