legacy-dotfiles/emacs.d/nxhtml/util/search-form.el

474 lines
18 KiB
EmacsLisp
Raw Normal View History

;;; search-form.el --- Search form
;;
;; Author: Lennart Borgman (lennart O borgman A gmail O com)
;; Created: 2008-05-05T01:50:20+0200 Sun
;; Version: 0.11
;; Last-Updated:
;; URL:
;; Keywords:
;; Compatibility:
;;
;; Features that might be required by this library:
;;
;; `cus-edit', `cus-face', `cus-load', `cus-start', `wid-edit'.
;;
;;;;;;;;;;seasfireplstring ;;
;;
;;; Commentary:
;;
;; After an idea by Eric Ludlam on Emacs Devel:
;;
;; http://lists.gnu.org/archive/html/emacs-devel/2008-05/msg00152.html
;;
;; NOT QUITE READY! Tagged files have not been tested.
;;
;; Fix-me: work on other windows buffer by default, not buffer from
;; where search form was created.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Change log:
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:
(eval-when-compile (require 'ourcomments-util))
(require 'cus-edit)
(require 'grep)
(defvar search-form-sfield nil)
(make-variable-buffer-local 'search-form-sfield)
(defvar search-form-rfield nil)
(make-variable-buffer-local 'search-form-rfield)
(defvar search-form-win-config nil)
(make-variable-buffer-local 'search-form-win-config)
(put 'search-form-win-config 'permanent-local t)
(defvar search-form-current-buffer nil)
(defun search-form-multi-occur-get-buffers ()
(let* ((bufs (list (read-buffer "First buffer to search: "
(current-buffer) t)))
(buf nil)
(ido-ignore-item-temp-list bufs))
(while (not (string-equal
(setq buf (read-buffer
(if (eq read-buffer-function 'ido-read-buffer)
"Next buffer to search (C-j to end): "
"Next buffer to search (RET to end): ")
nil t))
""))
(add-to-list 'bufs buf)
(setq ido-ignore-item-temp-list bufs))
(nreverse (mapcar #'get-buffer bufs))))
(defvar search-form-buffer) ;; dyn var, silence compiler
(defvar search-form-search-string) ;; dyn var, silence compiler
(defvar search-form-replace-string) ;; dyn var, silence compiler
(defun search-form-notify-1 (use-search-field
use-replace-field
w
hide-form
display-orig-buf)
(let ((search-form-search-string (when use-search-field (widget-value search-form-sfield)))
(search-form-replace-string (when use-replace-field (widget-value search-form-rfield)))
(search-form-buffer (current-buffer))
(this-search (widget-get w :do-search))
(do-it t))
(if (and use-search-field
(= 0 (length search-form-search-string)))
(progn
(setq do-it nil)
(message "Please specify a search string"))
(when (and use-replace-field
(= 0 (length search-form-replace-string)))
(setq do-it nil)
(message "Please specify a replace string")))
(when do-it
(if hide-form
(progn
(set-window-configuration search-form-win-config)
(funcall this-search search-form-search-string)
;;(kill-buffer search-form-buffer)
)
(when display-orig-buf
(let ((win (display-buffer search-form-current-buffer t)))
(select-window win t)))
;;(funcall this-search search-form-search-string))
(funcall this-search w)
))))
(defun search-form-notify-no-field (w &rest ignore)
(search-form-notify-1 nil nil w nil t))
(defun search-form-notify-sfield (w &rest ignore)
(search-form-notify-1 t nil w nil t))
(defun search-form-notify-sfield-nobuf (w &rest ignore)
(search-form-notify-1 t nil w nil nil))
(defun search-form-notify-both-fields (w &rest ignore)
(search-form-notify-1 t t w nil t))
(defun search-form-insert-button (title function descr do-search-fun)
(widget-insert " ")
(let ((button-title (format " %-15s " title)))
(widget-create 'push-button
:do-search do-search-fun
:notify 'search-form-notify-no-field
:current-buffer search-form-current-buffer
button-title))
(widget-insert " " descr)
(widget-insert "\n"))
(defun search-form-insert-search (title search-fun descr do-search-fun no-buf)
(widget-insert " ")
(let ((button-title (format " %-15s " title)))
(if no-buf
(widget-create 'push-button
:do-search do-search-fun
:notify 'search-form-notify-sfield-nobuf
:current-buffer search-form-current-buffer
button-title)
(widget-create 'push-button
:do-search do-search-fun
:notify 'search-form-notify-sfield
:current-buffer search-form-current-buffer
button-title)
))
(widget-insert " " descr " ")
(search-form-insert-help search-fun)
(widget-insert "\n"))
(defun search-form-insert-fb (descr
use-sfield
forward-fun
do-forward-fun
backward-fun
do-backward-fun)
(widget-insert (format " %s: " descr))
(widget-create 'push-button
:do-search do-forward-fun
:use-sfield use-sfield
:notify '(lambda (widget &rest event)
(if (widget-get widget :use-sfield)
(search-form-notify-sfield widget)
(search-form-notify-no-field widget)))
:current-buffer search-form-current-buffer
" Forward ")
(widget-insert " ")
(search-form-insert-help forward-fun)
(widget-insert " ")
(widget-create 'push-button
:do-search do-backward-fun
:use-sfield use-sfield
:notify '(lambda (widget &rest event)
(if (widget-get widget :use-sfield)
(search-form-notify-sfield widget)
(search-form-notify-no-field widget)))
:current-buffer search-form-current-buffer
" Backward ")
(widget-insert " ")
(search-form-insert-help backward-fun)
(widget-insert "\n"))
(defun search-form-insert-replace (title replace-fun descr do-replace-fun)
(widget-insert " ")
(let ((button-title (format " %-15s " title)))
(widget-create 'push-button
:do-search do-replace-fun
:notify 'search-form-notify-both-fields
:current-buffer search-form-current-buffer
button-title))
(widget-insert " " descr " ")
(search-form-insert-help replace-fun)
(widget-insert "\n"))
(defun search-form-insert-help (fun)
(widget-insert "(")
(widget-create 'function-link
:value fun
:tag "help"
:button-face 'link)
(widget-insert ")"))
(defun sf-widget-field-value-set (widget value)
"Set current text in editing field."
(let ((from (widget-field-start widget))
(to (widget-field-end widget))
(buffer (widget-field-buffer widget))
(size (widget-get widget :size))
(secret (widget-get widget :secret))
(old (current-buffer)))
(if (and from to)
(progn
(set-buffer buffer)
(while (and size
(not (zerop size))
(> to from)
(eq (char-after (1- to)) ?\s))
(setq to (1- to)))
(goto-char to)
(delete-region from to)
(insert value)
(let ((result (buffer-substring-no-properties from to)))
(when secret
(let ((index 0))
(while (< (+ from index) to)
(aset result index
(get-char-property (+ from index) 'secret))
(setq index (1+ index)))))
(set-buffer old)
result))
(widget-get widget :value))))
(defvar search-form-form nil)
(defun search-form-isearch-end ()
(condition-case err
(progn
(message "sfie: search-form-form=%s" (widget-value (cdr search-form-form)))
(remove-hook 'isearch-mode-end-hook 'search-form-isearch-end)
;; enter isearch-string in field
(with-current-buffer (car search-form-form)
;; Fix-me: trashes the widget, it disappears... - there seem
;; to be know default set function.
;;(widget-value-set (cdr search-form-form) isearch-string)
))
(error (message "search-form-isearch-end: %S" err))))
(defun search-form-isearch-forward (w)
(interactive)
(add-hook 'isearch-mode-end-hook 'search-form-isearch-end)
(with-current-buffer search-form-buffer
(setq search-form-form (cons search-form-buffer search-form-sfield))
(message "sfif: cb=%s field=%S" (current-buffer) (widget-value (cdr search-form-form)))
)
(call-interactively 'isearch-forward))
(defun search-form-isearch-backward (w)
(interactive)
(add-hook 'isearch-mode-end-hook 'search-form-isearch-end)
(setq search-form-form search-form-sfield)
(call-interactively 'isearch-backward))
;;;###autoload
(defun search-form ()
"Display a form for search and replace."
(interactive)
(let* ((buf-name "*Search Form*")
(cur-buf (current-buffer))
(buffer (get-buffer-create buf-name))
(win-config (current-window-configuration)))
(setq search-form-current-buffer (current-buffer))
(with-current-buffer buffer
(set (make-local-variable 'search-form-win-config) win-config))
(switch-to-buffer-other-window buffer)
(kill-all-local-variables) ;; why???
(let ((inhibit-read-only t))
(erase-buffer))
;;(Custom-mode)
(remove-overlays)
(make-local-variable 'widget-button-face)
(setq widget-button-face custom-button)
(setq show-trailing-whitespace nil)
(when custom-raised-buttons
(set (make-local-variable 'widget-push-button-prefix) "")
(set (make-local-variable 'widget-push-button-suffix) "")
(set (make-local-variable 'widget-link-prefix) "")
(set (make-local-variable 'widget-link-suffix) ""))
(widget-insert (propertize "Search/Replace, buffer: " 'face 'font-lock-comment-face))
(widget-insert (format "%s" (buffer-name search-form-current-buffer)))
(let ((file (buffer-file-name search-form-current-buffer)))
(when file
(insert " (" file ")")))
(widget-insert "\n\n")
(search-form-insert-fb
"Incremental String Search" nil
'isearch-forward
'search-form-isearch-forward
'isearch-backward
'search-form-isearch-backward)
(search-form-insert-fb
"Incremental Regexp Search" nil
'isearch-forward-regexp
(lambda (w) (call-interactively 'isearch-forward-regexp))
'isearch-backward-regexp
(lambda (w) (call-interactively 'isearch-backward-regexp)))
;; Fix-me: in multiple buffers, from buffer-list
(widget-insert (make-string (window-width) ?-) "\n")
(widget-insert "Search: ")
(setq search-form-sfield
(widget-create 'editable-field
:size 58))
(widget-insert "\n\n")
(widget-insert (propertize "* Buffers:" 'face 'font-lock-comment-face) "\n")
(search-form-insert-fb "String Search" t
'search-forward
(lambda (w) (search-forward search-form-search-string))
'search-backward
(lambda (w) (search-backward search-form-search-string)))
(search-form-insert-fb "Regexp Search" t
're-search-forward
(lambda (w) (re-search-forward search-form-search-string))
're-search-backward
(lambda (w) (re-search-backward search-form-search-string)))
;; occur
(search-form-insert-search "Occur" 'occur
"Lines in buffer"
(lambda (w)
(with-current-buffer (widget-get w :current-buffer)
(occur search-form-search-string)))
t)
;; multi-occur
;; Fix-me: This should be done from buffer-list. Have juri finished that?
(search-form-insert-search "Multi-Occur" 'multi-occur
"Lines in specified buffers"
(lambda (w)
(let ((bufs (search-form-multi-occur-get-buffers)))
(multi-occur bufs search-form-search-string)))
t)
;;
(widget-insert "\n")
(widget-insert (propertize "* Files:" 'face 'font-lock-comment-face)
"\n")
(search-form-insert-search "Search in Dir" 'lgrep
"Grep in directory"
'search-form-lgrep
t)
(search-form-insert-search "Search in Tree" 'rgrep
"Grep in directory tree"
'search-form-rgrep
t)
(widget-insert "\n")
(search-form-insert-search "Tagged Files" 'tags-search
"Search files in tags table"
(lambda (w)
(with-current-buffer (widget-get w :current-buffer)
(tags-search search-form-search-string)))
t)
(widget-insert (make-string (window-width) ?-) "\n")
(widget-insert "Replace: ")
(setq search-form-rfield
(widget-create 'editable-field
:size 58))
(widget-insert "\n\n")
(widget-insert (propertize "* Buffers:" 'face 'font-lock-comment-face) "\n")
(search-form-insert-replace "Replace String"
'query-replace
"In buffer from point"
(lambda (w)
(query-replace search-form-search-string search-form-replace-string)))
(search-form-insert-replace "Replace Regexp"
'query-replace-regexp
"In buffer from point"
(lambda (w)
(query-replace-regexp search-form-search-string search-form-replace-string)))
(widget-insert "\n" (propertize "* Files:" 'face 'font-lock-comment-face) "\n")
;; fix-me: rdir-query-replace (from to file-regexp root &optional delimited)
(search-form-insert-replace "Replace in Dir"
'ldir-query-replace
"Replace in files in directory"
'search-form-ldir-replace)
(search-form-insert-replace "Replace in Tree"
'rdir-query-replace
"Replace in files in directory tree"
'search-form-rdir-replace)
(widget-insert "\n")
(search-form-insert-replace "Tagged Files"
'tags-query-replace
"Replace in files in tags tables"
(lambda (w)
(tags-query-replace search-form-search-string search-form-replace-string)))
(buffer-disable-undo)
(widget-setup)
(buffer-enable-undo)
(use-local-map widget-keymap)
(fit-window-to-buffer)
(widget-forward 1)
))
(defun search-form-lgrep (w)
(search-form-r-or-lgrep w t))
(defun search-form-rgrep (w)
(search-form-r-or-lgrep w nil))
(defun search-form-r-or-lgrep (w l)
(with-current-buffer (widget-get w :current-buffer)
(let* ((regexp search-form-search-string)
(files (grep-read-files regexp))
(dir (read-directory-name (if l "In directory: "
"Base directory: ")
nil default-directory t)))
(if l
(lgrep regexp files dir)
(rgrep regexp files dir)
))))
(defun search-form-ldir-replace (w)
(search-form-l-or-r-dir-replace w t))
(defun search-form-rdir-replace (w)
(search-form-l-or-r-dir-replace w nil))
(defun search-form-l-or-r-dir-replace (w l)
(let ((files (replace-read-files search-form-search-string search-form-replace-string))
(dir (read-directory-name (if l
"In directory: "
"In directory tree: ")
nil
(file-name-directory
(buffer-file-name search-form-current-buffer))
t)))
(if l
(ldir-query-replace search-form-search-string search-form-replace-string files dir)
(rdir-query-replace search-form-search-string search-form-replace-string files dir))))
(provide 'search-form)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; search-form.el ends here