More Emacs Snippets

Today I read a great blog post by Justin Davis in which he shares useful snippets from his personal Emacs configuration. I shared some of my own back in June. Reading Justin’s nice utilities motivated me to share some more of my own.

Guessing at the Best Markup Mode

James Clark’s nxml-mode is terrific for XML. A lot of people I know also prefer to use it for HTML as well. However, I prefer to use a variety of modes for such documents, and I use the following function to pick my preferred mode based on the file I’m editing:

(defun html-or-sgml-or-nxml-mode ()
  "Will active either `html-mode', `sgml-mode' or `nxml-mode'
based on the file associated with the current buffer."
  (interactive)
  (let ((file-extension
         (substring (buffer-file-name) -4))
        (html-extensions '("html" ".htm"))
        (sgml-extensions '(".dtd")))
    (cond ((member file-extension html-extensions)
           (html-mode))
          ((member file-extension sgml-extensions)
           (sgml-mode))
          (t (nxml-mode)))))

Deleting XML With XPath Expressions

Related to the above, I use this function to delete all content in an XML document that matches a given XPath expression:

(defun remove-xml-content-by-xpath (xpath-expression)
  "Removes all content from the buffer described by the given
XPath expression.  This function relies on the program `xml-rm'."
  (interactive "MXPath Expression: ")
  (save-excursion
    (shell-command-on-region
     (point-min)
     (point-max)
     (format "xml-rm :%s" xpath-expression)
     t)
    (indent-region (point-min) (point-max))))

The function is nothing more than a wrapper around xml-rm, which is part of Laird Breyer’s xml-coreutils, a nice set of command-line tools for XML.

Delete the File of a Buffer

Note: I often prefix my personal snippets with ejmr/ to avoid conflicts with Emacs packages.

Sometimes when I kill a buffer I want to delete its file at the same time, which I do with this:

(defun ejmr/delete-file-and-kill-buffer ()
  "Kill the current buffer and delete the file it visits."
  (interactive)
  (let ((filename (buffer-file-name)))
    (when filename
      (if (vc-backend filename)
          (vc-delete-file filename)
        (progn
          (delete-file filename t)
          (message "Deleted file %s" filename)
          (kill-buffer))))))

I also use (setq delete-by-moving-to-trash t) so that the deletion functions put the file in my trash, giving me the chance to restore it just in case. I recommend enabling that behavior because all of us accidentally hit the wrong key now and then, and I’ve certainly deleted files by mistake.

Converting Markdown Documents

I’m always writing things in Markdown. Jason Blevins’ markdown-mode is my favorite package when it comes to writing the documents themselves. But I often convert my Markdown documents to other formats and for that I use Pandoc, a versatile converter by John MacFarlane. So I use this piece of Emacs Lisp to convert a buffer of Markdown to some other format via Pandoc:

(defun convert-markdown-to (newtype)
  "Converts the current buffer, assumed to be in Markdown format,
into a new format.  The new format must be one acceptable to
`Pandoc'.  The function opens the new file in a buffer if called
interactively.  If not called interactively then it returns the
name of the new file."
  (interactive "sOutput: ")
  (let ((current-document (buffer-file-name))
        (temp-filename (concat "/tmp/output." newtype)))
    (with-temp-file temp-filename
      (call-process-shell-command (concat "pandoc -f markdown -t " newtype)
                                  nil t nil current-document))
    (cond ((called-interactively-p 'any)
           (with-current-buffer (find-file temp-filename)))
          (t temp-filename))))

(define-key markdown-mode-map (kbd "C-c c") 'convert-markdown-to)

Syohei Yoshida’s quickrun.el has a similar utility, and I recommend checking it out regardless of whether or not you use Markdown or Pandoc.

Advertisements

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s