Emacs Lisp: by Example

"Aaron S. Hawley" <[email protected]>
Newsgroups gmane.org.ballistichelmet.lambda
Organization University of Vermont
Message-ID <[email protected]>
;;;; Emacs Lisp: by Example
;;; Text Processing and Interaction Facilities
;; February 13 2004
;; Aaron Hawley
;;
;; Emacs Lisp has much of the regular expression power of Perl with
;; the invaluable addition of interactive capabilities.  Below are
;; some examples.  The ability to modify text files is but a taste of
;; the functionality of Emacs and her lisp extension language.  The
;; following functions present some common uses (regular expressions,
;; interaction, highlighting, user prompts) and mistakes (watch for
;; case sensitivity) of writing Emacs Lisp.  The last function proves
;; the point that a search-and-replace (no matter how strong a regular
;; expression) cannot always successfully complete a task that demands
;; human intervention.  These functions were developed in GNU Emacs 21.

(defun mytext-next-all-caps-heading ()
  "Finds a text heading because it is in all caps."
  (interactive)
  (message "Finding text headings ...")
  (push-mark) ;; start from current cursor position
  (let ((case-fold-search nil)) ;; set to case-sensitive.
    (if (re-search-forward
	 "^[^a-z\n]+$"
	 nil ;; not bound
	 t) ;; quell errors
	(message "Found text heading.")
      (message "End of buffer"))))

(defun mytext-unjustify-buffer ()
  "Finds a text heading because it is in all caps."
  (interactive)
  (message "Finding text headings ...")
  (push-mark) ;; start from current cursor position
  (let ((case-fold-search nil)) ;; set to case-sensitive.

    ;; remove any spaces between single consecutive "word
    ;; constituents" (which really just means a single letter).
    (perform-replace
     " \\(\\w\\) +\\(\\w\\)\\b"
     "\\1\\2"
     nil ;; don't query
     t ;; is regexp
     nil)) ;; don't enforce word delimiting
  (message "Line unjustified"))

(defun mytext-indented-lines-to-paragraphs ()
  "Converts single space lines with indentation at beginning of
paragraphs to paragraphs with a blank line between each paragraph."
  (interactive)
  (message "Converting indented lines to paragraphs ...")
  (push-mark) ;; start from current cursor position
  ;; any line starting with blank characters should be changed
  ;; to a double line.
  (perform-replace
   "\n[[:blank:]]+\\b"
   "\n\n"
     nil ;; don't query
     t ;; is regexp
     nil) ;; don't enforce word delimiting
  (message "Indentation converted to paragraphs"))

(defun mytext-previous-word ()
  "Return the word previous to location ``point'' is on--return as a
string."
  (save-excursion (backward-word 1) (current-word)))

;; When using optical character recognition (OCR) scanning technology
;; or simply copying and pasting from print-oriented electronic
;; documents, hyphenation will be present at the end of lines.  To
;; correct this situation with a regular expression is a simple task.
;; Not all hyphens should be removed, however.  Because of the dual
;; meaning of a hyphen, it could very well be necessary for the word's
;; spelling.  So at each hyphenated line, the user is prompted ("yes"
;; or "no") whether to keep or remove the hyphen.
(defun mytext-remove-hyphenated-lines ()
  "Dehyphenates all lines in the buffer, and will wrap the word to the
next line.

Upon the arriving at a hyphenated line, the user will be queried as to
whether the word should maintain the hyphen or be concatenated without
the hyphen."
  (interactive)
  (setq hyphenated-lines 0) ;; counter
  (message "Removing end of line hyphens ...")
  (push-mark) ;; start from current cursor position.
  ;; search repeatedly for a hyphen at the end of a line.
  (while (re-search-forward "-[[:blank:]]*\n\\b"
			    (point-max) ;; go to end of buffer.
			    t) ;; quell errors.
    ;; increment counter.
    (setq hyphenated-lines (1+ hyphenated-lines))
    ;; save-excursion is handy: it allows you to move the cursor
    ;; around, retrieve and return a value but return the cursor back
    ;; to where it started.
    (let* ((hyphenated-word-start (save-excursion
				    (backward-word 1)
				    (point)))
	   (hyphenated-word-end (save-excursion
				  ;; go to end of word.
				  (forward-word 1)
				  (point)))
	   (hyphenated-word (concat
			     (mytext-previous-word)
			     (current-word)))
	   ;; Create an overlay over the span of the hyphenated word.
	   (highlight-overlay (make-overlay hyphenated-word-start
					    hyphenated-word-end)))
      ;; Set font face of the overlay of the high to highlight
      ;; (usually a inverse-video appearance).
      (overlay-put highlight-overlay 'face 'highlight)
      ;; Ask the user if the hyphen is truly part of the word or not.
      ;; FIXME: This could be accomplished much of the time by using
      ;; Emacs's spell-checking facilities.
      (if (y-or-n-p (concat "Remove hyphenation in \""
			    hyphenated-word
			    "\" ?"))
	  ;; If yes, remove hyphen from word.
	  (replace-match "")
	;; Else keep the hyphen in the word.
	(replace-match "-"))
      (delete-overlay highlight-overlay) ;; Remove highlighting.
      (backward-word 1) ;; Go to the beginning of the word.
      (open-line 1) ;; Make end-line, putting (wrapping) word to next
		    ;; line.
      (delete-trailing-whitespace)
      (undo-boundary) ;; have the each iterative modification be a
		      ;; single undo, rather than a single undo of
                      ;; all the work done by this function.
      (forward-line))) ;; Done with this line, continue on next.
  ;; END: report how many lines were fixed.
  (message (concat "Fixed "
		   (number-to-string hyphenated-lines)
		   " hyphenated lines")))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.