how to search string in other buffer in emacs? - search

I have llist of words in one buffer and bunch of text lines in another. I am looking for something like selected word in one buffer has to be highlighted in another buffer. Does emacs support it?

Try org-mode.
You can put a link [[file:yourFile::yourSearchExpression]] into the org-buffer.
If you click the link the buffer visiting yourFile is searched for yourSearchExpression (a regular expression).
I use the extension below. With this extension you can also write [[buffer:yourBuffer::yourSearchExpression]]. Here, yourBuffer must be a buffer (not a file).
But, you can open the file of interest beforehand.
The first character of yourSearchExpression can be an operator.
If it is a + then yourBuffer is searched forward starting at the current point position.
If it is a - then yourBuffer is searched backward starting at the current point position. If no operator is given then the buffer is searched forward starting at the beginning of the buffer. Other operators can easily be implemented.
The good thing is that you can easily pre-define your searches in the org-file. You have one file where you organize your searches for one subject. The stuff you search can be spread over several buffers.
That becomes handy if you need the search of this type again later on.
I have added the high-lighting quite recently. Therefore, if you encounter problems. Just give me a note.
;; stolen from isearch:
(defface search-highlight-face
'((((class color) (min-colors 88) (background light))
;; The background must not be too dark, for that means
;; the character is hard to see when the cursor is there.
(:background "magenta3" :foreground "lightskyblue1"))
(((class color) (min-colors 88) (background dark))
(:background "palevioletred2" :foreground "brown4"))
(((class color) (min-colors 16))
(:background "magenta4" :foreground "cyan1"))
(((class color) (min-colors 8))
(:background "magenta4" :foreground "cyan1"))
(t (:inverse-video t)))
"Face for highlighting search matches."
:group 'search-highlight)
(defface search-highlight-other-face
'((((class color) (min-colors 88) (background light))
(:background "paleturquoise"))
(((class color) (min-colors 88) (background dark))
(:background "paleturquoise4"))
(((class color) (min-colors 16))
(:background "turquoise3"))
(((class color) (min-colors 8))
(:background "turquoise3"))
(t (:underline t)))
"Face for lazy highlighting of matches other than the current one."
:group 'search-highlight)
(require 'cl) ;; for find
(defun search-highlight (se &rest opt)
"Like the group of `search-forward' commands with highlighting of the matches.
Note, that this function should only be used in commands since it is directly visible.
The window of the current buffer must be alive and should be visible.
Options:
:back non-nil: search backward instead of forward
:re non-nil: SE is regular expression
:noerror non-nil: issue error when not found
:bound bound of search
:count search that many times (defaults to 1)
:face use this face to highlight
:others non-nil: highlight also other matches within visible area of buffer
:recenter recenter point in window vertically (before highlighting others)
"
(interactive "sSearch expression:")
(search-highlight-cleanup) ;; If anything went wrong prevously.
(let* (ol
(regexp? (when (plist-get opt :re) "-regexp"))
(cmd (intern-soft (concat "search"
(if (plist-get opt :back) "-backward" "-forward")
regexp?
)))
e)
(when (funcall cmd se (plist-get opt :bound) (plist-get opt :noerror) (plist-get opt :count))
(setq ol (make-overlay (match-beginning 0) (match-end 0)))
(overlay-put ol 'face 'search-highlight-face))
(when (plist-get opt :recenter) (recenter))
(if (plist-get opt :others)
(save-excursion
(goto-char (window-start))
(setq e (window-end nil t))
(setq cmd (intern-soft (concat "search-forward" regexp?)))
(while (funcall cmd se e t)
(unless (and ol (= (match-beginning 0) (overlay-start ol)))
(overlay-put (make-overlay (match-beginning 0) (match-end 0))
'face 'search-highlight-other-face)))))
(add-hook 'pre-command-hook 'search-highlight-cleanup t t)))
(defun search-highlight-cleanup ()
"Remove highlights for search-highlight-mode."
(interactive)
(remove-hook 'pre-command-hook 'search-highlight-cleanup t)
(remove-overlays 0 (buffer-size)
'face 'search-highlight-face)
(remove-overlays 0 (buffer-size)
'face 'search-highlight-other-face))
(defun org-at-buffer ()
"Check whether point is at [[buffer:BUFFER::SEARCH]].
BUFFER is just the name of an existing buffer.
You can make sure that the buffer exists by [[file:...]].
::RE is an optional regular expression.
The first character of SEARCH may be an operator:
+ Start at current point and search forward.
- Start at current point and search backward.
If the operator is missing the buffer is searched for RE starting at the beginning of BUFFER.
"
(save-excursion
(let ((pt (point))
b e
name
re)
(when (search-backward "[[buffer:" (line-beginning-position) 'noErr)
(forward-char)
(setq b (+ (point) (length "[buffer:")))
(forward-sexp) ;; actual link
(setq e (1- (point)))
(when (looking-at "\\[") ;; optional description
(forward-sexp))
(when (>= (point) pt)
(goto-char b)
(if (search-forward "::" e 'noErr)
(setq
name (buffer-substring-no-properties b (match-beginning 0))
re (buffer-substring-no-properties (match-end 0) e)
)
(setq name (buffer-substring-no-properties b e)))
(switch-to-buffer-other-window name)
(when re
(if (and (> (length re) 0) (find (aref re 0) "+-"))
(let ((op (aref re 0)))
(setq re (substring re 1))
(cond
((= op ?+)
(when (= (point) (point-max))
(goto-char (point-min)))
(search-highlight re :re t :noerror t :others t :recenter t))
((= op ?-)
(when (= (point) (point-min))
(goto-char (point-max)))
(search-highlight re :back t :re t :noerror t :others t :recenter t))
(t
(error "Unexpected op."))))
(goto-char (point-min))
(search-highlight re :re t :noerror t :others t :recenter t)))
t)))))
(add-to-list 'org-open-at-point-functions 'org-at-buffer)

Related

emacs: search and replace on a region

So, I have this excellent function (that someone made for me) for doing multiple search and replaces on an entire buffer.
(defun accent-replace-whole-buffer ()
"Corrects macrons from badly scanned latin"
(interactive "*")
(dolist (ele (list ?â ?ä ?ê ?ë ?î ?ô ?ü ?ï))
(setq elt (char-to-string ele))
(goto-char (point-min))
(while (search-forward elt nil t 1)
(replace-match
(char-to-string
(pcase ele
(`?â ?ā)
(`?ä ?ā)
(`?ê ?ē)
(`?ë ?ē)
(`?î ?ī)
(`?ô ?ō)
(`?ü ?ū)
(`?ï ?ī)))))))
and I would like to make another function, which does this, only on the selected region.
How would I go about this? Is there a nice tutorial anywhere?
Use narrow-to-region, inside save-restriction:
(defun accent-replace-in-region (begin end)
"Corrects macrons in active region from badly scanned latin"
(interactive "*r")
(save-restriction
(narrow-to-region begin end)
(dolist (ele (list ?ā ?ā ?ē ?ē ?ī ?ō ?ū ?ī))
(setq elt (char-to-string ele))
(goto-char (point-min))
(while (search-forward elt nil t 1)
(replace-match
(char-to-string
(pcase ele
(`?â ?ā)
(`?ä ?ā)
(`?ê ?ē)
(`?ë ?ē)
(`?î ?ī)
(`?ô ?ō)
(`?ü ?ū)
(`?ï ?ī))))))))
Instead of the builtin interactive code "r", using that form:
(defun MYFUNTION (&optional beg end)
(interactive "*")
(let ((beg (cond (beg)
((use-region-p)
(region-beginning))
(t (point-min))))
(end (cond (end (point-marker end))
((use-region-p)
(point-marker (region-end)))
(t (point-marker (point-max))))))
(and beg end (narrow-to-region beg end))
(goto-char beg)
;; here some replace example revealing the problem mentioned
(while (re-search-forward "." end t 1)
(replace-match "+++++++++"))))
Basically two reasons for this: Make sure, the region is visible when acting upon. "r" doesn't care for transient-mark-mode. Unfortunately use-region-p also has some quirks. Second reason: end needs to be updated when a replacing will change the length of the region.

Why does org-preview-latex-fragment work about 10 times slower in OSX than on linux?

I'm using the native cocoa emacs on OSX as well as on debian in a virtual machine.
When I run the aforementioned function in order to generate latex previews (on the same file) in the OSX or in the VM Emacs, I get huge performance differences: it takes at least 10 times as long to generate the previews in OSX as in the VM (running on the same machine, with the same document!!).
I imagine it is one of the programs in the stack of things that work to produce those previews? Or is calling a subprocess very expensive in OSX? (because it appears one is called for each preview)?
I would be happy to provide additional info, just don't know what...
Thanks in advance!
There are two approach to preview latex frags:
latex -> pdflatex-> dvi -> dvi2png -> png : fast
latex -> xelatex -> pdf -> imagemagick -> png: slow
may be you used the second one...
Eval this (test) function, and check message, you may find which step is slow.....
(defun test (&optional options buffer)
"This calls dvipng."
(require 'ox-latex)
(setq test-timestamp (float-time))
(message "test1: %s" (- (float-time) test-timestamp))
(let* ((tmpdir (if (featurep 'xemacs)
(temp-directory)
temporary-file-directory))
(texfilebase (make-temp-name
(expand-file-name "orgtex" tmpdir)))
(texfile (concat texfilebase ".tex"))
(dvifile (concat texfilebase ".dvi"))
(pngfile (concat texfilebase ".png"))
(fnh (if (featurep 'xemacs)
(font-height (face-font 'default))
(face-attribute 'default :height nil)))
(scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
(dpi (number-to-string (* scale (floor (* 0.9 (if buffer fnh 140.))))))
(fg (or (plist-get options (if buffer :foreground :html-foreground))
"Black"))
(bg (or (plist-get options (if buffer :background :html-background))
"Transparent")))
(message "test2: %s" (- (float-time) test-timestamp))
(if (eq fg 'default) (setq fg (org-dvipng-color :foreground))
(unless (string= fg "Transparent") (setq fg (org-dvipng-color-format fg))))
(if (eq bg 'default) (setq bg (org-dvipng-color :background))
(unless (string= bg "Transparent") (setq bg (org-dvipng-color-format bg))))
(message "test3: %s" (- (float-time) test-timestamp))
(let ((latex-header (org-create-formula--latex-header)))
(with-temp-file texfile
(insert latex-header)
(insert "\n\\begin{document}\n" "$y=ax+b+c+d$" "\n\\end{document}\n")))
(message "test4: %s" (- (float-time) test-timestamp))
(let ((dir default-directory))
(condition-case nil
(progn
(cd tmpdir)
(call-process "latex" nil nil nil texfile))
(error nil))
(cd dir))
(message "test5: %s" (- (float-time) test-timestamp))
(if (not (file-exists-p dvifile))
(progn (message "Failed to create dvi file from %s" texfile) nil)
(condition-case nil
(call-process "dvipng" nil nil nil
"-fg" fg "-bg" bg
"-D" dpi
;;"-x" scale "-y" scale
"-T" "tight"
"-o" pngfile
dvifile)
(error nil))
(message "test6: %s" (- (float-time) test-timestamp))
(if (not (file-exists-p pngfile))
(if org-format-latex-signal-error
(error "Failed to create png file from %s" texfile)
(message "Failed to create png file from %s" texfile)
nil)
;; Use the requested file name and clean up
(copy-file pngfile "~/testpic.png" 'replace)
(message "test7: %s" (- (float-time) test-timestamp))
pngfile))))

"1 of n" result for Emacs search

When I use incremental search in emacs I can't know where I am in whole matches. In Chrome browser it says location using "2 of 30". How can I do that in Emacs?
Here's my first attempt to implement this.
It uses the lazy highlighting that isearch implements, and forces the highlighting to cover the entire buffer (not just the visible portions) - which can slow down the search on large buffers. It then updates the display to include a current position (of total) relative to the highlighted search results.
This has the drawback that it is dependent on the entire buffer being searched and highlighted. And, sometimes when you C-s to the next match, the display changes to (0 of 1) even though the highlights are clearly still present.
But, it seems to be a reasonable first cut.
Prepare for big cut/paste:
(require 'isearch)
(defun lazy-highlight-cleanup (&optional force)
"Stop lazy highlighting and remove extra highlighting from current buffer.
FORCE non-nil means do it whether or not `lazy-highlight-cleanup'
is nil. This function is called when exiting an incremental search if
`lazy-highlight-cleanup' is non-nil."
(interactive '(t))
(if (or force lazy-highlight-cleanup)
(while isearch-lazy-highlight-overlays
(delete-overlay (car isearch-lazy-highlight-overlays))
(setq isearch-lazy-highlight-overlays
(cdr isearch-lazy-highlight-overlays))))
(when isearch-lazy-highlight-timer
(cancel-timer isearch-lazy-highlight-timer)
(setq isearch-message-suffix-add "")
(setq isearch-lazy-highlight-timer nil)))
(defun isearch-lazy-highlight-search ()
"Search ahead for the next or previous match, for lazy highlighting.
Attempt to do the search exactly the way the pending Isearch would."
(condition-case nil
(let ((case-fold-search isearch-lazy-highlight-case-fold-search)
(isearch-regexp isearch-lazy-highlight-regexp)
(search-spaces-regexp isearch-lazy-highlight-space-regexp)
(isearch-word isearch-lazy-highlight-word)
(search-invisible nil) ; don't match invisible text
(retry t)
(success nil)
(isearch-forward isearch-lazy-highlight-forward)
(bound (if isearch-lazy-highlight-forward
(min (or isearch-lazy-highlight-end-limit (point-max))
(if isearch-lazy-highlight-wrapped
isearch-lazy-highlight-start
(isearch-window-end)))
(max (or isearch-lazy-highlight-start-limit (point-min))
(if isearch-lazy-highlight-wrapped
isearch-lazy-highlight-end
(isearch-window-start))))))
;; Use a loop like in `isearch-search'.
(while retry
(setq success (isearch-search-string
isearch-lazy-highlight-last-string bound t))
;; Clear RETRY unless the search predicate says
;; to skip this search hit.
(if (or (not success)
(= (point) bound) ; like (bobp) (eobp) in `isearch-search'.
(= (match-beginning 0) (match-end 0))
(funcall isearch-filter-predicate
(match-beginning 0) (match-end 0)))
(setq retry nil)))
success)
(error nil)))
(defun isearch-find-current-overlay ()
(let ((total 0)
(count 1)
(olist isearch-lazy-highlight-overlays))
(while olist
(setq total (1+ total))
(if (< (overlay-end (car olist)) (point))
(setq count (1+ count)))
(setq olist
(cdr olist)))
(cons count total)))
(add-hook 'isearch-update-post-hook 'isearch-count-message)
(defun isearch-count-message ()
(let ((counts (isearch-find-current-overlay)))
(setq isearch-message-suffix-add (format " (%d of %d)" (car counts) (cdr counts)))))
(defun isearch-window-start ()
"force highlight entire buffer"
(point-min))
(defun isearch-window-end ()
"force highlight entire buffer"
(point-max))
(defun isearch-lazy-highlight-update ()
"Update highlighting of other matches for current search."
(let ((max lazy-highlight-max-at-a-time)
(looping t)
nomore)
(with-local-quit
(save-selected-window
(if (and (window-live-p isearch-lazy-highlight-window)
(not (eq (selected-window) isearch-lazy-highlight-window)))
(select-window isearch-lazy-highlight-window))
(save-excursion
(save-match-data
(goto-char (if isearch-lazy-highlight-forward
isearch-lazy-highlight-end
isearch-lazy-highlight-start))
(while looping
(let ((found (isearch-lazy-highlight-search)))
(when max
(setq max (1- max))
(if (<= max 0)
(setq looping nil)))
(if found
(let ((mb (match-beginning 0))
(me (match-end 0)))
(if (= mb me) ;zero-length match
(if isearch-lazy-highlight-forward
(if (= mb (if isearch-lazy-highlight-wrapped
isearch-lazy-highlight-start
(isearch-window-end)))
(setq found nil)
(forward-char 1))
(if (= mb (if isearch-lazy-highlight-wrapped
isearch-lazy-highlight-end
(isearch-window-start)))
(setq found nil)
(forward-char -1)))
;; non-zero-length match
(let ((ov (make-overlay mb me)))
(push ov isearch-lazy-highlight-overlays)
;; 1000 is higher than ediff's 100+,
;; but lower than isearch main overlay's 1001
(overlay-put ov 'priority 1000)
(overlay-put ov 'face lazy-highlight-face)
(overlay-put ov 'window (selected-window))))
(if isearch-lazy-highlight-forward
(setq isearch-lazy-highlight-end (point))
(setq isearch-lazy-highlight-start (point)))))
;; not found or zero-length match at the search bound
(if (not found)
(if isearch-lazy-highlight-wrapped
(setq looping nil
nomore t)
(setq isearch-lazy-highlight-wrapped t)
(if isearch-lazy-highlight-forward
(progn
(setq isearch-lazy-highlight-end (isearch-window-start))
(goto-char (max (or isearch-lazy-highlight-start-limit (point-min))
(isearch-window-start))))
(setq isearch-lazy-highlight-start (isearch-window-end))
(goto-char (min (or isearch-lazy-highlight-end-limit (point-max))
(isearch-window-end))))))))
(unless nomore
(setq isearch-lazy-highlight-timer
(run-at-time lazy-highlight-interval nil
'isearch-lazy-highlight-update)))))))))
I saw this the other day:
https://github.com/syohex/emacs-anzu
anzu.el is an Emacs port of anzu.vim. anzu.el provides a minor mode which displays current match and total matches information in the mode-line in various search modes.
The screenshot on the github page is a gif animation of its functionality.
Out of the box, you can use M-so while isearching to at least see the total number of matches (even if it unfortunately isn't smart enough to track the match that you're on in the original buffer).
Add the following to your emacs init file. Despite the use of count-matches, it works very fast on my laptop. I have not tried it with very large files.
(defun my-isearch-update-post-hook()
(let (suffix num-before num-after num-total)
(setq num-before (count-matches isearch-string (point-min) (point)))
(setq num-after (count-matches isearch-string (point) (point-max)))
(setq num-total (+ num-before num-after))
(setq suffix (if (= num-total 0)
""
(format " [%d of %d]" num-before num-total)))
(setq isearch-message-suffix-add suffix)
(isearch-message)))
(add-hook 'isearch-update-post-hook 'my-isearch-update-post-hook)

Emacs, Linux and international keyboard layouts

Is there an easy way to use Emacs key-bindings when you are using a not-English (Russian) keyboard layout?
Whenever an international layout is on, all keystrokes are interpreted literally, M-ф instead of M-a. As a result I can't use commands.
It would also be nice if Linux could interpret non-prefixed and shift-prefixed keys according according to an international layout, while keeping the rest English.
You can set input method (kudos go to kindahero) by typing
M-x set-input-method RET cyrillic-yawerty RET
or
M-x set-input-method RET cyrillic-jcuken RET
To store it permanently, add
(setq default-input-method "cyrillic-yawerty")
to ~/.emacs config (and use C-\ to switch between keyboard layouts).
Here is an alternative solution that uses the OS language, based on syndikat's answer.
Some key translations are missing, but it should be easy to add them.
;; USAGE:
;; Put in your .emacs:
;;
;; (translate-keystrokes-ru->en)
;; (add-hook 'text-mode-hook
;; (lambda () (literal-insert-mode 1)))
;;
;; Only buffers with literal-insert-mode active will be sensitive to the
;; environment language. Prefixed keybindings will still be usable.
(defun translate-keystrokes-ru->en ()
"Make emacs output english characters, regardless whether
the OS keyboard is english or russian"
(flet ((make-key-stroke (prefix char)
(eval `(kbd ,(if (and (string-match "^C-" prefix)
(string-match "[A-Z]" (string char)))
(concat "S-" prefix (string (downcase char)))
(concat prefix (string char)))))))
(let ((case-fold-search nil)
(keys-pairs (mapcar* 'cons
"йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№"
"qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"))
(prefixes '("" "s-" "M-" "M-s-"
"C-" "C-s-" "C-M-" "C-M-s-")))
(mapc (lambda (prefix)
(mapc (lambda (pair)
(define-key key-translation-map
(make-key-stroke prefix (car pair))
(make-key-stroke prefix (cdr pair))))
keys-pairs))
prefixes))))
(defun literal-insert ()
(interactive)
(insert-char last-input-event 1))
(define-minor-mode literal-insert-mode
"Make emacs output characters corresponging to the OS keyboard,
ignoring the key-translation-map"
:keymap (let ((new-map (make-sparse-keymap))
(english-chars "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"))
(mapc (lambda (char)
(define-key new-map (string char)
'literal-insert))
english-chars)
new-map))
Not sure, where did sabof got 150 billion. I ran this code (thanks to Yuri Khan, taken from EmacsWiki):
(loop
for from across "йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№"
for to across "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"
do
(eval `(define-key key-translation-map (kbd ,(concat "C-" (string from))) (kbd ,(concat "C-" (string to)))))
(eval `(define-key key-translation-map (kbd ,(concat "M-" (string from))) (kbd ,(concat "M-" (string to))))))
It's only 128 combinations. Unfortunately, combinations with single letters like C-x b don't work. I'm still trying to find a better solution.
I use following snippet for Cyrillic keyboard and it works fine for me:
(defun reverse-input-method (input-method)
"Build the reverse mapping of single letters from INPUT-METHOD."
(interactive
(list (read-input-method-name "Use input method (default current): ")))
(if (and input-method (symbolp input-method))
(setq input-method (symbol-name input-method)))
(let ((current current-input-method)
(modifiers '(nil (control) (meta) (control meta))))
(when input-method
(activate-input-method input-method))
(when (and current-input-method quail-keyboard-layout)
(dolist (map (cdr (quail-map)))
(let* ((to (car map))
(from (quail-get-translation
(cadr map) (char-to-string to) 1)))
(when (and (characterp from) (characterp to))
(dolist (mod modifiers)
(define-key local-function-key-map
(vector (append mod (list from)))
(vector (append mod (list to)))))))))
(when input-method
(activate-input-method current))))
(reverse-input-method 'russian-computer)
Except:
The only issue I know is that recalculation of OrgTable formulas isn't
working in Russian layout because it is mapped to C-c-* and * change
its location.
source
If you want to keep using the Russian layout in Emacs (rather than use Emacs's own input methods), the only way I know of for now is to add bindings of the form:
(define-key function-key-map [?\M-ф] [?\M-a])
This will tell Emacs that in case M-ф is not bound, it should try to lookup M-a instead. Sadly, you'll need a lot of these bindings. If someone writes up a patch/package that can automatically provide all these bindings, I'd be happy to include it in Emacs.

Searching with intelligent bracket counting (Elisp)

I have the following function that deletes the LaTeX command surrounding the current cursor position:
(defun remove-tex-cmd ()
(interactive)
(save-excursion
(let (cur-point beg-point end-point)
(setq cur-point (point))
(catch 'notexcmd
(if (not (re-search-backward "\\.*?{" nil t)) ; now the point is at the {
(throw 'notexcmd nil))
(search-backward "\\" nil t)
(setq beg-point (point))
(re-search-forward "}")
(setq end-point (point))
(if (> end-point cur-point)
(kill-region beg-point end-point))
(throw 'notexcmd nil)))
(if 'notexcmd
(message "no tex command at point"))))
It works well except for the following situation, because it simply matches the next closing }:
\test{a<cursor here>sdf ${bla}+1$}
results in
+1$}
I could, of course, count the opening and closing brackets. However, as this problem should occur frequently, I wonder whether there exists some more intelligent search function, or am I missing a totally different point?
Use list- or sexp- based operations:
(defun remove-tex-cmd ()
(interactive)
(backward-up-list 1)
(backward-sexp 1)
(kill-sexp 2))
To handle scan error when outside parentheses:
(defun remove-tex-cmd ()
(interactive)
(condition-case nil
(progn
(backward-up-list 1)
(backward-sexp 1)
(kill-sexp 2))
(scan-error (message "Outside parentheses."))))

Resources