TN

TN

Gnu-emacs user.

I use Emacs from within Debian, Ubuntu, and Cygwin.

Using Emacs from within cygwin

Problem: aspell crashes with messages like:

    "^M.cset" could not be opened for reading or does not exist.lib/aspell/
    Aborted

Characteristic in this kind of error messages is the carry return character "^M". Maybe, it is not even printed. Then the error messages often look like there is a file name missing.

Error description: One cause of this error may be that the personal word list file or other configuration files of aspell in the user’s home directory have DOS-line ends (CR-LF "carry return"+"line feed").

The "carry return" is wrongly interpreted by aspell as configuration information. Often it is mistaken as a file name and the corresponding file can naturally not be found.

For example, this error occurs when you switch off the low-level CR-LF conversion of Cygwin. This may cause some trouble in finding the error since at a first glance it has nothing to do with emacs or aspell.

Fix: For each of the configuration files of aspell in your home directory (matching the file pattern .aspell*)

  1. load it into emacs
  2. change End-of-line style to unix by clicking onto "(DOS)" until it changes into ":"; This should mark the file as modified.
  3. save the file.

Code-snippets

How does the element order of two lists differ?

(defun get-permutation (l1 l2)
"Given two lists l1 and l2 return a list of integers li such that (`nth' i li)
is the index of element (nth i l1) in l2. Thereby, the elements of l1 and l2 are identified with `equal' and numbering of indices starts with zero (as for `nth')."
(let* ((i 0)
 (dict (mapcar '(lambda (x) (prog1 (cons x i) (setq i (1+ i)))) l1)))
  (mapcar
   '(lambda (x) (cdr (assoc x dict))) l2)))

Add a filter function to dired

Just the opposite of dired-omit
(add-hook 'dired-after-readin-hook 'dired-file-name-filter-handler)

(defvar dired-file-name-filter nil
  "*File name filter. Only files with name matching the regexp dired-file-name-filter are shown in the dired buffer.")

(make-variable-buffer-local 'dired-file-name-filter)

(defvar dired-filter-name-marker 16)

(defun dired-file-name-filter (filter)
  "Set variable `dired-file-name-filter' to filter."
  (interactive "sFile name filter regexp (or empty string for no filter):")
  (setq dired-file-name-filter (if (= (length filter) 0) nil filter))
  (dired-revert))

(define-key dired-mode-map [menu-bar regexp filter] '(menu-item "Filter" dired-file-name-filter :help "Set file name filter."))

(define-key dired-mode-map (kbd "% f") 'dired-file-name-filter)

(defun dired-file-name-filter-handler ()
  "To be hooked into `dired-after-readin-hook'."
  (when dired-file-name-filter
    (goto-char (point-min))
    (insert "Dired Filter Name Filter:" dired-file-name-filter)
    (let ((dired-marker-char dired-filter-name-marker))
      (dired-map-dired-file-lines
       '(lambda (name)
	  (unless (string-match dired-file-name-filter name)
	    (dired-mark 1)
	    )))
      (dired-do-kill-lines nil (concat "Filter" dired-file-name-filter " omitted %d line%s")))))

List distinct matches of a regular expression

(defun unique-matches (re &optional n b e)
  "Return a list of all distinct occurences of the regular expression RE within region from B to E. If B and E are nil then search from point to end of buffer. If called interactively the list goes to the kill-ring. The optional argument N is the parenthesized expression of RE which should be listed. It defaults to 0."
  (interactive "sRegular expression:\nMNumber of subexpression (default: 0):")
  (if (stringp n) (setq n (string-to-number n)))
  (if (and (called-interactively-p) (use-region-p))
      (progn
	(setq b (region-beginning))
	(setq e (region-end))))
  (let (ret)
    (save-excursion
      (unless n (setq n 0))
      (unless b (setq b (point)))
      (unless e (setq e (point-max)))
      (goto-char b)
      (while (search-forward-regexp re e 'noErr)
	(add-to-list 'ret (match-string-no-properties n)))
      (setq ret (nreverse ret))
      (message "Matches found: %s" ret)
      (if (called-interactively-p)
	  (progn
	    (kill-new (format "%s" ret))))
      ret)))

Load files from bash into emacs

Put the lines below into your .bashrc-file. After that you can load files from the bash command line with

e FILENAME

and pipe text into emacs via

echo "Hello world" | e -

Lines to be put into .bashrc:

e() {
    local TMP="`mktemp /tmp/emacsstdinXXX`";
    if [[ "$1" == "-" ]]; then
	cat >"$TMP";
	emacsclient -a /usr/bin/emacs --eval "(let ((b (create-file-buffer \"*stdin*\"))) (switch-to-buffer b) (insert-file-contents \"${TMP}\"))";
	rm "$TMP";
    else
	emacsclient --no-wait -a /usr/bin/emacs "$@" &
    fi;
}

TeX-texify: Get everything done for a LaTeX-file

In AUCTeX-mode one uses `TeX-command´ to invoke the next compilation step for the current LaTeX-document. Note, that this command is bound to the key-sequence C-c C-c.

If one has some citations and references in the document one needs to call `TeX-command´ multiple times. Within the following code the command `TeX-texify´ is defined which runs as often as it is suggested by `TeX-command´.

(require 'tex-buf)
(defun TeX-command-default (name)
  "Next TeX command to use. Most of the code is stolen from `TeX-command-query'."
  (cond ((if (string-equal name TeX-region)
			     (TeX-check-files (concat name "." (TeX-output-extension))
					      (list name)
					      TeX-file-extensions)
			   (TeX-save-document (TeX-master-file)))
			 TeX-command-default)
			((and (memq major-mode '(doctex-mode latex-mode))
			      (TeX-check-files (concat name ".bbl")
					       (mapcar 'car
						       (LaTeX-bibliography-list))
					       BibTeX-file-extensions))
			 ;; We should check for bst files here as well.
			 TeX-command-BibTeX)
			((TeX-process-get-variable name
						   'TeX-command-next
						   TeX-command-Show))
			(TeX-command-Show)))


(defcustom TeX-texify-Show t "Start view-command at end of TeX-texify?" :type 'boolean :group 'TeX-command)
(defcustom TeX-texify-max-runs-same-command 5 "Maximal run number of the same command" :type 'integer :group 'TeX-command)

(defun TeX-texify-sentinel (&optional proc sentinel)
  "Non-interactive! Call the standard-sentinel of the current LaTeX-process.
If there is still something left do do start the next latex-command."
  (set-buffer (process-buffer proc))
  (funcall TeX-texify-sentinel proc sentinel)
  (let ((case-fold-search nil))
    (when (string-match "\\(finished\\|exited\\)" sentinel)
      (set-buffer TeX-command-buffer)
      (unless (plist-get TeX-error-report-switches (intern (TeX-master-file)))
	(TeX-texify)))))

(defun TeX-texify ()
  "Get everything done."
  (interactive)
  (let ((nextCmd (TeX-command-default (TeX-master-file)))
	proc)
    (if (and (null TeX-texify-Show)
	     (equal nextCmd TeX-command-Show))
	(when  (called-interactively-p 'any)
	  (message "TeX-texify: Nothing to be done."))
      (TeX-command nextCmd 'TeX-master-file)
      (when (or (called-interactively-p 'any)
		(null (boundp 'TeX-texify-count-same-command))
		(null (boundp 'TeX-texify-last-command))
		(null (equal nextCmd TeX-texify-last-command)))
	(mapc 'make-local-variable '(TeX-texify-sentinel TeX-texify-count-same-command TeX-texify-last-command))
	(setq TeX-texify-count-same-command 1))
      (if (>= TeX-texify-count-same-command TeX-texify-max-runs-same-command)
	  (message "TeX-texify: Did %S already %d times. Don't want to do it anymore." TeX-texify-last-command TeX-texify-count-same-command)
	(setq TeX-texify-count-same-command (1+ TeX-texify-count-same-command))
	(setq TeX-texify-last-command nextCmd)
	(and (null (equal nextCmd TeX-command-Show))
	     (setq proc (get-buffer-process (current-buffer)))
	     (setq TeX-texify-sentinel (process-sentinel proc))
	     (set-process-sentinel proc 'TeX-texify-sentinel))))))

(add-hook 'LaTeX-mode-hook '(lambda () (local-set-key (kbd "C-c C-a") 'TeX-texify)))

auctex-preview: keep old preview visible when editing

I don’t like it if auctex hides the old preview for a formula while I edit it. With the following snippet (e.g., in .emacs) you can keep the old preview:

(defadvice preview-inactive-string (around preview-show-old nil activate)
  "Show old preview when editing source code."
  (when (overlay-get ov 'preview-state)
    (let ((preview-icon (or (car-safe (overlay-get ov 'preview-image)) preview-icon)))
      (overlay-put ov 'preview-old-image preview-icon)
      ad-do-it
      )))

(defadvice preview-disabled-string (around preview-show-old nil activate)
  "Show old preview when editing source code."
  (when (overlay-get ov 'preview-state)
    (let ((preview-icon (or (overlay-get ov 'preview-old-image) preview-icon)))
      ad-do-it
      )))

auctex-preview: Scale preview images with respect to the buffer-local face size

One can change the buffer local face size with the help of text-scale-increase and text-scale-decrease from text-scale-mode (key strokes C-x C-+ and C-x C--). The following advice synchronizes the size of the preview images with the buffer local face size. Usage: Install the package by pasting the following advice into your .emacs file. In an auctex-buffer with previews first adjust the font size with C-x C-+ or C-x C– and then regenerate the previews with C-c C-p C-d.

(require 'face-remap)
(defadvice preview-inherited-face-attribute (after preview-inherit-local-face nil activate)
  "Scale preview images with respect to buffer-local face"
  (when (eq attribute :height)
    (message "advice preview-inherit-face-attribute")
    (let ((scale-amount text-scale-mode-amount)
	  (scale-factor text-scale-mode-step))
      (when (< scale-amount 0)
	(setq scale-amount (- scale-amount))
	(setq scale-factor (/ 1.0 scale-factor)))
      (while (> scale-amount 0)
	(setq ad-return-value (* scale-factor ad-return-value))
	(setq scale-amount (1- scale-amount)))
      )))

Pasting images from ms-windows clipboard into cygwin-emacs

Images cannot directly be pasted from the clipboard in cygwin (only text is supported). Therefore, one needs some windows program to grab the image from the clipboard and save it to a file. This is done via wpython2.7 and the python imaging library (PIL).

Short cut for pasting is C-S-y. Interfaces for org and auctex are defined.

(defvar pythonw-interpreter "/c/Python27/python.exe"
  "Python interpreter for retrieving images from the windows console.")

(defun new-file-name (prefix suffix)
  "Get name of non-existing file by inserting numbers between PREFIX and SUFFIX if necessary.
SUFFIX may not include directory components."
  (let ((first-try (concat prefix suffix))
	(prefix-dir (or (file-name-directory prefix) "./"))
	(prefix-file (file-name-nondirectory prefix)))
    (if (file-exists-p first-try)
	(concat
	 prefix
	 (number-to-string
	  (1+
	   (apply
	    'max
	    (append '(-1)
	    (mapcar #'(lambda (name)
		       (string-to-number (substring name (length prefix-file) (- (length suffix)))))
		    (directory-files prefix-dir nil (concat prefix-file "[0-9]+" suffix) 'NOSORT))))))
	 suffix)
      first-try)))

(require 'image)
(defvar paste-image-hook nil "Run after pasting images from clipboard.")
(make-variable-buffer-local 'paste-image-hook)

(defvar paste-image-prefix "" "Prefix to be inserted before the pasted image.")
(make-variable-buffer-local 'paste-image-prefix)

(defvar paste-image-postfix "" "Postfix to be inserted after the pasted image.")
(make-variable-buffer-local 'paste-image-postfix)

(defvar paste-image-type "png" "Default image type and extension of pasted images.")
(make-variable-buffer-local 'paste-image-type)

(unless (assoc "\\.eps" image-type-file-name-regexps)
  (add-to-list 'image-type-file-name-regexps '("\\.eps" . postscript)))

(defvar paste-image-types
  '(
    ("png")
    ("eps" "png" "convert %< -compress lzw ps3:%>")
    )
  "Each type specifier is a list. nth 0 is the target image format. nth 1 is the source image format and nth 2 is the converter from target to source %< stands for the source and %> stands for the output."
  )

(defun paste-image-type-from-file-name (name)
  "Return image type for paste-image"
  (car (assoc (downcase (file-name-extension name)) paste-image-types)))

(defun paste-image-paste (dir-name target-name img-type)
  (let*
      ((img-type-list (assoc img-type paste-image-types))
       (grab-type (or (nth 1 img-type-list) (car img-type-list)))
       (converter (nth 2 img-type-list))
       (src-name target-name)
       )
    (unless grab-type
      (error "Unsupported image grab type %s. (See paste-image-types.)" img-type))
    (when converter
      (setq src-name (concat target-name "." grab-type))
      )
    (with-temp-buffer
      (setq default-directory dir-name)
      (insert "
from PIL import Image, ImageGrab
print \"--- Grab Image From Clipboard ---\"
im=ImageGrab.grabclipboard()
if isinstance(im,Image.Image):
 im.save(\"" src-name "\",\"" (upcase grab-type) "\")
else:
 print \"paste-image-paste:No image in clipboard.\"
")
      (call-process-region (point-min) (point-max) pythonw-interpreter t t nil)
      (goto-char (point-min))
      (if (search-forward "paste-image-paste:No image in clipboard." nil 'noError)
	  (error "No image in clipboard."))
      (message "%s" (buffer-substring-no-properties (point-min) (point-max)))
      (when converter
	(setq converter (string-replace-matches converter "%<" src-name))
	(setq converter (string-replace-matches converter "%>" target-name))
	(shell-command converter)
	))
    ))

(defun paste-image (&optional file-name img-type)
  "Paste image from windows clipboard into buffer.
That means put the image into the directory with the basename of the buffer file.
The image gets a name 'imgXXX.png' where XXX stands for some unique number."
  (interactive)
  (unless img-type
    (setq img-type paste-image-type))
  (unless file-name
    (let* ((dir-name (file-name-sans-extension (buffer-file-name)))
	   (file-path (new-file-name (concat dir-name "/img") (concat "." img-type))))
      (setq dir-name (file-name-directory file-path))
      (setq file-name (file-name-nondirectory file-path))
      (while
	  (progn
	    (setq file-path (read-file-name "Image file name:" dir-name nil nil file-name))
	    (let ((dir (file-name-directory file-path)))
	      (or (and
		   dir
		   (file-exists-p dir)
		   (null (file-directory-p dir)))
		  (null (and (file-name-extension file-path)
			     (setq img-type (paste-image-type-from-file-name file-path))))))))
      (setq file-name file-path)))
  (let* ((cur-dir default-directory)
	 (dir-name (or (file-name-directory file-name) "./"))
	 (dir-name-noslash (directory-file-name dir-name))
	 (fname (concat (file-name-nondirectory file-name)
			(if img-type
			    (if (string-match (concat "\\." paste-image-type "$") file-name)
				""
			      (concat "." paste-image-type))
			  (progn (setq img-type "png") ".png")))))
    (if (file-exists-p dir-name-noslash)
	(unless (file-directory-p dir-name-noslash)
	  (error "%s is not a directory" dir-name))
      (make-directory dir-name-noslash))
    (if img-type
	(if (symbolp img-type)
	    (setq img-type (symbol-name img-type)))
      (error "Image type not set."))
    (paste-image-paste dir-name fname img-type)
    (insert paste-image-prefix (file-relative-name dir-name cur-dir) fname paste-image-postfix)
    (run-hooks paste-image-hook)))

(global-set-key (kbd "C-S-y") 'paste-image)


(add-hook 'org-mode-hook '(lambda ()
			    (setq paste-image-prefix "[[file:")
			    (setq paste-image-postfix"]]")
			    (setq paste-image-hook 'org-display-inline-images)
			    ))


(add-hook 'LaTeX-mode-hook (lambda ()
			     (setq paste-image-prefix "\\includegraphics{")
			     (setq paste-image-postfix "}")
			     (setq paste-image-type "eps")
			     (add-hook 'paste-image-hook 'preview-at-point)
			     ))

Using xpdf as viewer with forward and inverse search

xpdf exists in cygwin and in linux and can be configured for forward and inverse search using synctex.

One clumsy method is shown here that overcomes some problems such as that emacsclient cannot be started from the xpdf-mouse bindings because of the obscuring parenthesis.

Note however, that this is a fast hack!

Prerequisites: “xpdf”, “synctex”, “bash”, “bc”, and “pgrep” must be installed additionally to “emacs”.

The “.xpdfrc”-file in the users home directory should contain the line:

bind ctrl-mousePress1 any "run(xpdfsynctex edit %i %j %k)"

There should be the executable shell script “xpdfsynctex” in the users command path:

#!/usr/bin/bash
LOG=xpdfsynctex.log

echo "Running $0" "$@" > ${LOG}

declare -A FIELDS 

INPUT="`zgrep Input:1: *.synctex.gz`"
INPUT="${INPUT/Input:1:/}"

tofields () {
for ((i=1; i <= ${#EDIT[@]}; i=i+1 )); do
    IFS=:
    tmp=(${EDIT[$i]})
    if [[ "${tmp[0]}" != "" ]]; then
	eval FIELDS["${tmp[0]}"]="${tmp[1]}"
 	echo "FIELDS[${tmp[0]}]=${tmp[1]}" >> ${LOG}
    fi
done;   
}

echo "INPUT=${INPUT}" >> ${LOG}

HEIGHT=842
echo "Assuming A4 with $HEIGHT pt (72dpi)." >> ${LOG}

if [[ "$1" == "edit" ]]; then

PAGE=$2
X=$3
Y_FROM_BOTTOM=$4
Y=`bc <<< "${HEIGHT}-${Y_FROM_BOTTOM}"`

echo "Position in dots from top left: X=$X, Y=$Y on page ${PAGE}." >> ${LOG};

IFS="
"
EDIT=(`synctex edit -o ${PAGE}:$X:$Y:${INPUT}`)

tofields

CMDLINE="emacsclient -a /usr/bin/emacs -e \"(find-file \\\"${INPUT}\\\")\" -e \"(goto-line ${FIELDS[Line]})\""

echo "Executing:${CMDLINE}"  >> ${LOG}

eval ${CMDLINE}  >> ${LOG}

elif [[ "$1" == "view" ]]; then

BASENAME=$2
LINE=$3
COLUMN=$4
EDIT=(`synctex view -i ${LINE}:${COLUMN}:${INPUT} -o ${BASENAME}.pdf`)

tofields

PAGE=${FIELDS[Page]}
XTL=${FIELDS[x]}
YTL=`bc <<< "${HEIGHT}-${FIELDS[y]}"`
XBR=`bc <<< "$XTL+${FIELDS[W]}"`
YBR=`bc <<< "$YTL-${FIELDS[H]}"`

CMDLINE="xpdf -remote xpdfServer${BASENAME} ${BASENAME}.pdf";

if ! pgrep -x -n ${CMDLINE}; then
    echo "Starting \"${CMDLINE}\"" >> ${LOG}
    eval ${CMDLINE} >> ${LOG} &
    sleep 1
else
    echo "Server \"${CMDLINE}\$ already running." >> ${LOG}
fi

CMDLINE="xpdf -remote xpdfServer${BASENAME} -exec \"gotoPage(${PAGE})\""
echo "Executing:${CMDLINE}" >> ${LOG}
eval ${CMDLINE} >> ${LOG}

CMDLINE="xpdf -remote xpdfServer${BASENAME} -exec \"setSelection(${PAGE},$XTL,$YTL,$XBR,$YBR)\""
echo "Executing:${CMDLINE}" >> ${LOG}
eval ${CMDLINE} >> ${LOG}

else
echo help # todo
fi

In the users initialization there should be the lines:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Using xpdf as viewer:

(add-hook 'LaTeX-mode-hook
	  '(lambda ()
	     (setcdr (assoc "LaTeX" TeX-command-list) '("%`%l%(mode)%' %t; dvipdf %d > /dev/null; pgrep -x -f \"xpdf -remote xpdfServer%s %s.pdf\" && xpdf -remote xpdfServer%s -reload" TeX-run-TeX nil   (latex-mode doctex-mode)   :help "Run LaTeX"))
	     (setcdr (assoc "View" TeX-command-list) '("xpdfsynctex view %s %n 1" TeX-run-background nil t :help "Run Viewer"))
	     ))

Multiple languages in one buffer (e.g. flyspell in latex-document with \selectlanguage)

The following piece of code lightens the input of multilingual text. It switches the ispell-dictionary in dependence of the language at the current point position. The points in the buffer where the language switches are recognized by predefined strings at the beginning of line (see variables swl-regexp and swl-alist).

Paste the following into your .emacs.el file (or wherever your configuration is). Adapt the variables swl-regexp and swl-alist to your needs. Currently, detecting between english and ngerman in babel-latex documents is configured. Then open your document and start swl-mode by M-x swl-mode. (You can do this automatically by a mode-hook, such as latex-mode-hook.) The dictionary to be used for flyspell or ispell is then recognized automagically in dependence of the point-position.

(require 'ispell) ;; for variables ispell-dictionary and so on

(defcustom swl-regexp "^\\\\\\(?:selectlanguage{\\([[:alnum:]]+\\)}\\|usepackage\\[\\(?:[[:alnum:]]+,\\)\\([[:alnum:]]+\\)\\]{babel}\\)"
  "Regular expression for `swl-mode' to detect language changes.
The first matching sub-expression defines the new language. It should match one of the languages given in `swl-alist'.
This variable is buffer local. This way you can make it mode-dependent with the help of mode-hooks."
  :group 'swl
  :type 'regexp)
(make-variable-buffer-local 'swl-regexp)

(defcustom swl-alist '(
		    ("english" . "en_US")
		    ("ngerman" . "de_DE")
		    ("russian" . "ru"))
  "List of language switchers.
Each language switcher is a cons of a string that introduces a new language
and the corresponding `ispell-dictionary'."
  :group 'swl
  :type '(repeat cons))
(make-variable-buffer-local 'swl-alist)

(defun first-match-substring ()
  "Get the first non-nil result of (`match-string-noproperties' i) for i=1,...,last subexpr."
  (loop for i from 1 below (/ (length (match-data)) 2)
	thereis (match-string-no-properties i)))

(defun swl-jit-handler (b e)
  "(Re-)scan buffer for language switches."
  (save-excursion
    (with-silent-modifications
      (let (lang)
	(goto-char b)
	(beginning-of-line -1) ;; One line back to force overlapping with old formatted region.
	(setq b (point))
	(unless (setq lang (get-text-property (point) :ispell-dictionary))
	  ;; No dictionary found at the starting point of the region.
	  (if (search-backward-regexp swl-regexp nil 'noErr)
	      (setq lang (cdr (assoc-string (first-match-substring) swl-alist))
		    b (1+ (match-beginning 0)))
	    (setq lang swl-default-dictionary
		  b (point-min))))
	;; Now we have the real starting point b for formatting and a
	;; non-nil language lang.
	(while (search-forward-regexp swl-regexp e 'noErr)
	  (put-text-property b (match-beginning 0) :ispell-dictionary lang)
	  (setq b (1+ (match-beginning 0))
		lang (cdr (assoc-string (first-match-substring) swl-alist))))
	(put-text-property b e :ispell-dictionary lang)
	))))

(defun swl-eye ()
  "Switching `ispell-local-dictionary' depending on the text property :ispell-dictionary"
  (let ((newLang (get-text-property (point) :ispell-dictionary))
	(curLang (or ispell-local-dictionary ispell-dictionary swl-default-dictionary)))
    (unless (string= newLang curLang)
      (ispell-change-dictionary newLang)
      )))

(defvar swl-default-dictionary nil
  "Default buffer-local dictionary for `swl-mode' (switch language mode).
It does not make sense to change the default value since it automatically from `ispell-local-dictionary' or `ispell-dictionary'.")
(make-variable-buffer-local 'swl-default-dictionary)

(define-minor-mode swl-mode "Switch `ispell-dictionary' corresponding to the entries in `swl-alist'." nil " swl" nil
  (if swl-mode
      (progn
	(setq swl-default-dictionary
	      (or
	       ispell-local-dictionary
	       ispell-dictionary
	       "default"))
	(jit-lock-register 'swl-jit-handler)
	(add-hook 'post-command-hook 'swl-eye 'append t)
	)
    (jit-lock-unregister 'swl-jit-handler)
    (remove-hook 'post-command-hook 'swl-eye t)
    (unintern 'swl-default-dictionary)
    ))

Extending org-mode search features

With this extension of org-mode you can use links [[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.

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)
(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)

Grepping without dependence on external programs

Call M-x elgrep for grepping the files in one directory for a regular expression. With prefix-arg elgrep recurses into sub-directories. Output goes into a grep-buffer with all its features.

Okay without external dependencies is no longer entirely true. If pdf files are grepped then pdftotext from poppler is needed.

If you do not give a regular expression it just searches for the files like ‘find’.

The code of elgrep has moved to https://github.com/TobiasZawada/elgrep.

Welcome to the wiki. – DrewAdams

Thank you. Especially, for adding CategoryHomepage! Didn’t find the hints for homepage creation before. – TN


CategoryHomepage