--- pukiwiki-mode.el.download-041005 2004-10-05 16:30:14.000000000 +0900 +++ pukiwiki-mode.el 2004-10-06 10:47:41.000000000 +0900 @@ -126,12 +126,41 @@ (defvar pukiwiki-bracket-name-regexp '("\\[\\[\\([^]:|]+\\)\\]\\]" . 1)) (defvar pukiwiki-rd+-bracket-name-regexp '("((<\\([^>:|]+\\)>))" . 1)) +;; regexp for anchor of alias. +(defvar pukiwiki-bracket-alias-regexp + '("\\[\\[\\([^]:|]+>+[^]:|]+\\)\\]\\]" . 1)) + +;; InterWikiName +;; regexp for anchor of InterWikiName and Alias. +(defvar pukiwiki-bracket-interwikiname-regexp + '("\\[\\[\\([^]:|]+>*[^]:|]+:+[^]:|]+\\)\\]\\]" . 1)) + +;; regexp for anchor of href. +(defvar pukiwiki-view-bracket-url-regexp + ;; '("\\[+\\(https*:[^]]+\\s-+[^]:|]+\\)\\]+" . 1)) + '("\\[+\\(\\(ht\\|f\\)tps*:[^]]+\\s-+[^]:|]+\\)\\]+" . 1)) +(defvar pukiwiki-view-bracket-url-secondhalf-regexp + ;; '("\\[+\\([^]]+:https*:[^]]+[^]:|]+\\)\\]+" . 1)) + '("\\[+\\([^]]+[>:]\\(ht\\|f\\)tps*:[^]]+[^]:|]+\\)\\]+" . 1)) + +;; regexp for anchor of href 2. +(defvar pukiwiki-view-no-bracket-url-regexp + '("\\(h*ttps*:[-+_a-zA-Z0-9/.,~#?&%=]+\\)" . 1)) + (defvar pukiwiki-style-anchor-regexp-alist (list (cons 'default (cons pukiwiki-bracket-name-regexp pukiwiki-wikiname-regexp-list)) - (cons 'rd+ (list pukiwiki-rd+-bracket-name-regexp))) + (cons 'rd+ (list pukiwiki-rd+-bracket-name-regexp)) + (cons 'delete-url-description + (list pukiwiki-view-bracket-url-regexp + pukiwiki-bracket-interwikiname-regexp + pukiwiki-bracket-alias-regexp + pukiwiki-view-bracket-url-secondhalf-regexp)) + (cons 'leave-url-description + (list pukiwiki-bracket-name-regexp + pukiwiki-view-no-bracket-url-regexp))) "Alist of regexp for anchor.") (defvar pukiwiki-anchor-regexp-alist @@ -141,6 +170,105 @@ (copy-face 'underline 'pukiwiki-anchor-face) "Face for Pukiwiki anchor." ) +(defcustom pukiwiki-no-proxy-domains-list '("localhost") + "*Domain list that don't via proxy server." + :group 'pukiwiki + :type '(repeat (string :format "Domain name: %v +" :size 0))) + +(defcustom pukiwiki-process-sentinel-interval 1 + "*Sentinel time for end of process." + :group 'pukiwiki + :type '(integer :size 0)) + +(defcustom pukiwiki-jump-display-window-top nil + "*Non-nil means displaying the pointer which moved at the top of a window." + :group 'pukiwiki + :type 'boolean) + +(defcustom pukiwiki-jump-display-window-top-without-content nil + "*Non-nil means excepting, if it is content +when displaying the pointer which moved at the top of a window." + :group 'pukiwiki + :type 'boolean) + +(defcustom pukiwiki-jump-display-window-top-skip-visible-url nil + "*Non-nil means ignore, if it is visible url description +when displaying the pointer which moved at the top of a window." + :group 'pukiwiki + :type 'boolean) + +(defcustom pukiwiki-jump-display-window-upper-margin 0 + "*The margin of the window upper part when displaying the pointer +which moved at the top of a window." + :group 'pukiwiki + :type '(integer :size 0)) + +(defcustom pukiwiki-jump-display-window-top-only-header nil + "*Non-nil means if it is header +when displaying the pointer which moved at the top of a window." + :group 'pukiwiki + :type 'boolean) + +(defcustom pukiwiki-diff-using-ediff nil + "*Non-nil means using `Ediff' package for diff process." + :group 'pukiwiki + :type 'boolean) + +(defcustom pukiwiki-view-comment-form-name-field-width 20 + "*Width of the NAME input field." + :group 'pukiwiki + :type '(integer :size 0)) + +(defcustom pukiwiki-view-comment-form-comment-field-width 60 + "*Width of the COMMENT input field." + :group 'pukiwiki + :type '(integer :size 0)) + +(defcustom pukiwiki-view-comment-form-subject-field-width 40 + "*Width of the COMMENT input field." + :group 'pukiwiki + :type '(integer :size 0)) + +(defcustom pukiwiki-view-comment-form-message-field-width 64 + "*Width of the COMMENT input field." + :group 'pukiwiki + :type '(integer :size 0)) + +(defcustom pukiwiki-view-comment-form-name-default nil + "*Default value of the NAME input field." + :group 'pukiwiki + :type '(radio (const :tag "Not specified" nil) + (string :format "Default post name: %v\n" :size 0))) + +(defcustom pukiwiki-interwiki-browse-not-match-pukiwiki nil + "*Non-nil means browse extent browser by browse-url, +url is not match PukiWiki site." + :group 'pukiwiki + :type 'boolean) + +(defcustom pukiwiki-view-jump-page-history-keep-count 100 + "*Maximum number of history which the HISTORY LIST keeps." + :group 'pukiwiki + :type '(integer :size 0)) + +(defcustom pukiwiki-view-form-textarea-buffer-history-keep-count 50 + "*Maximum number of history which the HISTORY LIST keeps." + :group 'pukiwiki + :type '(integer :size 0)) + +(defcustom pukiwiki-view-chip-away-bracket t + "*Non-nil means chip away bracket from anchor." + :group 'pukiwiki + :type 'boolean) + +(defcustom pukiwiki-view-comment-date-regexp + '("[0-9]+-[0-9]+-[0-9]+" "[0-9]+年[0-9]+月[0-9]+日") + "*Date pattern list of comment." + :group 'pukiwiki + :type '(repeat (string :format "regexp: %v +" :size 0))) + (defvar pukiwiki-keywords '("add" "aname" "article" "attach" "back" "backup" "bugtrack" "bugtrack_list" @@ -159,26 +287,32 @@ "touchgraph" "tracker" "unfreeze" "version" "versionlist" "vote" "yetlist")) +(setq pukiwiki-view-list-face 'pukiwiki-view-list-1-face) (defvar pukiwiki-font-lock-keywords (list - '("^[ ]*_ \\([0-9]+-[0-9]+-[0-9]+[ ]*([^)]+)[ ]*[0-9]+:[0-9]+:[0-9]+ \\[[^\r\n]+$\\)" 1 font-lock-comment-face) + (cons + (concat "^[ ]*\\(_\\|\\[[0-9* ]+\\]\\) \\(\\(" + (mapconcat 'identity pukiwiki-view-comment-date-regexp "\\|") + "\\)[ ]*([^)]+)[ ]*[0-9]+:[0-9]+:[0-9]+ *\\[*[^\r\n]+$\\)") + '((1 pukiwiki-view-button-face t t) + (2 pukiwiki-view-comment-header-face t t))) + '("\\(^//[^\n\r]+$\\)" 1 font-lock-comment-face) '("\\(^[>]+[^\n\r]+$\\)" 1 font-lock-reference-face) - ;; '("^\\([ ]*-+[^\n\r]+$\\)" 1 font-lock-keyword-face) (cons (concat "^#\\(" (mapconcat 'identity pukiwiki-keywords "\\|") "\\)") (list 0 'font-lock-keyword-face)) + ;***** (list 0 'font-lock-reference-face)) (cons (concat "^#\\(" (mapconcat 'identity pukiwiki-keywords "\\|") "\\)" "(\\([^\n\r]+\\))") (list 2 'font-lock-doc-face)) - '("\\(^[*]+[^\n\r]+\\)" 1 font-lock-function-name-face) - '("\\(^ [^\n\r]+$\\)" 1 font-lock-constant-face) - )) + '("\\(^[*]+[^\n\r]+\\)" 1 pukiwiki-view-header-face) + '("\\(^ [^\n\r]+$\\)" 1 pukiwiki-view-preformat-face-1))) (defface pukiwiki-added-face '((((class color) @@ -202,6 +336,140 @@ (defvar pukiwiki-added-face 'pukiwiki-added-face) (defvar pukiwiki-removed-face 'pukiwiki-removed-face) +;; view mode の face 定義。 +(defgroup pukiwiki-face nil + "The faces used for pukiwiki-mode." + :group 'pukiwiki + :prefix "pukiwiki-") + +(defface pukiwiki-view-header-face + '((((class color) (background light)) + (:foreground "BlueViolet" :background "Lavenderblush")) + (((class color) (background dark)) (:foreground "darkviolet"))) + "見出し行の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-comment-header-face + '((((class color) (background light)) (:foreground "seagreen")) + (((class color) (background dark)) (:foreground "seagreen"))) + "コメント見出し (日付、時刻と投稿者が表示される部分) の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-cite-face + '((((class color) (background light)) (:foreground "olivedrab")) + (((class color) (background dark)) (:foreground "forestgreen"))) + "引用部分の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-preformat-face + '((((class color) (background light)) (:foreground "slateblue")) + (((class color) (background dark)) (:foreground "darkslateblue"))) + "整形済みテキストの face (行頭の空白 7バイト以上)" + :group 'pukiwiki-face) + +(defface pukiwiki-view-preformat-face-1 + '((((class color) (background light)) (:foreground "slateblue")) + (((class color) (background dark)) (:foreground "darkslateblue"))) + "整形済みテキストの face (行頭の空白 1バイト)" + :group 'pukiwiki-face) + +(defface pukiwiki-view-preformat-face-2 + '((((class color) (background light)) (:foreground "mediumpurple")) + (((class color) (background dark)) (:foreground "blueviolet"))) + "整形済みテキストの face (行頭の空白 2バイト)" + :group 'pukiwiki-face) + +(defface pukiwiki-view-preformat-face-3 + '((((class color) (background light)) (:foreground "mediumseagreen")) + (((class color) (background dark)) (:foreground "seagreen"))) + "整形済みテキストの face (行頭の空白 3バイト)" + :group 'pukiwiki-face) + +(defface pukiwiki-view-preformat-face-4 + '((((class color) (background light)) (:foreground "deeppink")) + (((class color) (background dark)) (:foreground "hotpink"))) + "整形済みテキストの face (行頭の空白 4バイト)" + :group 'pukiwiki-face) + +(defface pukiwiki-view-preformat-face-5 + '((((class color) (background light)) (:foreground "lightcoral")) + (((class color) (background dark)) (:foreground "coral"))) + "整形済みテキストの face (行頭の空白 5バイト)" + :group 'pukiwiki-face) + +(defface pukiwiki-view-preformat-face-6 + '((((class color) (background light)) (:foreground "royalblue")) + (((class color) (background dark)) (:foreground "dodgerblue"))) + "整形済みテキストの face (行頭の空白 6バイト)" + :group 'pukiwiki-face) + +(defface pukiwiki-view-strikethru-face + '((((class color) (background light)) (:strikethru t)) + (((class color) (background dark)) (:strikethru t))) + "打ち消し線の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-list-1-face + '((((class color) (background light)) (:foreground "darkmagenta")) + (((class color) (background dark)) (:foreground "darkred"))) + "リスト項目の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-button-face + '((((class color) (background light)) (:foreground "darkgoldenrod")) + (((class color) (background dark)) (:foreground "goldenrod"))) + "anchor button の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-current-button-face + '((((class color) (background light)) (:background "Paleturquoise")) + (((class color) (background dark)) (:background "lightblue"))) + "ポイントが乗ったときの anchor button の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-url-face + '((((class color) (background light)) (:foreground "Blue")) + (((class color) (background dark)) (:foreground "mediumblue"))) + "anchor url の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-anchor-face + '((((class color) (background light)) (:underline t)) + (((class color) (background dark)) (:underline t))) + "wiki anchor の face" + :group 'pukiwiki-face) + +(defface pukiwiki-view-current-url-face + '((((class color) (background light)) (:background "Paleturquoise")) + (((class color) (background dark)) (:background "lightblue"))) + "ポイントが乗ったときの anchor url の face" + :group 'pukiwiki-face) + +(defface pukiwiki-index-current-line-face + '((((class color) (background light)) (:background "Yellow")) + (((class color) (background dark)) (:foreground "Gold"))) + "インデックス上のポイントが乗った行の face" + :group 'pukiwiki-face) + +;; index mode. +(defface pukiwiki-index-normal-face + '((((class color) (background light)) (:foreground "green4")) + (((class color) (background dark)) (:foreground "yellow"))) + "インデックスの通常行の face" + :group 'pukiwiki-face) + +(defface pukiwiki-index-cache-face + '((((class color) (background light)) (:foreground "BlueViolet")) + (((class color) (background dark)) (:foreground "green3"))) + "インデックスのキャッシュ済み行の face" + :group 'pukiwiki-face) + +(setq pukiwiki-index-font-lock-keywords + (list + '("^\\s-*\\([0-9]+\\s-+V\\s-+.+[0-9/]+$\\)" 1 pukiwiki-index-cache-face) + '("^\\s-*\\([0-9]+\\s-+.+\\s-+[0-9/]+$\\)" 1 pukiwiki-index-normal-face) + )) + (defvar pukiwiki-diff-font-lock-keywords (list '("\\(^+[^\n\r]*$\\)" 1 pukiwiki-added-face) @@ -237,39 +505,6 @@ (defvar pukiwiki-search-word nil) -(defcustom pukiwiki-no-proxy-domains-list '("localhost") - "*Domain list that don't via proxy server." - :group 'pukiwiki - :type '(repeat (string :format "Domain name: %v -" :size 0))) - -(defcustom pukiwiki-process-sentinel-interval 1 - "*Sentinel time for end of process." - :group 'pukiwiki - :type '(integer :size 0)) - -(defcustom pukiwiki-jump-display-window-top nil - "*Non-nil means displaying the pointer which moved at the top of a window." - :group 'pukiwiki - :type 'boolean) - -(defcustom pukiwiki-jump-display-window-top-without-content nil - "*Non-nil means excepting, if it is content -when displaying the pointer which moved at the top of a window." - :group 'pukiwiki - :type 'boolean) - -(defcustom pukiwiki-jump-display-window-upper-margin 0 - "*The margin of the window upper part when displaying the pointer -which moved at the top of a window." - :group 'pukiwiki - :type '(integer :size 0)) - -(defcustom pukiwiki-diff-using-ediff nil - "*Non-nil means using `Ediff' package for diff process." - :group 'pukiwiki - :type 'boolean) - ;;; 汎用関数 (defun pukiwiki-mode-version () @@ -460,7 +695,8 @@ (save-excursion (beginning-of-line) (setq pos (point)) - (while (and (setq result (pukiwiki-search-anchor pos)) + (while (and (setq result (pukiwiki-search-anchor + pos pukiwiki-anchor-regexp-alist)) (<= (cdr result) point)) (setq pos (cdr result))) (when (and result (<= (car result) point)) @@ -473,15 +709,16 @@ PREV が non-nil ならば、前のアンカーへ移動する。" (interactive "P") - (goto-char (or (car (pukiwiki-search-anchor (point) prev)) + (goto-char (or (car (pukiwiki-search-anchor + (point) pukiwiki-anchor-regexp-alist prev)) (point)))) -(defun pukiwiki-search-anchor (point &optional prev) +(defun pukiwiki-search-anchor (point list &optional prev) "POINT から最も近いアンカーを探す。 見つかったら (beginning . end) を、見つからなかったら nil を 返す" (let ((case-fold-search nil) - (alist pukiwiki-anchor-regexp-alist) + (alist list) result) (save-excursion (while alist @@ -804,30 +1041,91 @@ nil nil ((?_ . "w")) nil (font-lock-comment-start-regexp . "//"))) (pukiwiki-mode-set-font-lock 'pukiwiki-view-mode) + ;; hooks + (progn + (make-local-hook 'post-command-hook) + (add-hook 'post-command-hook 'pukiwiki-view-post-command-function nil t) + (make-local-hook 'pukiwiki-view-post-command-hook) + (add-hook 'pukiwiki-view-post-command-hook + (function + (lambda () + (pukiwiki-view-echo-url-at-point) + (pukiwiki-view-highlight-current-anchor))) + nil t)) (run-hooks 'pukiwiki-view-mode-hook)) +(add-hook 'pukiwiki-view-mode-hook + (function + (lambda () + (turn-off-font-lock) (turn-on-font-lock) + (setq fill-column (- (window-width) 4)) ; window width に合わせる。 + ))) + +(defun pukiwiki-view-post-command-function () + (run-hooks 'pukiwiki-view-post-command-hook)) + +(defun pukiwiki-view-echo-url-at-point () + (progn + (when (setq prop (get-text-property (point) 'url)) + (princ prop)))) + +(defun pukiwiki-view-highlight-current-anchor () + (progn + (pukiwiki-view-highlight-off-current-anchor) + (pukiwiki-view-highlight-on-current-anchor))) + +(defun pukiwiki-view-highlight-on-current-anchor () + (let ((pos (point)) + (type (get-text-property (point) 'anchortype)) + star end orig) + (when (and (get-text-property (point) 'anchor) + (or (eq 'url type) (eq 'pagename type))) + (save-excursion + ;; highlighit する region を特定する。 + (setq end (next-single-property-change (point) type)) + (setq start (previous-single-property-change end type)) + (unless start (setq start (point-min))) + + ;; overlay set. + (setq ovr-temp (make-overlay start end)) + (overlay-put ovr-temp 'face 'pukiwiki-view-current-url-face) + (overlay-put ovr-temp 'pukiwiki-temp-overlay t) + (overlay-put ovr-temp 'priority 1))))) + +(defun pukiwiki-view-highlight-off-current-anchor () + (let ((overlays (overlays-in (point-min) (point-max)))) + (while + (setq ovr (prog1 (car overlays) (setq overlays (cdr overlays)))) + (when (overlay-get ovr 'pukiwiki-temp-overlay) + (delete-overlay ovr))))) + (defun pukiwiki-view-setup-keys () "Set up keymap for pukiwiki-edit-mode. If you want to set up your own key bindings, use `pukiwiki-edit-mode-hook'." (local-set-key "q" 'pukiwiki-diff-exit) (local-set-key "b" 'scroll-down) (local-set-key " " 'scroll-up) + (local-set-key "B" 'pukiwiki-view-backward-page) + (local-set-key "g" 'pukiwiki-view-goto-page) (local-set-key "c" 'pukiwiki-view-return-contents) (local-set-key "e" 'pukiwiki-view-edit-current-page) (local-set-key "\C-m" 'pukiwiki-view-return-function) (local-set-key "\C-i" 'pukiwiki-jump-anchor) (local-set-key "\M-\C-i" 'pukiwiki-jump-anchor-prev) (local-set-key "\C-xv=" 'pukiwiki-index-show-diff) + (local-set-key "n" 'pukiwiki-jump-anchor-window-top) + (local-set-key "p" 'pukiwiki-jump-anchor-window-top-prev) + (local-set-key "s" 'pukiwiki-view-local-style-set) ) (defun pukiwiki-view-edit-current-page () "現在行のページを編集する。" (interactive) - (if (and - pukiwiki-pagename - pukiwiki-site-info) - (pukiwiki-edit-page pukiwiki-pagename pukiwiki-site-info))) - + (when (and + pukiwiki-pagename + pukiwiki-site-info) + (let ((buf (pukiwiki-edit-page pukiwiki-pagename pukiwiki-site-info))) + (when buf (switch-to-buffer buf))))) ;;; 一覧モード(pukiwiki-index-*) (make-variable-buffer-local 'pukiwiki-site-info) @@ -840,11 +1138,65 @@ \\{pukiwiki-index-mode-map}" (make-local-variable 'pukiwiki-site-info) (make-local-variable 'pukiwiki-index-page-info-list) + ;; InterWikiName + (make-local-variable 'pukiwiki-index-interwiki-info-list) + (make-local-variable 'pukiwiki-index-attach-list) (make-local-variable 'pukiwiki-index-sort-key) (pukiwiki-index-setup-keys) + ;; hooks + (progn + (make-local-hook 'post-command-hook) + (add-hook 'post-command-hook 'pukiwiki-index-post-command-function nil t) + (make-local-hook 'pukiwiki-index-post-command-hook) + (add-hook 'pukiwiki-index-post-command-hook + (function + (lambda () + (pukiwiki-index-highlight-current-line))) + nil t)) (run-hooks 'pukiwiki-index-mode-hook)) +(add-hook 'pukiwiki-index-mode-hook + (function + (lambda () + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults + '(pukiwiki-index-font-lock-keywords + nil nil ((?_ . "w")) nil)) + (pukiwiki-mode-set-font-lock 'pukiwiki-index-mode) + (turn-off-font-lock) (turn-on-font-lock)))) + +(defun pukiwiki-index-post-command-function () + (run-hooks 'pukiwiki-index-post-command-hook)) + +(defun pukiwiki-index-highlight-current-line () + (progn + (pukiwiki-index-highlight-on-current-line))) + +(defun pukiwiki-index-highlight-on-current-line () + (let ((pos (point)) + star end) + (unless (get-text-property (point) 'pukiwiki-current-line) + (save-excursion + ;; これまでの overlays を一掃する。 + (pukiwiki-index-highlight-off-current-line) + ;; highlighi する region を特定する。 + (setq start (line-beginning-position)) + (setq end (1+ (line-end-position))) + + ;; overlay set. + (setq ovr-temp (make-overlay start end)) + (overlay-put ovr-temp 'face 'pukiwiki-index-current-line-face) + (overlay-put ovr-temp 'pukiwiki-current-line t) + (overlay-put ovr-temp 'priority 1))))) + +(defun pukiwiki-index-highlight-off-current-line () + (let ((overlays (overlays-in (point-min) (point-max)))) + (while + (setq ovr (prog1 (car overlays) (setq overlays (cdr overlays)))) + (when (overlay-get ovr 'pukiwiki-current-line) + (delete-overlay ovr))))) + (defun pukiwiki-index-setup-keys () "Set up keymap for pukiwiki-index-mode. If you want to set up your own key bindings, use `pukiwiki-index-mode-hook'." @@ -859,6 +1211,7 @@ (define-key pukiwiki-index-mode-map "R" 'pukiwiki-index-refetch-index) (define-key pukiwiki-index-mode-map "q" 'pukiwiki-index-suspend) (define-key pukiwiki-index-mode-map "Q" 'pukiwiki-index-quit) + (define-key pukiwiki-index-mode-map "B" 'pukiwiki-index-view-backward-page) (define-key pukiwiki-index-mode-map "n" 'pukiwiki-index-next-page) (define-key pukiwiki-index-mode-map "p" 'pukiwiki-index-prev-page) ;;(define-key pukiwiki-index-mode-map "j" 'pukiwiki-index-jump-chapter) @@ -885,7 +1238,7 @@ (when (null site-info) (setq site-info (pukiwiki-read-site-name))) (setq buf (pukiwiki-display-index site-info refetch pagename)) - (switch-to-buffer buf) + (set-buffer buf) ; 画面がチラ付くので変更しました。 (pukiwiki-index-sort nil ?d) (unless pagename (delete-other-windows)))) @@ -920,6 +1273,11 @@ (message "Loading index list...") (setq pukiwiki-index-page-info-list (pukiwiki-fetch-index site-info)) + ;; InterWikiName + (message "Loading InterWikiName list...") + (setq pukiwiki-index-interwiki-info-list + (pukiwiki-fetch-interwikiname site-info)) + (message "Loading attach list... (C-g for Cancel)") (condition-case err (setq pukiwiki-index-attach-list @@ -943,7 +1301,7 @@ (re-search-forward (format "^%4d" (nth 0 elm))) (beginning-of-line) (recenter)))) - (switch-to-buffer old-buf) + (set-buffer old-buf) ; 画面がチラ付くので変更しました。 buf)) (defun pukiwiki-index-get-buffer-create (site-info) @@ -991,7 +1349,8 @@ (setq pagename (nth 1 page-info)) (delete-other-windows) (split-window nil 10) - (recenter t) + ;; 画面がチラ付くので外してみました。 + ;; (recenter t) (other-window 1) (pukiwiki-display-page pagename pukiwiki-site-info refetch) (pukiwiki-view-mode) @@ -1015,10 +1374,12 @@ (pukiwiki-view-reformating) (setq buffer-read-only t) + (switch-to-buffer (current-buffer)) ; 画面がチラ付くので変更しました。 (other-window 1)) (pukiwiki-index pukiwiki-site-info nil pagename) (switch-to-buffer cbuf) - (goto-char point))) + (goto-char point) + (recenter))) (defun pukiwiki-index-display-page-next (&optional refetch) "現在行のページを表示する。すでに表示されている時はスクロールする。 @@ -1252,7 +1613,7 @@ (message "Ediff session...") ;; 最新バックアップのソースを取得し、バッファを生成。 - (setq backup-buffername (concat "*pukiwiki backup tmp*")) + (setq backup-buffername (concat " *pukiwiki backup tmp*")) (let* ((backup t) (url (progn (string-match "nowdiff" url) (replace-match "source" nil nil url)))) @@ -1260,7 +1621,7 @@ url pagename site-info backup-buffername backup)) ;; 現在のソースを取得し、バッファを生成。 - (setq current-buffername (concat "*pukiwiki current tmp*")) + (setq current-buffername (concat " *pukiwiki current tmp*")) (let* ((url (progn (string-match "cmd=backup\\(.*\\)&age=[0-9]*&action=nowdiff" url) @@ -1275,9 +1636,8 @@ buffername &optional backup day) (let ((raw backup)) - (setq contents (pukiwiki-fetch-source - pagename url - (pukiwiki-site-coding-system site-info) raw)) + (setq contents (pukiwiki-fetch-source pagename url + (pukiwiki-site-coding-system site-info) raw)) (setq buf (get-buffer-create buffername)) (switch-to-buffer buf) (setq buffer-read-only nil) @@ -1289,12 +1649,15 @@ (pukiwiki-view-mode) (when pukiwiki-auto-insert ; 整形ありのとき。 + (pukiwiki-set-auto-face) + (pukiwiki-text-reformating) (pukiwiki-insert-paragraph) (pukiwiki-insert-cite) (pukiwiki-insert-list) (pukiwiki-insert-ls2) - (pukiwiki-set-auto-face) + (pukiwiki-insert-simple-elements) + (pukiwiki-delete-blank-line) (pukiwiki-view-renumber)) @@ -2115,26 +2478,9 @@ (goto-char (point-min))) (and buf (kill-buffer buf)) (message "Loading...") - (condition-case err - (setq result (pukiwiki-fetch-source - pagename (pukiwiki-site-url site-info) - (pukiwiki-site-coding-system site-info))) - (error - (setq result (pukiwiki-fetch-source - pagename - (format "%s?cmd=%s&page=%s" - (pukiwiki-site-url site-info) - "diff" - (http-url-hexify-string - pagename - (pukiwiki-site-coding-system site-info))) - (pukiwiki-site-coding-system site-info) - 'diff)) - (setq result (delete (list 'password) result)) - (setq result - (cons - (cons 'password t) - result)))) + (setq result + (pukiwiki-fetch-source-in-order pagename site-info 'browse-extra)) + (setq body (cdr (assoc 'body result))) (setq pagetitle (cdr (assoc 'pagetitle result))) (setq password (cdr (assq 'password result))) @@ -2152,7 +2498,7 @@ (setq result nil)) not-cancelled))) (setq buf (generate-new-buffer "*pukiwiki tmp*")) - (switch-to-buffer buf) + (set-buffer buf) ; 画面がチラ付くので変更しました。 (pukiwiki-edit-rename-buffer (pukiwiki-site-name site-info) pagename pagetitle password) (save-excursion @@ -2266,6 +2612,63 @@ (setcdr history (mapcar (lambda (elm) (cons (nth 1 elm) nil)) indexes)) (reverse indexes)))) +;; InterWikiName +(defun pukiwiki-fetch-interwikiname (site-info) + "InterWikiName の一覧を取得する。" + + (save-excursion + ;; InterWikiName ページのソースを取得し、バッファを生成。 + (setq interwiki-buffername (concat " *pukiwiki interwiki tmp*")) + (let* ((url (concat (pukiwiki-site-url site-info) + "?cmd=edit&page=InterWikiName")) + (buf (pukiwiki-interwiki-create-buffer + url "InterWikiName" site-info interwiki-buffername))) + + ;; list を生成。 + (set-buffer buf) + (goto-char (point-min)) + (setq interwikiname-list nil) + (while (re-search-forward + "\\[\\(https*://[^ ]+\\) \\([^]]+\\)\\][ \t]*\\([^ \n\r]*\\).*$" + nil t) + (save-match-data + (setq match-url (match-string 1)) + (setq start 0 pos 0) + (while (setq pos (string-match "&" match-url start)) + (setq match-url (replace-match "&" nil nil match-url)) + (setq start pos))) + (setq interwikiname-list + (cons + (list (match-string 2) + match-url + nil + (cond + ((string= "euc" (match-string 3)) 'euc-jp-dos) + ((string= "sjis" (match-string 3)) 'shift_jis-dos) + ((string= "utf8" (match-string 3)) 'utf-8-dos) + ((string= "" (match-string 3)) 'utf-8-dos) + ((string= "raw" (match-string 3)) nil) + (t + (intern (match-string 3))))) + interwikiname-list))) + + (kill-buffer buf) + interwikiname-list))) + +(defun pukiwiki-interwiki-create-buffer (url pagename site-info + buffername + &optional opt) + (let* ((raw opt) + (contents (pukiwiki-fetch-source pagename url + (pukiwiki-site-coding-system site-info) raw)) + (buf (get-buffer-create buffername))) + + (set-buffer buf) + (setq buffer-read-only nil) + (erase-buffer) + (insert (cdr (assoc 'body contents))) + buf)) + (defun pukiwiki-fetch-attach-index (site-info) "添付ファイルの一覧を表示する。" (let (indexes @@ -2309,6 +2712,56 @@ indexes))))) indexes)) +(defun pukiwiki-fetch-source-in-order (page info &optional browser) + "与えられた page のデータを読み込む。 +先ず編集モードで読み込み、正当なデータが得られなかったら、差分モードで読む。 +差分も取得できなければ error 終了する。 +BROWSER が非 nil なら、差分も取得できなかったときに `browse-url' により、 +外部ブラウザでの読み込みを行なう。" + + (let ((pagename page) + (site-info info) + (browse-extra browser) + result) + + (condition-case err + (setq result (pukiwiki-fetch-source + pagename (pukiwiki-site-url site-info) + (pukiwiki-site-coding-system site-info))) + (error + (condition-case err + (setq result (pukiwiki-fetch-source + pagename + (format "%s?cmd=%s&page=%s" + (pukiwiki-site-url site-info) + "diff" + (http-url-hexify-string + pagename + (pukiwiki-site-coding-system site-info))) + (pukiwiki-site-coding-system site-info) + 'diff)) + (error + ;; 'diff で request しても Pukiwiki のテキストが見付からなかった + ;; 場合は、外部ブラウザにも依頼する。 + (when (and browse-extra pukiwiki-interwiki-browse-not-match-pukiwiki) + (let ((url (pukiwiki-site-url site-info t))) + (if (string-match "$1" url) + (progn + (setq url (replace-match + (http-url-hexify-string + page + (pukiwiki-site-coding-system site-info)) + nil nil url)) + (browse-url url)) + (browse-url (concat url page))))) + (error "PukiWiki のテキストが見つかりません"))) + + (setq result (delete (list 'password) result)) + (setq result + (cons + (cons 'password t) + result)))))) + (defun pukiwiki-fetch-source (pagename site-url coding-system &optional raw) "Pukiwiki の ソースを取得する。 @@ -2445,8 +2898,13 @@ (defun pukiwiki-site-name (&optional site-info) (nth 0 (or site-info pukiwiki-site-info))) -(defun pukiwiki-site-url (&optional site-info) - (nth 1 (or site-info pukiwiki-site-info))) +;; 2004.09.27 InterWikiName で、末尾が `?' な url も与えられてしまうので。 +;; (defun pukiwiki-site-url (&optional site-info) +;; (nth 1 (or site-info pukiwiki-site-info))) +(defun pukiwiki-site-url (&optional site-info no-strip) + (let ((url (nth 1 (or site-info pukiwiki-site-info)))) + (if (and (not no-strip) (string-match "\\?$" url)) + (replace-match "" nil nil url) url))) (defun pukiwiki-site-style (&optional site-info) (or (nth 2 (or site-info pukiwiki-site-info)) @@ -2491,7 +2949,7 @@ If STR is a string, replace entity references within the string. Otherwise replace all entity references within current buffer." (pukiwiki-do-replace-entity-ref - "&" "&" + " " " " (pukiwiki-do-replace-entity-ref "<" "<" (pukiwiki-do-replace-entity-ref @@ -2499,7 +2957,16 @@ (pukiwiki-do-replace-entity-ref """ "\"" (pukiwiki-do-replace-entity-ref - "'" "'" str)))))) + "'" "'" + (pukiwiki-do-replace-entity-ref + "<" "<" + (pukiwiki-do-replace-entity-ref + ">" ">" + (pukiwiki-do-replace-entity-ref + "&" "&" + (pukiwiki-do-replace-entity-ref + "&" "&" str + )))))))))) (defun pukiwiki-do-replace-entity-ref (from to &optional str) (save-match-data @@ -2566,26 +3033,44 @@ ;;; for pukiwiki ;;;; ページ表示の整形関連 -(defun pukiwiki-insert-comment-str (str) +(defun pukiwiki-insert-comment-str (str &optional region-start region-end) + (let ((beg (or region-start (point))) + (end (or region-end (1+ (point)))) + (end-marker (make-marker))) + + (if str + (progn + (set-marker end-marker end) + (insert str) + (pukiwiki-insert-comment-str-subr beg end-marker) + (insert "\n")) + (pukiwiki-insert-comment-str-subr beg end)))) + +(defun pukiwiki-insert-comment-str-subr (beg end) + (narrow-to-region beg end) + (let ((contents nil) (lth nil) (end nil)) - (with-temp-buffer - (text-mode) - (insert str) + ;; 改行されているコメントを、コメントごとに一行に詰め込む。 + (pukiwiki-insert-comment-str-fill-line) (goto-char (point-min)) (keep-lines "^-") (goto-char (point-min)) - (pukiwiki-replace-string "&new{" "" nil (point-min) (point-max)) + + ;; 実体参照や特殊文字を解決。 + (pukiwiki-replace-entity-refs) (pukiwiki-replace-string "&new{" "" nil (point-min) (point-max)) - (pukiwiki-replace-string "SIZE(10){" "" nil (point-min) (point-max)) + (pukiwiki-replace-regexp "SIZE([0-9]+){" "" nil (point-min) (point-max)) (pukiwiki-replace-regexp "}[;]*" "" nil (point-min) (point-max)) - (pukiwiki-replace-regexp - "^\\([-]+\\)\\([^\n\r]+\\)[ ]*--[ ]*\\[\\[\\([^]\n\r]+\\)\\]\\] \\([^\n\r]+\\)[ ]*$" - "\\1 \\4 [\\3]\n \\2" - nil (point-min) (point-max)) - (pukiwiki-replace-regexp - "^\\([-]+\\)\\([^\n\r]+\\)[ ]*--[ ]*\\([^[\n\r]+\\)[ ]*$" - "\\1 \\3 [名無し]\n \\2" - nil (point-min) (point-max)) + + ;; コメントの形式を見易い様に変換。 + ;; overlay が削られてしまうので変更してみました。 + (pukiwiki-replace-comment + "^\\([-]+\\)\\([^\n\r]+\\)\\([ ]*--[ ]*\\)\\(\\[\\[[^]\n\r]+\\]\\]\\) \\([^\n\r]+\\)[ ]*$" + (point-min) (point-max)) + (pukiwiki-replace-comment + "^\\([-]+\\)\\([^\n\r]+\\)\\([ ]*--[ ]*\\)\\([^[\n\r]+\\)[ ]*$" + (point-min) (point-max)) + (pukiwiki-replace-regexp "[ ]+$" "" nil (point-min) (point-max)) @@ -2616,49 +3101,911 @@ (format "%s" (make-string (* 2 lth) ? ))) (forward-line 1) (beginning-of-line))))) - ;; (replace-regexp "^[-]+" - ;; "_" - ;; nil (point-min) (point-max)) + + ;; anchor を有効に。 + (let ((beg (point-min-marker)) + (end (point-max-marker))) + (unwind-protect + (pukiwiki-insert-comment-with-anchor (point-min) (point-max)) + (save-excursion + (set-buffer (marker-buffer beg)) + (narrow-to-region beg end)))) + (fill-region (point-min) (point-max)) (pukiwiki-replace-regexp "\n[ ]*\n" "\n" - nil (point-min) (point-max)) - (setq contents (buffer-substring-no-properties - (point-min) (point-max)))) - (insert contents))) + nil (point-min) (point-max))) + (widen)) + +(defun pukiwiki-replace-comment (regexp start end) + "コメントの書式を変換する。" + + (let ((top start) (bottom end) (next (make-marker)) (prev start) header) + (goto-char top) + (catch 'range-over + (while (setq result (re-search-forward regexp bottom t)) + (set-marker next result) + (setq header (concat (match-string 1) " " + (or (match-string 5) "") " " + (match-string 4) "\n")) + (when (match-string 5) + (delete-region (match-beginning 5) (match-end 5))) + (delete-region (match-beginning 4) (match-end 4)) + (delete-region (match-beginning 3) (match-end 3)) + (delete-region (match-beginning 1) (match-end 1)) + + (save-excursion + (goto-char (match-beginning 1)) + (insert " ") + (forward-char -1) + ;; delete overlay from invalid point. + (let ((overlays (overlays-in (point) (1+ (point))))) + (while + (setq ovr (prog1 (car overlays) (setq overlays (cdr overlays)))) + (when (overlay-get ovr 'overlay) + (move-overlay ovr + (1+ (overlay-start ovr)) (overlay-end ovr))))) + ;; delete properties from invalid point. + (set-text-properties (point) (1+ (point)) nil) + (insert (concat header " "))) + + (setq bottom (+ bottom (- next result))) + (if (>= (point) bottom) ; insert で next が bottom よりも + ; 先に進んだ時も 'range-over. + (throw 'range-over t)) + (setq prev next)) + (cond ((eq result nil) ; もう match しなかった。 + (throw 'range-over t)) + ((>= next bottom) ; next が bottom を越えた。 + (throw 'range-over t)))))) + +(defun pukiwiki-insert-comment-str-fill-line () + "改行されているコメントを一行に詰め込む。" + + (save-excursion + (let (beg end next) + (goto-char (point-min)) + (catch 'not-match + (while (re-search-forward "^-" nil t) + (setq beg (line-beginning-position) + next (point)) + (if (re-search-forward "^-" nil t) + (progn + (forward-line -1) + (setq end (line-end-position))) + (throw 'not-match t)) + (pukiwiki-replace-regexp "\n" "" nil beg end) + (goto-char next)))))) + +(defun pukiwiki-insert-comment-with-anchor (start end) + (narrow-to-region start end) + ;; with delete url description. + (pukiwiki-insert-anchor + (cdr (assoc 'delete-url-description pukiwiki-style-anchor-regexp-alist))) + ;; to leave url description. + (pukiwiki-insert-anchor + (cdr (assoc 'leave-url-description pukiwiki-style-anchor-regexp-alist))) + (widen) + (point)) (defun pukiwiki-insert-comment () "pcomment によるコメントを挿入する" - (let ((comment nil)) + (let ((comment nil) reply-option) (save-excursion (save-current-buffer (goto-char (point-min)) - (when (re-search-forward "^#pcomment\\((reply)\\|\\)" nil t) - (message "Inserting pcomment...") - (setq comment - (pukiwiki-fetch-source - (concat "コメント/" pukiwiki-pagename) - (pukiwiki-site-url pukiwiki-site-info) - (pukiwiki-site-coding-system pukiwiki-site-info))) - (forward-line 1) - (if (cdr (assoc 'body comment)) - (pukiwiki-insert-comment-str (cdr (assoc 'body comment)))) - (pukiwiki-replace-entity-refs)) + (setq pname nil) + (while (re-search-forward + "^#pcomment\\((\\([^)]*\\)reply\\([^)]*\\))\\)*$" nil t) + (let ((options (concat (match-string 2) (match-string 3))) + option pname) + (catch 'match + (while (string-match "\\([^,]*\\) *, *\\(.*\\)" options) + (setq option (match-string 1 options)) + (setq options (match-string 2 options)) + (when (and (not (string= "" option)) + (not (string= "noname" option)) + (not (string= "nodate" option)) + (not (string= "above" option)) + (not (string= "below" option)) + (not (string-match "^[0-9]+$" option))) + (setq pname option) + (throw 'match t)))) + (unless pname + (setq pname + (if (string-match "\\[\\[\\(.+\\)\\]\\]" pukiwiki-pagename) + ;; 1.3 系の BracketName + (concat "[[" "コメント/" + (match-string 1 pukiwiki-pagename) "]]") + (concat "コメント/" pukiwiki-pagename)))) + + (message "Inserting comment...") + (setq comment + (pukiwiki-fetch-source-in-order + pname + pukiwiki-site-info nil)) + (forward-line 1) + (if (cdr (assoc 'body comment)) + (pukiwiki-insert-comment-str (cdr (assoc 'body comment)))) + ;; 2004.09.20 reply 対象のコメントを選択可能に。 + (pukiwiki-view-comment-form-pcomment-reformat) + + (pukiwiki-replace-entity-refs)))))) + (message "Inserting comment...done!")) + +;; comment form に対応。 +(defcustom pukiwiki-view-form-text-input-style nil + "*comment form のテキスト入力項目の表示、入力形式。" + :group 'pukiwiki + :type '(radio (const :tag "Not specified" nil) + (const :format "Ask name and comment: %v\n" ask) + (const :format "Display input text form: %v\n" form) + (const :format "Display input text form by large area: %v\n" large) + )) + +(defcustom pukiwiki-view-form-textarea-buffer-height 10 + "*Hieght of the MESSAGE input buffer." + :group 'pukiwiki + :type '(integer :size 0)) + +(defvar pukiwiki-view-form-elem-text-list + '("name" "msg") + "comment form のテキスト入力項目の要素リスト") + +(defvar pukiwiki-view-form-elem-list + '("encode_hint" "refer" "plugin" "nodate" "digest" "comment") + "comment form の共通な要素リスト") + +(defvar pukiwiki-view-form-elem-comment-list + '("comment_no" "above") + "comment form のみに必要な要素リスト") + +(defvar pukiwiki-view-form-elem-pcomment-list + '("reply" "page" "dir" "count") + "pcomment form のみに必要な要素リスト") + +(defvar pukiwiki-view-form-elem-article-list + '("article_no") + "article form のみに必要な要素リスト") + +(defun pukiwiki-view-form-textarea-setup-keys () + "Set up keymap for pukiwiki-view-form-textarea-mode. +If you want to set up your own key bindings, +use `pukiwiki-view-form-textarea-mode-hook'." + (define-key pukiwiki-view-form-textarea-mode-map + "\C-c\C-c" 'pukiwiki-view-form-textarea-set) + (define-key pukiwiki-view-form-textarea-mode-map + "\C-c\C-k" 'pukiwiki-view-form-textarea-exit) + (define-key pukiwiki-view-form-textarea-mode-map + "\C-c\C-q" 'pukiwiki-view-form-textarea-exit) + (define-key pukiwiki-view-form-textarea-mode-map + "\C-c\C-y" 'pukiwiki-view-form-textarea-buffer-history-yank)) + +(defun pukiwiki-view-form-textarea-set (&optional no-hist) + "入力されたデータを保存してバッファを破棄し、元の状態に復帰します。 +前置引数が指定されると、バッファ入力履歴への保存を行ないません。" + + (interactive "P") + + ;; バッファの破棄と元の状態への復帰。 + (let* ((ret (pukiwiki-view-form-textarea-exit no-hist)) + (input (car ret)) + (type (cdr ret))) + ;; 入力データの反映。 + (pukiwiki-view-comment-form-input 'already input type))) + +(defun pukiwiki-view-form-textarea-exit (&optional no-hist) + "入力されたデータとバッファを破棄し、元の状態に復帰します。 +前置引数が指定されると、バッファ入力履歴への保存を行ないません。" + + (interactive "P") + + (let ((input (buffer-string)) + (kbuf (current-buffer)) + (buf pukiwiki-view-form-textarea-orig-buf) + (pos pukiwiki-view-form-textarea-orig-pos) + (type pukiwiki-view-form-textarea-orig-type) + (wincfg pukiwiki-view-form-textarea-orig-wincfg)) + ;; 履歴に保持。 + (unless no-hist + (pukiwiki-view-form-textarea-buffer-history-push input)) + ;; バッファを破棄し、元の状態への復帰。 + (pukiwiki-view-form-textarea-kill-and-restore kbuf buf pos wincfg) + (cons input type))) + +(defun pukiwiki-view-form-textarea-kill-and-restore (kbuf buf pos config) + "バッファを破棄し、元の状態への復帰します。" + + ;; textarea buffer を抜ける。 + (kill-buffer kbuf) + ;; buffer, point, window の復元。 + (set-buffer buf) + (goto-char pos) + (set-window-configuration config)) + +(defun pukiwiki-view-form-textarea-buffer-history-push (str) + "Textarea バッファへの入力履歴を保存します。 +STR に指定された文字列を、履歴として保存します。" + + (when (and (> (length str) 0) + (not + (string= str (car pukiwiki-view-form-textarea-buffer-history)))) + (let ((history (cons str pukiwiki-view-form-textarea-buffer-history))) + (when (and str history) + (setq pukiwiki-view-form-textarea-buffer-history history) + ;; 履歴保持の最大数を超えたら、最古のものから削除する。 + (when (> (length pukiwiki-view-form-textarea-buffer-history) + pukiwiki-view-form-textarea-buffer-history-keep-count) + (setq pukiwiki-view-form-textarea-buffer-history + (nreverse + (cdr + (nreverse pukiwiki-view-form-textarea-buffer-history))))))))) + +(defun pukiwiki-view-form-textarea-buffer-history-get (&optional num) + "Textarea バッファへの入力履歴を取り出します。 +NUM に数値が指定されると、最新から NUM 番目の履歴を取り出します。 +NUM が nil か 0 だと、最新の履歴を取り出します。" + + (let ((newest (car pukiwiki-view-form-textarea-buffer-history)) + (specified + (and num (nth num pukiwiki-view-form-textarea-buffer-history)))) + (if specified specified newest))) + +(defvar pukiwiki-view-form-textarea-buffer-history nil + "Textarea への入力内容の履歴リスト") +(defvar pukiwiki-view-form-textarea-buffer-history-count 0 + "Textarea 入力バッファでの連続した yank command の実行回数") +(defvar pukiwiki-view-form-textarea-buffer-history-prepos 0 + "Textarea 入力バッファで、連続 yank する際に、以前の yank 内容を削除する +開始位置。") + +(defun pukiwiki-view-form-textarea-buffer-history-yank (&optional num) + "Textarea バッファへの入力履歴を yank します。 +このコマンドを連続して実行すると、逐次、履歴を遡って yank します。 +履歴の最古に到達すると、次は最新の履歴を yank します。" + + (interactive "P") + (let* ((same-command (eq this-command last-command)) + (num + (if same-command + (setq pukiwiki-view-form-textarea-buffer-history-count + (if (= (1+ pukiwiki-view-form-textarea-buffer-history-count) + (length pukiwiki-view-form-textarea-buffer-history)) + 0 + (1+ pukiwiki-view-form-textarea-buffer-history-count))) + (setq pukiwiki-view-form-textarea-buffer-history-prepos (point)) + (setq pukiwiki-view-form-textarea-buffer-history-count 0))) + (pos pukiwiki-view-form-textarea-buffer-history-prepos) + (result (pukiwiki-view-form-textarea-buffer-history-get num))) + (when same-command + (delete-region pos (point))) + (insert result))) + +(define-derived-mode pukiwiki-view-form-textarea-mode text-mode + "Pukiwiki Textarea" + "Major mode for input buffer of textarea. + +\\{pukiwiki-view-form-textarea-mode-map}" + + (pukiwiki-view-form-textarea-setup-keys) + + (make-local-variable 'pukiwiki-view-form-textarea-orig-buf) + (make-local-variable 'pukiwiki-view-form-textarea-orig-pos) + (make-local-variable 'pukiwiki-view-form-textarea-orig-type) + (make-local-variable 'pukiwiki-view-form-textarea-orig-wincfg) + + (setq mode-name "pukiwiki view form textarea" + major-mode 'pukiwiki-view-form-textarea-mode) + (run-hooks 'pukiwiki-view-form-textarea-mode-hook)) + +(defun pukiwiki-view-form-input (input-type property) + (let ((prop property) + (type input-type)) + (pukiwiki-view-comment-form-input type))) + +(defun pukiwiki-view-form-select-radio-button (select) + (let ((pos (point)) + (status select) + star end) + (when (and (get-text-property (point) 'anchor) + (numberp (get-text-property (point) 'radio))) + + ;; radio button の選択は、`*' を表示することで表現する。 + (save-excursion + ;; 対象 extent の保持。 + (goto-char (next-single-property-change (point) 'anchor)) + (setq end (point)) + (setq start (previous-single-property-change (point) 'anchor)) + + ;; all clear. + (pukiwiki-view-form-unselect-all-radio-button) + + ;; toggle select status. (on or off) + (if (eq 'yes status) + (add-text-properties start end (list 'select 'no)) + (add-text-properties start end (list 'select 'yes)))) + ;; mark update. + (pukiwiki-view-form-select-radio-button-refresh start end)) + (goto-char pos))) + +(defun pukiwiki-view-form-select-radio-button-refresh (start end) + (let ((status (get-text-property start 'select))) + (setq buffer-read-only nil) + (goto-char start) + (re-search-forward "[ *]" nil t) + (if (eq 'yes status) + (replace-match "*") + (replace-match " ")) + (setq buffer-read-only t))) + +(defun pukiwiki-view-form-unselect-all-radio-button () + (save-excursion + (let ((start (previous-single-property-change (point) 'pcomment-start)) + (end (next-single-property-change (point) 'pcomment-end)) + next) + (goto-char start) + (while (< (setq next + (next-single-property-change (point) 'anchorhead nil end)) + end) + (progn + (goto-char next) + (when (get-text-property (point) 'radio) + (setq next-end (next-single-property-change (point) 'anchor)) + (add-text-properties next next-end (list 'select 'no)) + (pukiwiki-view-form-select-radio-button-refresh next next-end))))))) + +(defun pukiwiki-view-comment-form-input (input-type &optional input original) + (let ((pos (point)) + (type input-type) + (orig-type original) + (data input)) + (save-excursion + ;; minibuffer か、Textarea 入力用バッファからの入力を受け付けて、 + (cond + ((eq type 'name) + (setq data (cdr (pukiwiki-view-comment-form-text-input-get-name)))) + ((eq type 'comment) + (if (eq pukiwiki-view-form-text-input-style 'large) + (pukiwiki-view-comment-form-text-input-get-str-from-buffer + (current-buffer) pos type) + (setq data + (cdr (pukiwiki-view-comment-form-text-input-get-comment))))) + ((eq type 'subject) + (setq data (cdr (pukiwiki-view-comment-form-text-input-get-subject)))) + ((eq type 'message) + (if (eq pukiwiki-view-form-text-input-style 'large) + (pukiwiki-view-comment-form-text-input-get-str-from-buffer + (current-buffer) pos type) + (setq data + (cdr (pukiwiki-view-comment-form-text-input-get-message))))) + (t nil)) + (unless (null data) + (when (= (length data) 0) (setq data nil))) + + (when (or (eq type 'name) + (and (eq type 'comment) + (not (eq pukiwiki-view-form-text-input-style 'large))) + (eq type 'subject) + (and (eq type 'message) + (not (eq pukiwiki-view-form-text-input-style 'large))) + (eq type 'already)) + + (when (eq type 'already) ; 'already の場合は元の type に戻す。 + (setq type original)) + + ;; 範囲を特定し、 + (setq start + (next-single-property-change (line-beginning-position) type)) + (setq end (next-single-property-change start type)) + + ;; property に設定すると共に、buffer を書き換える。 + (setq buffer-read-only nil) + (delete-region (line-beginning-position) end) + (pukiwiki-view-comment-form-insert-input type data) + (setq buffer-read-only t))) + (goto-char pos))) + +(defun pukiwiki-view-form-submit (property) + (let ((prop property)) + (when (pukiwiki-view-comment-form-request prop) + (pukiwiki-view-display-page pukiwiki-pagename 1 nil t)))) + +(defun pukiwiki-view-comment-form-request (property) + (interactive) + + ;; element の収集。 + (let* ((prop property) + (plugin (cdr (assoc "plugin" prop))) + (list (append pukiwiki-view-form-elem-list + (cond ((string= "comment" plugin) + pukiwiki-view-form-elem-comment-list) + ((string= "pcomment" plugin) + pukiwiki-view-form-elem-pcomment-list)))) + post-data) + + ;; 入力項目以外。この時点では reply は list のまま。 + (mapcar (lambda (key) (add-to-list 'post-data (assoc key prop))) list) + ;; 入力項目。 + (setq post-data + (pukiwiki-view-comment-form-text-input-get post-data plugin)) + + (if (string= "" (cdr (assoc "msg" post-data))) + (progn (message "Comment text missing!!") nil) + ;; request を post する。 + (message "Putting Text...") + (setq buf + (pukiwiki-http-request 'post nil pukiwiki-pagename + (pukiwiki-site-url) + (pukiwiki-site-coding-system) + post-data)) + t))) + +(defun pukiwiki-view-comment-form-text-input-get (post plugin) + (let (flag) + ;; post する form に入力されたデータを取得。 + (cond + ;; 入力済みの項目内容を properties から得る。 + ((or (eq pukiwiki-view-form-text-input-style 'form) + (eq pukiwiki-view-form-text-input-style 'large)) + (setq result-list + (pukiwiki-view-comment-form-text-input-get-data plugin)) + (add-to-list 'post (assoc "name" result-list)) + + (cond + ((string-match "p*comment" plugin) + (add-to-list 'post (assoc "msg" result-list)) + (if (assoc "reply" result-list) + (setq order (1- (cdr (assoc "reply" result-list)))) + (setq order (car (rassoc "0" (car (cdr (assoc "reply" post))))))) + (when (string= plugin "pcomment") + (when (assoc "reply" post) + (setcdr (assoc "reply" post) + (cdr (assoc order (car (cdr (assoc "reply" post))))))))) + + ((string= plugin "article") + (add-to-list 'post (assoc "subject" result-list)) + (add-to-list 'post (assoc "msg" result-list))))) + + ((eq pukiwiki-view-form-text-input-style 'ask) + ;; ミニバッファから。 + (add-to-list 'post + (pukiwiki-view-comment-form-text-input-get-name)) + (cond + ((string-match "p*comment" plugin) + (add-to-list 'post + (pukiwiki-view-comment-form-text-input-get-comment)) + (when (string= plugin "pcomment") + ;; 選択された順序番号を持つ `reply' に絞るため、list の中身を + ;; 書き換える。 + (when (assoc "reply" post) + (setcdr + (assoc "reply" post) + (cdr (assoc (1- + (string-to-number + (pukiwiki-view-comment-form-text-input-get-replyno))) + (car (cdr (assoc "reply" post))))))))) + ((string= plugin "article") + (add-to-list 'post + (pukiwiki-view-comment-form-text-input-get-subject)) + (add-to-list 'post + (pukiwiki-view-comment-form-text-input-get-message)))))) + post)) + +(defun pukiwiki-view-comment-form-text-input-get-data (plugin) + (let (reply-no name-value msg-value subject-value name subject msg) + ;; plugin に応じて、以下の property を探す。 + ;; p*comment のとき: name, msg (comment) を探す。 + ;; article のとき : name, subject, message を探す。 + (save-excursion + (catch 'found + (while (setq next (previous-single-property-change (point) 'anchorhead)) + (goto-char next) + (cond + ;; name + ((and (eq 'form (get-text-property (point) 'anchortype)) + (setq name (get-text-property (point) 'name))) + (setq name-value name)) + ;; msg (comment) + ((and (eq 'form (get-text-property (point) 'anchortype)) + (setq msg (get-text-property (point) 'comment))) + (setq msg-value msg)) + ;; subject + ((and (eq 'form (get-text-property (point) 'anchortype)) + (setq subject (get-text-property (point) 'subject))) + (setq subject-value subject)) + ;; msg (message) + ((and (eq 'form (get-text-property (point) 'anchortype)) + (setq msg (get-text-property (point) 'message))) + (setq msg-value msg))) + (when (or (and name-value msg-value) + (and name-value subject-value msg-value)) + (throw 'found t))))) + + (setq ret (list (cons "name" name-value) + (cons "msg" msg-value))) + (when subject-value (setq ret (cons (cons "subject" subject-value) ret))) + + ;; reply-no を探す。 + (when (string= plugin "pcomment") + (save-excursion + (let ((start (previous-single-property-change (point) 'pcomment-start)) + (end (previous-single-property-change (point) 'pcomment-end)) + next no) + (goto-char start) + (while (< (setq next (next-single-property-change + (point) 'anchorhead nil end)) end) + (progn + (goto-char next) + (cond + ;; reply-no + ((and (eq 'radio (get-text-property (point) 'anchortype)) + (setq no (get-text-property (point) 'radio)) + (eq 'yes (get-text-property (point) 'select))) + (setq reply-no no)))))) + + (when reply-no + (add-to-list 'ret (cons "reply" reply-no))))) + ret)) + +(defvar pukiwiki-view-form-name-history nil) +(defvar pukiwiki-view-form-comment-history nil) +(defvar pukiwiki-view-form-subject-history nil) +(defvar pukiwiki-view-form-message-history nil) +(defun pukiwiki-view-comment-form-text-input-get-name () + (let* ((name-default pukiwiki-view-comment-form-name-default) + (ret (cons "name" + (read-string + (if name-default + (format "Name (%s): " name-default) + (format "Name : ")) + nil 'pukiwiki-view-form-name-history name-default)))) + (message nil) + ret)) + +(defun pukiwiki-view-comment-form-text-input-get-comment () + (let ((ret (cons "msg" (read-string "Comment: " nil + 'pukiwiki-view-form-comment-history + nil)))) + (message nil) + ret)) + +(defun pukiwiki-view-comment-form-text-input-get-subject () + (let ((ret + (cons "subject" (read-string "Subject: " nil + 'pukiwiki-view-form-subject-history + nil)))) + (message nil) + ret)) + +(defun pukiwiki-view-comment-form-text-input-get-message () + (let ((ret + (cons "msg" (read-string "Message: " nil + 'pukiwiki-view-form-message-history + nil)))) + (message nil) + ret)) + +(defun pukiwiki-view-comment-form-text-input-get-str-from-buffer + (buf pos type) + (let ((ibuf (generate-new-buffer "*pukiwiki view form textarea*")) + (obuf buf) (opos pos) + (current-window (selected-window))) + ;; create buffer of text area. + (set-buffer ibuf) + (pukiwiki-view-form-textarea-mode) + + ;; set up local variables. + (setq pukiwiki-view-form-textarea-orig-buf obuf) + (setq pukiwiki-view-form-textarea-orig-pos opos) + (setq pukiwiki-view-form-textarea-orig-type type) + (setq + pukiwiki-view-form-textarea-orig-wincfg (current-window-configuration)) + + ;; split window. + (let ((height (- (window-height current-window) + pukiwiki-view-form-textarea-buffer-height))) + (split-window current-window (max window-min-height height)) + (select-window (next-window)) + (switch-to-buffer ibuf)))) + +(defun pukiwiki-view-comment-form-text-input-get-replyno () + (let ((ret (read-string "Reply No: " nil t nil))) (message nil) ret)) + +(defun pukiwiki-view-comment-form-insert (form-type) + (let* ((type form-type) + (add (cond + ((eq type 'comment) pukiwiki-view-form-elem-comment-list) + ((eq type 'pcomment) pukiwiki-view-form-elem-pcomment-list) + ((eq type 'article) pukiwiki-view-form-elem-article-list) + ((eq type 'all) (apply 'append + pukiwiki-view-form-elem-comment-list + pukiwiki-view-form-elem-pcomment-list + pukiwiki-view-form-elem-article-list)))) + (list (append pukiwiki-view-form-elem-list add)) + reply-list) + ;; form data を取って来る。 + (setq result-list nil) + (let ((form-list (pukiwiki-view-form-data-get)) + ret-list) + (setq result-list + (mapcar + (lambda (form) + (let (pos key val ret (reply-count 0)) + (while + ;; key . value の pair を検索。 + (string-match + "\\s-+\\([a-zA-Z0-9_]+\\)=\"\\([^\"]+\\)\"" + form pos) + (setq pos (match-end 0)) + ;; pair が揃ったかチェック。 + (cond + ((string= (match-string 1 form) "name") + (setq key (match-string 2 form))) + ((string= (match-string 1 form) "value") + (setq val (match-string 2 form)))) + (when (and key val) + ;; pair が揃ったら cons にして返す。 + ;; `reply' は nest させる。 + (if (string= key "reply") + (progn + (setq reply-list + (cons (cons reply-count val) reply-list)) + (setq reply-count (1+ reply-count))) + (setq ret (cons (cons key val) ret))) + (setq key nil + val nil))) + ;; reply の分を ret に。 + (when reply-list + (setq ret (cons (cons "reply" (list reply-list)) ret)) + (setq reply-list nil)) + ret)) form-list)) + + ;; comment, pcomment 以外の form を除外する。 + (setq result-tmp-list result-list) + (setq result-list nil) + (while (setq form-elems (car result-tmp-list)) + (when (string-match "\\(p*comment\\|article\\)" + (cdr (assoc "plugin" form-elems))) + (setq result-list (cons form-elems result-list))) + (setq result-tmp-list (cdr result-tmp-list))) + ;; (setq result-list (nreverse result-list)) + (ignore)) + + ;; バッファへの設定。 + (pukiwiki-view-comment-form-insert-subr result-list) + )) + +(defun pukiwiki-view-comment-form-insert-subr (list) + (let ((elements-list list) plugin-type) + (save-excursion + (goto-char (point-min)) + ;;;;;; (switch-to-buffer (current-buffer)) ;;;;; for degug. + (while (re-search-forward + "^#\\(p*comment\\|article\\)\\(([^)]*)\\)*$" + nil t) + (setq plugin-type (match-string 1)) + (forward-line 1) + (when pukiwiki-view-form-text-input-style + (cond + ((or (eq pukiwiki-view-form-text-input-style 'form) + (eq pukiwiki-view-form-text-input-style 'large)) + ;; name input. + (insert "\n\n") + (forward-line -1) + (pukiwiki-view-comment-form-insert-input 'name "") + (cond + ((string-match "p*comment" plugin-type) + ;; comment input. + (insert "\n") + (forward-line -1) + (pukiwiki-view-comment-form-insert-input 'comment "")) + ((string= plugin-type "article") + ;; subject input. + (insert "\n") + (forward-line -1) + (pukiwiki-view-comment-form-insert-input 'subject "") + ;; message (comment-extra) input. + (insert "\n") + (forward-line -1) + (pukiwiki-view-comment-form-insert-input 'message "")) + (t nil))) + (t nil)) + ;; submit button. + (insert (concat " [" + (let ((elem (car elements-list))) + (or (cdr (assoc (cdr (assoc "plugin" elem)) elem)) + "コメントの挿入")) ; pcomment の時だけ変だ。 + "]\n\n")) + (forward-line -2) + (pukiwiki-view-comment-form-insert-property-set + (car elements-list) 'button 2) + (setq elements-list (cdr elements-list))) + )))) + +(defun pukiwiki-view-comment-form-insert-input (type data) + (let* ((prefix " ") ; 段落整形されてしまってフォーマットが + ; 崩れてしまうため、整形済みテキストと + ; 認識させるために必要。 + (prompt (cond ((eq type 'name) "名前 ") + ((eq type 'comment) "コメント ") + ((eq type 'subject) "題名 ") + ((eq type 'message) "記事 "))) + (len (cond ((eq type 'name) + pukiwiki-view-comment-form-name-field-width) + ((eq type 'comment) + pukiwiki-view-comment-form-comment-field-width) + ((eq type 'subject) + pukiwiki-view-comment-form-subject-field-width) + ((eq type 'message) + pukiwiki-view-comment-form-message-field-width))) + (str (if data + (format (concat "%-" (number-to-string len) "s") data) + (make-string len ? ))) + (offset (length (concat prefix prompt)))) + + ;; バッファへの表示データに改行が含まれていれば無効に。 + (while (string-match "\n+" str) + (setq str (replace-match "" nil nil str))) + ;; コメントの場合は、保持するデータに含まれる改行も無効に。 + (when (eq type 'comment) + (while (string-match "\n+" data) + (setq data (replace-match "" nil nil data)))) + + (when (> (string-width str) len) + (setq str (pukiwiki-truncate-string str len))) + (insert (concat prefix prompt "[" str "]")) + (pukiwiki-view-comment-form-insert-property-set data type offset))) + +(defun pukiwiki-truncate-string (str width) + "pukiwiki-mode 用の truncate-string. + +STR で指定された文字列の先頭から、WIDTH で指定された流さ分の文字列を +取り出して返します。端数が発生した場合は、空白をパディングします。" + + (let ((start 0) (end 1) (index 0) (len 0) ret-str rest) + (catch 'length-over + (while (setq c (substring str start end)) + (if (<= (setq len (+ (char-width (aref c index)) len)) width) + (progn + (if ret-str + (setq ret-str (format "%s%s" ret-str c)) + (setq ret-str (format "%s" c))) + (setq rest (- width len)) + (setq start (1+ start)) + (setq end (1+ start))) + (throw 'length-over t)))) + (if rest + (setq ret-str (format "%s%s" ret-str (make-string rest ? )))) + ret-str)) + +(defun pukiwiki-view-comment-form-insert-property-set (str type offset) + (let ((start (+ (line-beginning-position) offset)) + (end (line-end-position)) + (prop (or str ""))) + ;; text property set. + (add-text-properties start end + (list 'anchor t 'anchortype 'form + type prop) nil) + (add-text-properties (1+ start) (+ start 2) (list 'anchorhead t) nil) + ;; overlay set. + (setq ovr (make-overlay start end)) + (overlay-put ovr 'face 'pukiwiki-view-button-face) + (overlay-put ovr 'priority 1) + (goto-char end)) + (forward-line 1)) + +(defvar pukiwiki-view-comment-form-reply-level 2 + "The level of comment to enable reply.") + +(defun pukiwiki-view-comment-form-pcomment-reformat () + (save-excursion + (let* ((reg-end (point)) + (reg-start (progn + (re-search-backward "^#pcomment" nil t) + (point))) + (reply-no 0) + mark) + (narrow-to-region reg-start reg-end) + + ;; pcomment 挿入部分の開始位置設定。 + (goto-char (point-min)) + (add-text-properties (point) (1+ (point)) + (list 'pcomment-start t) nil) + + (while (re-search-forward "^\\(\\s-*\\)\\(_\\)" nil t nil) + ;; level 2 までだけ変換。 + (when (< (length (match-string 1)) + (1+ (* pukiwiki-view-comment-form-reply-level 2))) + (setq reply-no (1+ reply-no)) + (let* ((start (match-beginning 2)) + (end (match-end 2))) + ;; 行頭部分の記号を置換。 + (cond + ((or (eq pukiwiki-view-form-text-input-style 'form) + (eq pukiwiki-view-form-text-input-style 'large)) + (setq mark " ")) + ((eq pukiwiki-view-form-text-input-style 'ask) + (setq mark (number-to-string reply-no))) + (t nil)) + (replace-match (concat "[" mark "]") t nil nil 2) + ;; property, overlay を設定。 + (cond + ((or (eq pukiwiki-view-form-text-input-style 'form) + (eq pukiwiki-view-form-text-input-style 'large)) + ;; 先に置換してしまうので、point を調整。 + (let ((start (1+ start)) + (end (1+ end))) + ;; property set. + (pukiwiki-set-content-anchor-property + start end 'radio reply-no nil 0 'select 'no) + ;; overlay set. + (setq ovr (make-overlay start end)) + (overlay-put ovr 'face 'pukiwiki-view-button-face) + (overlay-put ovr 'priority 1))))))) + + ;; pcomment 挿入部分の終了位置設定。 + (goto-char (point-max)) + (add-text-properties (1- (point)) (point) + (list 'pcomment-end t) nil) + (widen)))) + +(defun pukiwiki-view-form-data-get () + "form data を取って来る。" + + (let* ((pagename + (if (string= major-mode 'pukiwiki-index-mode) + (nth 1 (pukiwiki-index-page-info-current-line)) + pukiwiki-pagename)) + (url nil) + (site-info pukiwiki-site-info) + (site-url (pukiwiki-site-url)) + (site-name (car pukiwiki-site-info)) + buf) + (message "Getting form data...") + + ;; 表示形式のソースを取得し、バッファを生成。 + (setq current-buffername (concat " *pukiwiki form tmp*")) + (let* ((url site-url) + (pukiwiki-auto-insert nil)) + + (setq form-list nil) + + ;; form data の抽出。 + (save-current-buffer + (setq buf (pukiwiki-view-comment-form-create-buffer + url pagename site-info current-buffername)) + (set-buffer buf) (goto-char (point-min)) - (when (re-search-forward "^#pcomment(reply[ ]*,\\([^),]+\\))" nil t) - (message "Inserting comment...") - (setq comment - (pukiwiki-fetch-source - (buffer-substring-no-properties - (match-beginning 1) (match-end 1)) - (pukiwiki-site-url pukiwiki-site-info) - (pukiwiki-site-coding-system pukiwiki-site-info))) - (forward-line 1) - (if (cdr (assoc 'body comment)) - (pukiwiki-insert-comment-str (cdr (assoc 'body comment)))) - (pukiwiki-replace-entity-refs) - ))) - (message "Inserting comment...done!"))) + (if (catch 'end-tag-nothing + (while (re-search-forward "