;; -*- coding: utf-8 -*- ;; some custome string functions for working with HTML ;; 2007-06 ;; Xah Lee ;; ∑ http://xahlee.org/ (defun forward-html-end-tag () "Move cursor to the next html tag's content." (interactive) (forward-char 1) (search-forward "

”. If current line is a single word, use that word as tag name. If current line has 2 words, use first word as tag name, second word as value for attribute “class”. For example, pre poem will become
."
  (interactive)
  (let (bds p1 p2 myline goodies tagname classVal insStr)

    (setq bds (get-selection-or-unit 'line))
    (setq myline (elt bds 0) )
    (setq p1 (elt bds 1) )
    (setq p2 (elt bds 2) )

    (setq goodies (split-string myline " +" t))

    (cond
     ((equal (length goodies) 1) (progn (setq tagname "div") (setq classVal (nth 0 goodies))))
     ((equal (length goodies) 2) (progn (setq tagname (nth 0 goodies)) (setq classVal (nth 1 goodies)))))
    (delete-region p1 p2)

    (cond
     ((equal (length goodies) 0) (insert "

\n

") ) ((and t) (insert (concat "<" tagname " class=\"" classVal "\">\n"))) ) (search-backward "<") (backward-char 1) )) ;; § ---------------------------------------- (defun insert-div-x-note () "Insert a HTML markup." (interactive) (insert "
\n") (backward-char 7) ) (defun xah-annotate () "Create a annotation in HTML. Wrap HTML “span” tag around current word or text selection, then insert a div tag above the current paragraph." (interactive) (let (bds inputText) (setq bds (get-selection-or-unit 'word)) (setq inputText (elt bds 0) ) (wrap-html-tag "span" "xnt") (search-backward "” and “” ;; around current word or text selection." ;; (interactive "sClass code: ") ;; (let (bds p1 p2) ;; (setq bds (get-selection-or-unit 'word)) ;; (setq p1 (elt bds 1) ) ;; (setq p2 (elt bds 2) ) ;; (goto-char p2) ;; (insert "") ;; (goto-char p1) ;; (insert (concat "")) ;; ) ;; ) (defun wrap-html-tag (tagName &optional className ξid) "Add a HTML tag to beginning and ending of current word or text selection. If tagName is empty or nil, use “span”. If className is empty or nil, don't add any class attribute. If ξid is empty or nil, don't add id attribute." (interactive "sEnter tag name: sEnter class:") (let (bds p1 p2 inputText outputText) (setq bds (get-selection-or-unit 'word)) (setq inputText (elt bds 0) ) (setq p1 (elt bds 1) ) (setq p2 (elt bds 2) ) (setq outputText (concat "<" (if (or (equal tagName nil) (string= tagName "")) "span" tagName) (if (or (equal ξid nil) (string= ξid "")) "" (concat " id=\"" ξid "\"")) (if (or (equal className nil) (string-equal className "")) "" (concat " class=\"" className "\"")) ">" inputText "" ) ) (delete-region p1 p2) (goto-char p1) (insert outputText) ) ) (defun mark-unicode (p1) "Wrap 「」 around current character. When called in elisp program, wrap the tag at point P1." (interactive (list (point))) (goto-char p1) (insert "") (forward-char 1) (insert "")) ;; § ---------------------------------------- (defun add-paragraph-tag () "Add

tag to current paragraph or text selection." (interactive) (let (bds p1 p2 inputText) (setq bds (get-selection-or-unit 'block)) (setq inputText (elt bds 0) ) (setq p1 (elt bds 1) ) (setq p2 (elt bds 2) ) (delete-region p1 p2 ) (insert "

" (replace-regexp-in-string "\n\n+" "

\n\n

" (trim-string inputText)) "

") ) ) (defun make-citation () "Reformat current text block or selection into a canonical citation format. For example, place cursor somewhere in the following block: Circus Maximalist By PAUL GRAY Monday, Sep. 12, 1994 http://www.time.com/time/magazine/article/0,9171,981408,00.html After execution, the lines will become Circus Maximalist (1994-09-12) By Paul Gray. @ Source www.time.com If there's a text selection, use it for input, otherwise the input is a text block between empty lines." (interactive) (let (bds p1 p2 inputText myList ξtitle ξauthor ξdate ξurl ) (setq bds (get-selection-or-unit 'block)) (setq inputText (elt bds 0) ) (setq p1 (elt bds 1) ) (setq p2 (elt bds 2) ) (setq inputText (replace-regexp-in-string "^[[:space:]]*" "" inputText)) ; remove white space in front (setq myList (split-string inputText "[[:space:]]*\n[[:space:]]*" t) ) (setq ξtitle (trim-string (elt myList 0))) (setq ξauthor (trim-string (elt myList 1))) (setq ξdate (trim-string (elt myList 2))) (setq ξurl (trim-string (elt myList 3))) (setq ξauthor (replace-regexp-in-string "\\. " " " ξauthor)) ; remove period in Initals (setq ξauthor (replace-regexp-in-string "By +" "" ξauthor)) (setq ξauthor (upcase-initials (downcase ξauthor))) (setq ξdate (fix-timestamp ξdate)) (setq ξurl (with-temp-buffer (insert ξurl) (source-linkify) (buffer-string))) (delete-region p1 p2 ) (insert (concat "" ξtitle "") " " "" " By " ξauthor ". @ " ξurl) )) (defun htmlize-keyboard-shortcut-notation () "Wrap a “kbd” tag around keyboard keys on current text inside 【】, or text selection. e.g. 【ctrl+w】 becomes 【Ctrl+w】 Same for Alt, Shift, Cmd, Win, Enter, Return, Home… and other strings." (interactive) (let (p1 p2 inputStr resultStr replaceList) (if (region-active-p) (progn (setq p1 (region-beginning)) (setq p2 (region-end)) ) (save-excursion (progn (if (search-backward "【" nil t) (progn (forward-char) (setq p1 (point) ) ) (setq p1 (line-beginning-position) ) ) (if (search-forward "】" nil t) (progn (backward-char) (setq p2 (point) )) (setq p2 (line-end-position) ) ) )) ) (setq inputStr (buffer-substring-no-properties p1 p2)) (setq replaceList [ ["Ctrl" "Ctrl"] ["Alt" "Alt"] ["Shift" "Shift"] ["Cmd" "⌘ Cmd"] ["Option" "⌥ Opt"] ["Opt" "⌥ Opt"] ["Win" "Win"] ["App" "App"] ["Meta" "Meta"] ["Return" "Return"] ["Enter" "Enter"] ["Backspace" "⌫ Backspace"] ["Del" "⌦ Delete"] ["Space" "Space"] ["Caps Lock" "Caps Lock"] ["Tab" "Tab"] ["Esc" "Esc"] ["F10" "F10"] ["F11" "F11"] ["F12" "F12"] ["F1" "F1"] ["F2" "F2"] ["F3" "F3"] ["F4" "F4"] ["F5" "F5"] ["F6" "F6"] ["F7" "F7"] ["F8" "F8"] ["F9" "F9"] ["Fn" "Fn"] ["←" ""] ["→" ""] ["↑" ""] ["↓" ""] ["Home" "Home"] ["End" "End"] ["PageUp" "PageUp"] ["PageDown" "PageDown"] ["delete" "Delete"] ["del" "Delete"] ["pgdn" "PageDown"] ["pgup" "PageUp"] ["‹key›" "‹key›"] ]) (let ((case-fold-search t) (case-replace nil) ) (setq resultStr (replace-pairs-in-string inputStr replaceList)) ) (setq resultStr (replace-regexp-pairs-in-string resultStr [ ["\+\\([^<]\\) \\(.\\) \\(.\\)\\'" "+\\1 \\2 \\3"] ["\+\\([^<]\\) \\([A-Za-z]\\)\\'" "+\\1 \\2"] ["\+\\([^<]\\)" "+\\1"] ])) (delete-region p1 p2) (insert resultStr) ) ;; test cases ;; 【Ctrl+x a】 ;; 【Ctrl+x a b】 ;; 【Ctrl+x Ctrl+j】 ) (defun emacs-to-windows-kbd-notation (p1 p2) "Change emacs keyboard-shortcut notation to Windows's notation. When called interactively, work on text enclosed in 【…】, or text selection. For example: 「【C-h f】」⇒ 「【Ctrl+h f】」 「【M-a】」⇒ 「【Meta+a】」 This command is just for convenient, not 100% correct translation. Partly because the Windows key notation isn't exactly standardized. e.g. up arrow key may be ↑ or UpArrow. " (interactive (let ((bds (get-selection-or-unit ["^【" "^】"])) ) (list (elt bds 1) (elt bds 2)) ) ) (let ( (case-fold-search nil)) (replace-pairs-region p1 p2 '( ["C-" "Ctrl+"] ["M-" "Meta+"] ["S-" "Shift+"] ["s-" "Super+"] ["H-" "Hyper+"] ["" "PageUp"] ["" "PageDown"] ["" "Home"] ["" "End"] ["RET" "Enter"] ["" "Enter"] ["TAB" "Tab"] ["" "Tab"] ["" "→"] ["" "←"] ["" "↑"] ["" "↓"] ["" "Insert"] ["" "Delete"] ["" "Backspace"] ["DEL" "Delete"] )) ) ) (defun xah-update-page-tag-old (p1 p2) "Update html page navigation tags. The input is a text selection. Each line should a file name Update each file's page navigation tag. Each file name is a file path without dir, and relative to current dir. Sample text selection for input: “combowords.html combowords-2.html combowords-3.html combowords-4.html”" (interactive "r") (let (filez pageNavStr (i 1)) (setq filez (split-string (buffer-substring-no-properties p1 p2) "\n" t) ) (delete-region p1 p2) ;; generate the page nav string (setq pageNavStr "
") (while (<= i (length filez)) (setq pageNavStr (concat pageNavStr "" (number-to-string i) ", ") ) (setq i (1+ i)) ) (setq pageNavStr (substring pageNavStr 0 -2) ) ; remove the last ", " (setq pageNavStr (concat pageNavStr "
")) ;; open each file, insert the page nav string, remove link in the ;; nav string that's the current page (mapc (lambda (thisFile) (message "%s" thisFile) (find-file thisFile) (goto-char (point-min)) (search-forward "
") (beginning-of-line) (kill-line 1) (insert pageNavStr "\n") (search-backward (file-name-nondirectory buffer-file-name)) (require 'sgml-mode) (sgml-delete-tag 1) ;; (save-buffer) ;; (kill-buffer) ) filez) )) (defun xah-update-page-tag () "Update html page navigation tags. The input is a block or text selection. Each line should a file name Update each file's page navigation tag. Each file name is a file path without dir, and relative to current dir. Sample text selection for input: combowords.html combowords-2.html combowords-3.html combowords-4.html " (interactive) (require 'sgml-mode) (let (bds p1 p2 inputStr fileList pageNavStr ) (setq bds (get-selection-or-unit 'block)) (setq inputStr (elt bds 0) p1 (elt bds 1) p2 (elt bds 2) ) (setq fileList (split-string (buffer-substring-no-properties p1 p2) "\n" t) ) (delete-region p1 p2) ;; generate the page nav string (setq pageNavStr "
\n") (let (linkPath fTitle (ξi 0) ) (while (< ξi (length fileList)) (setq linkPath (elt fileList ξi) ) (setq fTitle (get-html-file-title linkPath) ) (setq pageNavStr (concat pageNavStr "" (number-to-string (1+ ξi)) "\n") ) (setq ξi (1+ ξi)) ) ) (setq pageNavStr (concat pageNavStr "
")) ;; open each file, insert the page nav string (mapc (lambda (thisFile) (message "%s" thisFile) (find-file thisFile) (goto-char (point-min)) (if (search-forward "
" nil t) (let (p3 p4 ) (backward-char 18) (setq p3 (point)) (sgml-skip-tag-forward 1) (setq p4 (point)) (delete-region p3 p4) (insert pageNavStr) ) (progn (search-forward "