;; -*- 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 "") (backward-char 2) ) (defun backward-html-end-tag () "Move cursor to the previous html tag's content." (interactive) (search-backward "") ;; (forward-char-char 2) ) ;; § ---------------------------------------- (defun compact-css-region (p1 p2) "Remove unnecessary whitespaces of CSS source code in region. CSS is Cascading Style Sheet. WARNING: not robust. Designed for my personal use only." (interactive "r") (let () (save-restriction (narrow-to-region p1 p2) (replace-regexp-pairs-region (point-min) (point-max) '([" +" " "])) (replace-pairs-region (point-min) (point-max) '( ["\n" ""] [" /* " "/*"] [" */ " "*/"] [" {" "{"] ["{ " "{"] ["; " ";"] [": " ":"] [";}" "}"] ["}" "}\n"] )) ) ) ) ;; § ---------------------------------------- (defun insert-tag () "Insert a HTML tag based on the current line. If current line is empty, then insert “
”. 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" tagname ">"))) ) (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 "" (if (or (equal tagName nil) (string= tagName "")) "span" tagName) ">" ) ) (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+"] ["