case-fold-search)))
(string-match-p regexp string)))
-(defun el-search--print (expr)
- (let ((print-quoted t)
- (print-length nil)
+(defun el-search--pp-to-string (expr)
+ (let ((print-length nil)
(print-level nil))
- (prin1-to-string expr)))
+ (pp-to-string expr)))
(defvar el-search-read-expression-map
(let ((map (make-sparse-keymap)))
(use-local-map el-search-read-expression-map)
(setq font-lock-mode t)
(funcall font-lock-function 1)
- (backward-sexp)
- (indent-sexp)
+ (goto-char (minibuffer-prompt-end))
+ (when (looking-at ".*\n")
+ (indent-sexp))
(goto-char (point-max))
(when-let ((this-sexp (with-current-buffer (window-buffer (minibuffer-selected-window))
(thing-at-point 'sexp))))
(or hist 'read-expression-history) default)))
(defvar el-search-history '()
- "List of input strings.")
+ "List of search input strings.")
+
+(defvar el-search-query-replace-history '()
+ "List of input strings from `el-search-query-replace'.")
(defvar el-search--initial-mb-contents nil)
-(defun el-search--read-pattern (prompt &optional default read)
+(defun el-search--read-pattern (prompt &optional default read histvar)
+ (cl-callf or histvar 'el-search-history)
(let ((input (el-search-read-expression
- prompt el-search--initial-mb-contents 'el-search-history default read)))
- (if (or read (not (string= input ""))) input (car el-search-history))))
+ prompt el-search--initial-mb-contents histvar default read)))
+ (if (or read (not (string= input ""))) input (car (symbol-value histvar)))))
(defun el-search--end-of-sexp ()
;;Point must be at sexp beginning
(with-temp-buffer
(emacs-lisp-mode)
(insert (if splice
- (mapconcat #'el-search--print replacement " ")
- (el-search--print replacement)))
+ (mapconcat #'el-search--pp-to-string replacement " ")
+ (el-search--pp-to-string replacement)))
(goto-char 1)
(let (start this-sexp end orig-match-start orig-match-end done)
(while (and (< (point) (point-max))
"argument not a string or vector")
`(pred (el-search--match-key-sequence ,key-sequence)))
-(defun el-search--s (expr)
+(defun el-search--transform-nontrivial-lpat (expr)
(cond
((symbolp expr) `(or (symbol ,(symbol-name expr))
(,'\` (,'quote (,'\, (symbol ,(symbol-name expr)))))
('_ '`(,_))
('_? '(or '() `(,_))) ;FIXME: useful - document? or should we provide a (? PAT)
;thing?
- (_ `(,'\` ((,'\, ,(el-search--s elt)))))))
+ (_ `(,'\` ((,'\, ,(el-search--transform-nontrivial-lpat elt)))))))
lpats)
,@(if match-end '() '(_)))))
;;;; Core functions
;;;###autoload
-(defun el-search-pattern (pattern)
+(defun el-search-pattern (pattern &optional no-error)
"Start new or resume last elisp search.
Search current buffer for expressions that are matched by `pcase'
(error "Please don't forget the quote when searching for a symbol"))
(el-search--wrap-pattern pattern)))))
(if (not (called-interactively-p 'any))
- (el-search--search-pattern pattern)
+ (el-search--search-pattern pattern no-error)
(setq this-command 'el-search-pattern) ;in case we come from isearch
(setq el-search-current-pattern pattern)
(let ((opoint (point)))
(defun el-search-query-replace--read-args ()
(barf-if-buffer-read-only)
- (let* ((from (el-search--read-pattern "Query replace pattern: "))
- (to (let ((el-search--initial-mb-contents nil))
- (el-search--read-pattern "Replace with result of evaluation of: " from))))
+ (let ((from-input (el-search--read-pattern "Query replace pattern: " nil nil
+ 'el-search-query-replace-history))
+ from to)
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert from-input)
+ (goto-char 1)
+ (forward-sexp)
+ (skip-chars-forward " \t\n\f")
+ ;; FIXME: maybe more sanity tests here...
+ (if (not (looking-at "->"))
+ (setq from from-input
+ to (let ((el-search--initial-mb-contents nil))
+ (el-search--read-pattern "Replace with result of evaluation of: " from)))
+ (delete-char 2)
+ (goto-char 1)
+ (forward-sexp)
+ (setq from (buffer-substring 1 (point)))
+ (skip-chars-forward " \t\n\f")
+ (setq to (buffer-substring (point) (progn (forward-sexp) (point))))))
+ (unless (and el-search-query-replace-history
+ (not (string= from from-input))
+ (string= from-input (car el-search-query-replace-history)))
+ (push (format "%s -> %s" from to) ;FIXME: add line break when FROM or TO is multiline?
+ el-search-query-replace-history))
(list (el-search--wrap-pattern (read from)) (read to) to)))
;;;###autoload
to (point-max).
As each match is found, the user must type a character saying
-what to do with it. For directions, type ? at that time."
+what to do with it. For directions, type ? at that time.
+
+As an alternative to enter FROM-PATTERN and TO-EXPR separately,
+you can also give an input of the form
+
+ FROM-PATTERN -> TO-EXPR
+
+to the first prompt and specify both expressions at once. This
+format is also used for history entries."
(interactive (el-search-query-replace--read-args))
(setq this-command 'el-search-query-replace) ;in case we come from isearch
(setq el-search-current-pattern from-pattern)