Xah Lee, 2006-09
On the website xahlee.org, over 2000 HTML pages are manually created with emacs.
This page provides some tips about using Emacs to create and edit HTML documents. If you do not know the basics of emacs, please see: Emacs Intermediate.
First, turn on the CUA mode, under the menu “Options‣C-x/C-c/C-v Cut and Paste (CUA)”. Also, turn on “Options‣Paren Match Highlighting”, then select “Options‣Save Options”.
The CUA mode will make emacs behave more like modern applications:
In emacs, when you open a file ending in “html”, it'll automatically open in html-mode.
How to insert a tag?
html-mode provides many shortcuts to insert tags. Here's a list of tags you can insert and their keyboard shortcuts and command names.
tag keystroke command name --------------------------------------------------- <h1> Ctrl+c 1 html-headline-1 <h2> Ctrl+c 2 html-headline-2 <p> Ctrl+c RET html-paragraph <hr> Ctrl+c Ctrl+c - html-horizontal-rule <ul> Ctrl+c Ctrl+c u html-unordered-list <li> Ctrl+c Ctrl+c l html-list-item
For a complete list of shortcuts, pull the graphical menu HTML or SGML, or, type “Alt+x html-mode” then “Ctrl+h m” to see the list.
How to insert a ending tag?
Place your cursor at the place where you want to insert the ending tag, then press “Ctrl+c /”.
How to insert my custom tag?
Put the following code in your emacs init file. Then, can press F8, and your custom tag will be inserted, and your cursor point will be placed in between them.
(global-set-key (kbd "<f8>") 'insert-p) (defun insert-p () "Insert HTML markup <p></p>." (interactive) (insert "<p>\n</p>") (backward-char 5) )
You can change the string in the above code so that it will insert another tag that you use frequently, or even a text template, such as headers and footers. You can also change the keyboard shortcut.
Here's the elisp code that allows you to insert a tag with a class value. For example, type on a line “pre poem”, then “Alt-x insert-div”, then it'll become “<pre class=\"poem\"></pre>”.
(defun insert-div () "Insert a HTML tag “<thing1 class=\"thing2\"></thing1>”. The thing1 and thing2 are strings on the current line. For example, if your cursor is on a line: pre poem then it'll become <pre class=\"poem\"></pre> If the current line has only one word, “div” is used for the tag name." (interactive) ; algorithm outline: grab current line ;parse it into 2 things ;insert <thing1 class="thing2"></thing1> ;move cursor into the mid (let (bds p1 p2 goodies tagname attr-val) (setq bds (bounds-of-thing-at-point 'line)) (setq p1 (car bds) p2 (cdr bds)) (setq goodies (split-string (buffer-substring p1 p2) " +")) (if (equal (length goodies) 1) (progn (setq tagname "div") (setq attr-val (nth 0 goodies))) (progn (setq tagname (nth 0 goodies)) (setq attr-val (nth 1 goodies)))) (setq attr-val (substring attr-val 0 -1)) ; remove line ending char (delete-region p1 p2) (insert (concat "<" tagname " class=\"" attr-val "\"></" tagname ">\n")) (search-backward "<")))
How to delete a tag?
Put your cursor on or inside the tag, then press “Ctrl+c DEL” (sgml-delete-tag). This will delete both starting and ending tags. Very convenient.
How to make the cursor jump to the ending tag?
“Ctrl+c Ctrl+f” (sgml-skip-tag-forward). Also, to move to the beginning of a tag pair, do “Ctrl+c Ctrl+b”. The f is for forward, and b for backward.
How to generate a link?
Press “Ctrl+c Ctrl+c h” (html-href-anchor). Emacs will then ask you to type a url, then insert it with the closing “</a>”, with your cursor placed before it so that you can type the link text.
Alternatively, you can place the following lisp code in your emacs init file:
(defun wrap-url () "Make thing at cursor point into a HTML link.\n Example: http://wikipedia.org/ becomes <a href=\"http://en.wikipedia.org/\">http://wikipedia.org/</a>" (interactive) (re-search-backward "[\n\t ()]" nil t) (looking-at "[\n\t ()]?\\([^\n\t ()]+\\)") (let ( (p1 (match-beginning 1)) (p2 (match-end 1)) (url (match-string 1)) ) (delete-region p1 p2) (goto-char p1) (insert "<a href=\"" url "\">" url "</a>" ) ) ) (add-hook 'html-mode-hook (lambda () (define-key html-mode-map "\M-5" 'wrap-url) ) )
With this code, pressing “Alt+5” will automatically make the url your cursor is on into a link. For a detailed explanation of the code and a more robust version, see Elisp Lesson: wrap-url.
How to insert a inline img tag?
Press “Ctrl+c Ctrl+c i” (html-image), then type the url for the image. Alternatively, you can place the following code into your emacs init file.
(defun image-linkify () "Replace a path to image file with a HTML img tag. Example, if cursor is on the word “emacs_logo.png”, then it will became “<img src=\"emacs_logo.png\" alt=\"emacs logo\" width=\"123\" height=\"456\">”." (interactive) (let (img-file-path bounds img-dim width height altText myResult) (setq img-file-path (thing-at-point 'filename)) (setq bounds (bounds-of-thing-at-point 'filename)) (setq altText (file-name-nondirectory img-file-path)) (setq altText (replace-regexp-in-string "\\.[A-Za-z]\\{3,4\\}$" "" altText t t)) (setq altText (replace-regexp-in-string "_" " " altText t t)) (setq img-dim (get-image-dimensions img-file-path)) (setq width (number-to-string (car img-dim))) (setq height (number-to-string (car (last img-dim)))) (setq myResult (concat "<img src=\"" img-file-path "\"" " " "alt=\"" altText "\"" " " "width=\"" width "\" " "height=\"" height "\">")) (save-excursion (delete-region (car bounds) (cdr bounds)) (insert myResult)) )) (defun get-image-dimensions (img-file-relative-path) "Returns a image file's width and height as a list." (let (tmp dimen) (clear-image-cache) (setq tmp (create-image (concat default-directory img-file-relative-path))) (setq dimen (image-size tmp t)) (list (car dimen) (cdr dimen)) ) ) (global-set-key (kbd "<f5>") 'image-linkify)
To insert a local inline image using this code, first type the relative path of the image. Then, pressing F5 will turn it into a inline image, with “alt” and “height” and “width” attributes.
For a detailed explanation of this code, see: Linkify A Image Path.
How to insert a HTML table?
The following code will turn the current text block into HTML table.
(defun make-html-table-string (textblock delim) "Turn a text string into a HTML table. See make-html-table." (let () (setq textblock (replace-regexp-in-string delim "</td><td>" textblock)) (setq textblock (replace-regexp-in-string "\n" "</td></tr>\n<tr><td>" textblock)) (setq textblock (substring textblock 0 -8)) ;; delet the beginning “<tr><td>” in last line (concat "<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n<tr><td>" textblock "</table>") )) (defun make-html-table (sep) "Turn the current paragraph into a HTML table. The “current paragraph” is defined as having empty lines before and after the block of text the curson is on. For example: a•b•c 1•2•3 this•and•that with “•” as separator, becomes <table border=\"1\" cellpadding=\"5\" cellspacing=\"0\"> <tr><td>a</td><td>b</td><td>c</td></tr> <tr><td>1</td><td>2</td><td>3</td></tr> <tr><td>this</td><td>and</td><td>that</td></tr> </table>" (interactive "sEnter string pattern for column separation:") (let (bds p1 p2 myStr) (setq bds (bounds-of-thing-at-point 'paragraph)) (setq p1 (+ (car bds) 1)) (setq p2 (cdr bds)) (setq myStr (buffer-substring-no-properties p1 p2)) (delete-region p1 p2) (insert (make-html-table-string myStr sep) "\n") ))
For detail on how this code works, see Elisp Lesson: Writing make-html-table.
The above is a simple method. Once you have created a html table, you can not easily add or delete row or columns. There is a method, that allows you to create table and edit table like a GUI application, including merging cells vertically or horizontally. It takes about 10 minutes to learn how to use it though. The commands are table-capture and table-generate-source (new in emacs 22). For a detailed tutorial, see: http://www.emacswiki.org/cgi-bin/emacs-en/TableMode
How to wrap a tag around the current word or selection?
Put the following in your emacs init file.
(defun wrap-text (aa bb) "Wrap strings aa and bb around current word or region." (save-excursion (let (p1 p2 myword) (if (and transient-mark-mode mark-active) (progn (setq p1 (region-beginning)) (setq p2 (region-end))) (progn (skip-chars-backward "-A-Za-z") (setq p1 (point)) (skip-chars-forward "-A-Za-z") (setq p2 (point)))) (setq myword (buffer-substring-no-properties p1 p2)) (goto-char p2) (insert bb) (goto-char p1) (insert aa)))) (defun wrap-span-xnt () "Wrap a HTML <span> tag around current word or region." (interactive) (wrap-text "<span class=\"xnt\">" "</span>")) (global-set-key (kbd "<f6>") 'wrap-span-xnt)
With the above code, pressing F6 or “Alt+x wrap-span-xnt” will wrap a <span class="xnt"> and </span> around the word your cursor is on, or the current selection if there's one. You can change code to wrap different tags. You can also define different keyboard shortcuts so that different press of keys will wrap different tags around the word. (such as, bold, italic, or any CSS class or style). See Defining Your Own Keyboard Shortcuts.
How to replace “&” by “&” in a region?
Place the following in your emacs init file:
(defun replace-string-pairs-region (start end mylist) "Replace string pairs in region." (save-restriction (narrow-to-region start end) (mapc (lambda (arg) (goto-char (point-min)) (while (search-forward (car arg) nil t) (replace-match (cadr arg)) ) ) mylist ) ) ) (defun replace-html-chars (start end) "Replace “<” by “<” and other similar HTML chars that needs to be encoded." (interactive "r") (replace-string-pairs-region start end '( ("&" "&") ("<" "<") (">" ">") ) ) )
With the above code, you can select a region, then press “Alt+x replace-html-chars”, and have all “&”, “>”, “<” replaced by their encoded entity. You can define a keyboard shortcut for easy operation.
You can also use the code to replace some HTML entities↗ by their actual unicode characters. For example:
“ → “ ” → ” é → é © → © -> → → => → ⇒ Pi → π Infinity → ∞
This makes the HTML source code more elegant and readible. (You need to declare your charset as one of unicode encodings. See Character Sets and Encoding in HTML)
How to preview in a browser?
Press “Ctrl+c Ctrl+v” (browse-url-of-buffer). You can also get a textual preview by pressing “Ctrl+c TAB” (sgml-tags-invisible), which will hide all the tags. Press “Ctrl+c TAB” again to show tags.
In CSS, there a way to have color values colored by themselves?
Put the following elisp code in your “.emacs” file:
(defvar hexcolour-keywords '(("#[abcdef[:digit:]]\\{6\\}" (0 (put-text-property (match-beginning 0) (match-end 0) 'face (list :background (match-string-no-properties 0))))))) (defun hexcolour-add-to-font-lock () (font-lock-add-keywords nil hexcolour-keywords)) (add-hook 'css-mode-hook 'hexcolour-add-to-font-lock)
With the above code, when you open a css file, any text of color spec in hex form will be colored with its value, as the background color. Here's a sample screenshot:
If you want it work in html file too, repeat the “add-hook” line with “'html-mode-hook”.
Is there a way to show a color palette and their RGB values?
Use the menu “Edit‣Text Properties‣Display Colors” or type “Alt+x list-colors-display”. This is useful as a color reference for HTML coding. To show their RGB value in decimal: “Ctrl+h v color-name-rgb-alist”.
How to quickly open the file in a inline image?
Suppose in your HTML file, you have a lot relative links such as:
<img src="img/emacs_logo.png"> <a href="../other/file2.html">
You want to quickly open image to see what they are, or open any file inside a link's relative path, here's how: Place your cursor in the path, then press “Alt+x ffap”. (ffap is a alias to the command find-file-at-point) You can also create a shortcut such as F8 key for this.
I have a bunch of images in a dir. Is there a way to get a overview?
In emacs version 22, use “Alt+x tumme”. (“tumme” means thumb in Swedish. You need ImageMagick installed for tumme to work.). Emacs will create thumbnails on the fly. Here's a screenshot:
How to open the current directory in Desktop?
You can define a function and assign it a keyboard shortcut, so that upon a press of a button, emacs will switch you to your operating systems's file manager (aka Desktop) with the current directory open.
On the Mac OS X, this is done with the “/usr/bin/open” command. So, press “Alt+! open .” to have Finder open the current directory. You can define the function this way:
(defun open-with-finder () "Open the current file in Mac's Finder." (interactive) (shell-command "open .")) (global-set-key (kbd "<f2>") 'open-with-finder)
For a documentation of OS X's “open” command, see “man open”.
On Microsoft Windows, you can use “explorer.exe” instead of the “open” command.
I have a lot commands to insert custom tags. I want to assign them to the F1 to F12, and Alt+1 to Alt+9 keys.
Related essays:
Page created: 2006-07. © 2006 by Xah Lee.