Elisp Text Processing vs Structured
Major rewrite of a command, using completely different approaches. Left: text processing. Right: turn the text into nested list. In this case, the nested list is shorter, more readible, and actually more features.
Here's the comparison code. i think the text processing version is faster and uses less memory. but the split string version is clearer, shorter.
(defun my-lines-to-list1 () "Make the current lines or text blocks into a HTML list. If there is no selection, make each line into a list item. If there is selection, each text block becomes a list item. (text block is separated by blank lines.) If `universal-argument' is called first, use ordered list ol instead of ul. 2021-09-04" (interactive) (let* ((xbds (xah-get-bounds-of-thing-or-region 'block)) (xp1 (car xbds)) (xp2 (cdr xbds))) (save-restriction (narrow-to-region xp1 xp2) (progn (goto-char (point-min)) (insert "<li>") (if mark-active (while (re-search-forward " *\n\n+ *" nil 1) (replace-match "</li>\n\n<li>" t t)) (while (re-search-forward " *\n *" nil 1) (replace-match "</li>\n<li>" t t))) (insert "</li>\n")) (if current-prefix-arg (progn (goto-char (point-min)) (insert "<ol>\n") (goto-char (point-max)) (insert "</ol>")) (progn (goto-char (point-min)) (insert "<ul>\n") (goto-char (point-max)) (insert "</ul>"))) (goto-char (point-min)) (while (search-forward "<li></li>" nil 1) (replace-match "" t t)) (goto-char (point-min)) (while (search-forward "<li>\n" nil 1) (replace-match "<li>" t t)) (goto-char (point-min)) (while (re-search-forward "\n\n+" nil 1) (replace-match "\n\n" t t)) (insert "\n\n"))))
(defun my-lines-to-list2 () "Make the current block or selection into a HTML list. If there is no selection, make each line into a list item. If there is selection, each text block becomes a list item. (text block is separated by blank lines.) If `universal-argument' is called first, use ordered list ol instead of ul. 2021-09-04" (interactive) (let* ((xsep (if mark-active "\n\n+" "\n")) (xbds (xah-get-bounds-of-thing-or-region 'block)) (xp1 (car xbds)) (xp2 (cdr xbds)) (xinput (buffer-substring-no-properties xp1 xp2)) (xitems (split-string xinput xsep t " +")) (xsList (mapcar (lambda (x) (format "<li>%s</li>" x)) xitems)) (xlistStr (mapconcat 'identity xsList "\n"))) (save-restriction (narrow-to-region xp1 xp2) (delete-region (point-min) (point-max)) (insert (if current-prefix-arg (concat "<ol>\n" xlistStr "\n</ol>") (concat "<ul>\n" xlistStr "\n</ul>"))))))