emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Why is `C-x 8' limited to Latin-1 for search?


From: Drew Adams
Subject: RE: Why is `C-x 8' limited to Latin-1 for search?
Date: Sat, 8 Dec 2012 21:33:49 -0800

> To try the latter quickly (no, this is not the way to code 
> this; it's just a quick way to let you try it):
> 
> (unless (fboundp 'ORIG-isearch-edit-string)
>   (defalias 'ORIG-isearch-edit-string
>             (symbol-function 'isearch-edit-string)))
> 
> (defun isearch-edit-string ()
>   (interactive)
>   (let ((enable-recursive-minibuffers  t))
>     (ORIG-isearch-edit-string)))
> 
> In a buffer with some Unicode chars, e.g., `λ':
> 
> C-s M-e C-x 8 RET GREEK SMALL LETTER LAMBDA C-s
> 
> (You have completion for the character name, at least.)

And you can try the former quickly too (i.e., use `C-x 8 RET' directly in
Isearch without going through `M-e') with the code below. Again, I'm not
proposing using this code as is; this is just to let you see how the feature
might act.

E.g., after evaling the code below, to search for `abcλdef', do this (with
completion for the char name):

  C-s a b c C-x 8 RET GREEK SMALL LETTER LAMBDA RET d e f

(define-key isearch-mode-map "\C-x8\r" 'foo)

;; 99% the same as `isearch-edit-string' (`M-e'). This just calls
`read-char-by-name'.
;; The common code could be factored out, if this were how we wanted to
implement the feature.
;; (I didn't try to see if everything else here is needed for this feature, as
it is needed for `M-e'.)
;;
(defun foo ()
  (interactive)
  (condition-case nil
      (progn
        (let ((enable-recursive-minibuffer  t) ; <====== ADDED ====
              (isearch-nonincremental isearch-nonincremental)
              ;; Locally bind all isearch global variables to protect them
              ;; from recursive isearching.
              ;; isearch-string -message and -forward are not bound
              ;; so they may be changed.  Instead, save the values.
              (isearch-new-string isearch-string)
              (isearch-new-message isearch-message)
              (isearch-new-forward isearch-forward)
              (isearch-new-word isearch-word)
              (isearch-new-case-fold isearch-case-fold-search)
              (isearch-regexp isearch-regexp)
              (isearch-op-fun isearch-op-fun)
              (isearch-cmds isearch-cmds)
              (isearch-success isearch-success)
              (isearch-wrapped isearch-wrapped)
              (isearch-barrier isearch-barrier)
              (isearch-adjusted isearch-adjusted)
              (isearch-yank-flag isearch-yank-flag)
              (isearch-error isearch-error)
              (isearch-opoint isearch-opoint)
              (isearch-slow-terminal-mode isearch-slow-terminal-mode)
              (isearch-small-window isearch-small-window)
              (isearch-recursive-edit isearch-recursive-edit)
              ;; Save current configuration so we can restore it here.
              (isearch-window-configuration (current-window-configuration))
              ;; This could protect the index of the search rings,
              ;; but we can't reliably count the number of typed M-p
              ;; in `read-from-minibuffer' to adjust the index accordingly.
              ;; So when the following is commented out, `isearch-mode'
              ;; below resets the index to the predictable value nil.
              ;; (search-ring-yank-pointer search-ring-yank-pointer)
              ;; (regexp-search-ring-yank-pointer
regexp-search-ring-yank-pointer)
              ;; Temporarily restore `minibuffer-message-timeout'.
              (minibuffer-message-timeout
               isearch-original-minibuffer-message-timeout)
              (isearch-original-minibuffer-message-timeout
               isearch-original-minibuffer-message-timeout)
              old-point old-other-end)
          ;; Actually terminate isearching until editing is done.
          ;; This is so that the user can do anything without failure,
          ;; like switch buffers and start another isearch, and return.
          (condition-case nil
              (isearch-done t t)
            (exit nil))                 ; was recursive editing
          ;; Save old point and isearch-other-end before reading from minibuffer
          ;; that can change their values.
          (setq old-point (point) old-other-end isearch-other-end)
          (unwind-protect
               (let* ((message-log-max nil)
                      ;; Don't add a new search string to the search ring here
                      ;; in `read-from-minibuffer'. It should be added only
                      ;; by `isearch-update-ring' called from `isearch-done'.
                      (history-add-new-input nil)
                      ;; Binding minibuffer-history-symbol to nil is a
work-around
                      ;; for some incompatibility with gmhist.
                      (minibuffer-history-symbol))
                 (setq isearch-new-string
                       (concat
                        isearch-string

                       ;; ========= THIS IS ALL THAT'S NEW =========
                        (string (read-char-by-name "Unicode (name or hex): ")))

                       isearch-new-message
                       (mapconcat 'isearch-text-char-description
                                  isearch-new-string "")))
            ;; Set point at the start (end) of old match if forward (backward),
            ;; so after exiting minibuffer isearch resumes at the start (end)
            ;; of this match and can find it again.
            (if (and old-other-end (eq old-point (point))
                     (eq isearch-forward isearch-new-forward))
                (goto-char old-other-end))
            ;; Always resume isearching by restarting it.
            (isearch-mode isearch-forward
                          isearch-regexp
                          isearch-op-fun
                          nil
                          isearch-word)
            ;; Copy new local values to isearch globals
            (setq isearch-string isearch-new-string
                  isearch-message isearch-new-message
                  isearch-forward isearch-new-forward
                  isearch-word isearch-new-word
                  isearch-case-fold-search isearch-new-case-fold))
          ;; Empty isearch-string means use default.
          (when (= 0 (length isearch-string))
            (setq isearch-string (or (car (if isearch-regexp
                                              regexp-search-ring
                                            search-ring))
                                     "")
                  isearch-message
                  (mapconcat 'isearch-text-char-description
                             isearch-string ""))
            ;; After taking the last element, adjust ring to previous one.
            (isearch-ring-adjust1 nil)))
        ;; This used to push the state as of before this C-s, but it adds
        ;; an inconsistent state where part of variables are from the
        ;; previous search (e.g. `isearch-success'), and part of variables
        ;; are just entered from the minibuffer (e.g. `isearch-string').
        ;; (isearch-push-state)
        ;; Reinvoke the pending search.
        (isearch-search)
        (isearch-push-state)           ; this pushes the correct state
        (isearch-update)
        (if isearch-nonincremental
            (progn
              ;; (sit-for 1) ;; needed if isearch-done does: (message "")
              (isearch-done)
              ;; The search done message is confusing when the string
              ;; is empty, so erase it.
              (if (equal isearch-string "")
                  (message "")))))
    (quit            ; handle abort-recursive-edit
     (isearch-abort) ;; outside of let to restore outside global values
     )))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]