first commit

This commit is contained in:
2026-07-03 09:04:08 +09:00
commit 00a581c2ea
6 changed files with 2247 additions and 0 deletions
+174
View File
@@ -0,0 +1,174 @@
;;; my-org-pukiwiki.el --- Simple Org to PukiWiki exporter -*- lexical-binding: t; -*-
(require 'subr-x)
(defgroup my-org-pukiwiki nil
"Simple Org to PukiWiki exporter."
:group 'tools)
(defcustom my-org-pukiwiki-coding-system 'japanese-shift-jis
"Output coding system."
:type 'coding-system
:group 'my-org-pukiwiki)
(defun my-org-pukiwiki--metadata-p (line)
(string-match-p
"^#\\+\\(TITLE\\|AUTHOR\\|OPTIONS\\|DATE\\|EMAIL\\|LANGUAGE\\|KEYWORDS\\):"
line))
(defun my-org-pukiwiki--heading (line)
(if (string-match "^\\(\\*+\\)[ \t]+\\(.*\\)$" line)
(let* ((level (length (match-string 1 line)))
(title (match-string 2 line)))
(cond
((= level 1) (concat "* " title))
((= level 2) (concat "** " title))
((= level 3) (concat "*** " title))
(t (concat "'''" title "'''"))))
line))
(defun my-org-pukiwiki--list (line)
(cond
((string-match "^[ \t]*-[ \t]+\\(.*\\)$" line)
(concat "-" (match-string 1 line)))
((string-match "^[ \t]*[0-9]+\\.[ \t]+\\(.*\\)$" line)
(concat "+" (match-string 1 line)))
(t line)))
(defun my-org-pukiwiki--table-separator-p (line)
(string-match-p "^[ \t]*|[-+| \t]+|[ \t]*$" line))
(defun my-org-pukiwiki--table (line)
(cond
((my-org-pukiwiki--table-separator-p line)
nil)
((string-match-p "^[ \t]*|" line)
(let ((s (string-trim line)))
(setq s (replace-regexp-in-string "=" "" s))
(if (string-match-p "|[ \t]*キー[ \t]*|\\|[ \t]*関数[ \t]*|\\|[ \t]*機能[ \t]*|" s)
(concat s "h")
s)))
(t line)))
(defun my-org-pukiwiki--inline (line)
(setq line
(replace-regexp-in-string
"=\\([^=\n]+\\)="
"''\\1''"
line))
(setq line
(replace-regexp-in-string
"~\\([^~\n]+\\)~"
"''\\1''"
line))
line)
(defun my-org-pukiwiki--link (line)
;; [[file:foo.png]]
(setq line
(replace-regexp-in-string
"\\[\\[file:\\([^]]+\\)\\]\\]"
"#ref(\\1)"
line))
;; [[https://example.org][label]]
(setq line
(replace-regexp-in-string
"\\[\\[\\([^]]+\\)\\]\\[\\([^]]+\\)\\]\\]"
"[[\\2>\\1]]"
line))
;; [[https://example.org]]
(setq line
(replace-regexp-in-string
"\\[\\[\\(https?://[^]]+\\)\\]\\]"
"[[\\1]]"
line))
line)
(defun my-org-pukiwiki--sjis-safe (text)
(let ((s text))
(setq s (replace-regexp-in-string "\\|—\\|―" "--" s))
(setq s (replace-regexp-in-string "\\|”" "\"" s))
(setq s (replace-regexp-in-string "\\|" "'" s))
(setq s (replace-regexp-in-string "" "..." s))
(setq s (replace-regexp-in-string "" "Busy" s))
(setq s (replace-regexp-in-string "" "->" s))
(setq s (replace-regexp-in-string "" "<-" s))
(setq s (replace-regexp-in-string "" "=>" s))
(setq s (replace-regexp-in-string "├──" "+-" s))
(setq s (replace-regexp-in-string "└──" "+-" s))
(setq s (replace-regexp-in-string "" "|" s))
s))
(defun my-org-pukiwiki-convert-string (text)
"Convert Org TEXT to PukiWiki text."
(let ((lines (split-string text "\n"))
(out nil)
(in-block nil))
(dolist (line lines)
(cond
;; src/example block start
((string-match-p "^#\\+begin_\\(src\\|example\\)" line)
(setq in-block t))
;; src/example block end
((string-match-p "^#\\+end_\\(src\\|example\\)" line)
(setq in-block nil))
;; preformatted block: leading half-width space
(in-block
(push (concat " " line) out))
;; skip Org metadata
((my-org-pukiwiki--metadata-p line)
nil)
;; skip caption/name lines
((string-match-p "^#\\+\\(CAPTION\\|NAME\\):" line)
nil)
;; normal line
(t
(setq line (my-org-pukiwiki--heading line))
(setq line (my-org-pukiwiki--list line))
(setq line (my-org-pukiwiki--table line))
(when line
(setq line (my-org-pukiwiki--inline line))
(setq line (my-org-pukiwiki--link line))
(push line out)))))
(my-org-pukiwiki--sjis-safe
(string-join (nreverse out) "\n"))))
(defun my-org-pukiwiki-export-buffer ()
"Convert current Org buffer and show result in *PukiWiki*."
(interactive)
(let ((text (my-org-pukiwiki-convert-string (buffer-string))))
(with-current-buffer (get-buffer-create "*PukiWiki*")
(erase-buffer)
(insert text)
(goto-char (point-min))
(pop-to-buffer (current-buffer)))))
(defun my-org-pukiwiki-export-file (&optional file)
"Export current Org buffer to a Shift-JIS PukiWiki file."
(interactive)
(let* ((src (buffer-file-name))
(dst (or file
(if src
(concat (file-name-sans-extension src) ".pukiwiki")
"output.pukiwiki")))
(text (my-org-pukiwiki-convert-string (buffer-string)))
(coding-system-for-write my-org-pukiwiki-coding-system))
(with-temp-file dst
(insert text))
(message "Exported PukiWiki: %s" dst)))
(defun my-org-pukiwiki-copy-to-clipboard ()
"Convert current Org buffer to PukiWiki text and copy it to kill-ring."
(interactive)
(let ((text (my-org-pukiwiki-convert-string (buffer-string))))
(kill-new text)
(message "Copied PukiWiki text to clipboard")))
(provide 'my-org-pukiwiki)
;;; my-org-pukiwiki.el ends here