yuuji@395: ;;; yatexhlp.el --- YaTeX helper for LaTeX -*- coding: sjis -*- yuuji@287: ;;; yuuji@546: ;;; (c)1994,1998,2004,2014,2015,2018 by HIROSE Yuuji.[yuuji@yatex.org] yuuji@546: ;;; Last modified Sat Jun 2 16:45:45 2018 on firestorm yuuji@366: ;;; $Id$ yuuji@16: yuuji@287: ;;; Code: yuuji@46: (let ((help-file (concat "YATEXHLP." yuuji@46: (cond (YaTeX-japan "jp") yuuji@46: (t "eng")))) yuuji@46: (help-dir yuuji@49: (cond yuuji@68: ((and (boundp 'site-directory) site-directory) site-directory) yuuji@80: ((string-match "\\.app/" doc-directory) ;For Emacs.app(Darwin) yuuji@382: (expand-file-name "../site-lisp/yatex" doc-directory)) yuuji@382: (YaTeX-emacs-19 yuuji@382: (expand-file-name "../../site-lisp/yatex" doc-directory)) yuuji@49: (t exec-directory)))) yuuji@16: (defvar YaTeX-help-file yuuji@46: (expand-file-name help-file help-dir) yuuji@16: "*Help file of LaTeX/TeX commands or macros.") yuuji@16: (defvar YaTeX-help-file-private yuuji@16: (expand-file-name (concat "~/" help-file)) yuuji@68: "*Private help file of LaTeX/TeX macros.")) yuuji@68: yuuji@16: (defvar YaTeX-help-delimiter "\C-_" "Delimiter of each help entry.") yuuji@16: (defvar YaTeX-help-entry-map (copy-keymap YaTeX-mode-map) yuuji@16: "Key map used in help entry.") yuuji@16: (defvar YaTeX-help-file-current nil yuuji@16: "Holds help file name to which the description in current buffer should go.") yuuji@16: (defvar YaTeX-help-command-current nil yuuji@16: "Holds command name on which the user currently write description.") yuuji@16: (defvar YaTeX-help-saved-config nil yuuji@16: "Holds window configruation before the editing of manual.") yuuji@16: (defvar YaTeX-help-synopsis yuuji@16: (cond (YaTeX-japan "【書式】") yuuji@16: (t "[[ Synopsis ]]")) yuuji@16: "Section header of synopsis.") yuuji@16: (defvar YaTeX-help-description yuuji@16: (cond (YaTeX-japan "【説明】") yuuji@16: (t "[[ Description ]]")) yuuji@16: "Section header of description.") yuuji@16: yuuji@80: (defvar YaTeX-help-mode-map nil "Keymap used in YaTeX-help buffer") yuuji@80: (if YaTeX-help-mode-map nil yuuji@80: (setq YaTeX-help-mode-map (make-sparse-keymap)) yuuji@80: (let ((map YaTeX-help-mode-map)) yuuji@80: (suppress-keymap map) yuuji@353: (define-key map "j" (function (lambda () (interactive) (scroll-up 1)))) yuuji@353: (define-key map "k" (function (lambda () (interactive) (scroll-up -1)))) yuuji@80: (define-key map "n" 'next-line) yuuji@80: (define-key map "p" 'previous-line) yuuji@80: (define-key map " " 'scroll-up) yuuji@80: (define-key map "\C-?" 'scroll-down) yuuji@80: (define-key map "o" 'other-window) yuuji@80: (define-key map "h" 'describe-bindings) yuuji@80: (define-key map "q" 'YaTeX-help-quit) yuuji@80: (define-key map "<" 'beginning-of-buffer) yuuji@80: (define-key map ">" 'end-of-buffer))) yuuji@80: yuuji@80: (defun YaTeX-help-quit () yuuji@80: "Close help and return to privious buffer" yuuji@80: (interactive) yuuji@80: (bury-buffer (current-buffer)) yuuji@80: (set-window-configuration YaTeX-help-saved-config)) yuuji@80: yuuji@23: (defvar YaTeX-help-reference-regexp "]+\\)>" yuuji@23: "Regexp of reference format of YaTeX-help file.") yuuji@23: (defvar YaTeX-help-buffer "** YaTeX HELP **" "Help buffer name for yatexhlp") yuuji@23: yuuji@23: (defun YaTeX-help-entries () yuuji@23: "Return the alist which contains all the entries in YaTeX-help file." yuuji@23: (let (entries entry) yuuji@23: (save-excursion yuuji@23: (mapcar yuuji@23: (function yuuji@23: (lambda (help) yuuji@23: (if (file-exists-p help) yuuji@23: (progn yuuji@23: (set-buffer (find-file-noselect help)) yuuji@23: (save-excursion yuuji@23: (goto-char (point-min)) yuuji@23: (while (re-search-forward yuuji@23: (concat "^" (regexp-quote YaTeX-help-delimiter) yuuji@23: "\\(.+\\)$") nil t) yuuji@23: (setq entry (buffer-substring yuuji@23: (match-beginning 1) (match-end 1))) yuuji@23: (or (assoc entry entries) yuuji@23: (setq entries (cons (list entry) entries))))))))) yuuji@23: (list YaTeX-help-file YaTeX-help-file-private))) yuuji@80: entries)) yuuji@23: yuuji@80: (defvar YaTeX-help-entries nil yuuji@80: "Helo entries alist.") yuuji@80: (setq YaTeX-help-entries (YaTeX-help-entries)) yuuji@23: yuuji@23: (defun YaTeX-help-resolve-reference (buffer1 buffer2 &optional done-list) yuuji@23: "Replace reference format in buffer1 with refered contents in buffer2." yuuji@23: (let (ref ref-list beg end) yuuji@23: (save-excursion yuuji@23: (switch-to-buffer buffer1) yuuji@23: (goto-char (point-min)) yuuji@23: (while (re-search-forward YaTeX-help-reference-regexp nil t) yuuji@23: (setq ref (buffer-substring (match-beginning 1) (match-end 1)) yuuji@23: ref-list (cons (list ref) ref-list)) yuuji@23: (replace-match "") yuuji@23: (if (assoc ref done-list) nil ;already documented. yuuji@23: (switch-to-buffer buffer2) yuuji@23: (save-excursion yuuji@23: (goto-char (point-min)) yuuji@23: (if (re-search-forward yuuji@23: (concat (regexp-quote YaTeX-help-delimiter) yuuji@23: (regexp-quote ref) yuuji@23: "$") nil t) yuuji@23: (progn yuuji@23: (setq beg (progn (forward-line 2) (point)) yuuji@23: end (progn yuuji@23: (re-search-forward yuuji@23: (concat "^" (regexp-quote YaTeX-help-delimiter)) yuuji@23: nil 1) yuuji@23: (goto-char (match-beginning 0)) yuuji@23: (forward-line -1) yuuji@23: (while (and (bolp) (eolp) (not (bobp))) yuuji@23: (forward-char -1)) yuuji@23: (point))) yuuji@23: (switch-to-buffer buffer1) yuuji@23: (insert-buffer-substring buffer2 beg end)))) yuuji@23: (switch-to-buffer buffer1))) yuuji@23: (if beg (YaTeX-help-resolve-reference yuuji@80: buffer1 buffer2 (append done-list ref-list)))))) yuuji@23: yuuji@23: (defun YaTeX-refer-help (command help-file &optional append) yuuji@16: "Refer the COMMAND's help into HELP-FILE. yuuji@16: \[Help-file format\] yuuji@16: yuuji@16: yuuji@16: yuuji@16: Where: is the value of YaTeX-help-delimiter. yuuji@16: is newline. yuuji@16: is newline or end of buffer." yuuji@16: (let ((hfbuf (find-file-noselect help-file)) yuuji@23: (hbuf (get-buffer-create YaTeX-help-buffer)) yuuji@16: (curwin (selected-window)) yuuji@16: sb se db de) yuuji@16: (set-buffer hfbuf) yuuji@16: (goto-char (point-min)) yuuji@16: (if (null yuuji@23: (let ((case-fold-search nil)) yuuji@23: (re-search-forward yuuji@23: (concat (regexp-quote YaTeX-help-delimiter) yuuji@23: (regexp-quote command) yuuji@23: "$") nil t))) yuuji@16: nil ;if not found, return nil yuuji@16: (forward-line 1) yuuji@16: (setq sb (point) yuuji@16: se (progn (forward-line 1) (point)) yuuji@16: db (point) yuuji@16: de (progn yuuji@23: (re-search-forward yuuji@23: (concat "^" (regexp-quote YaTeX-help-delimiter)) nil 1) yuuji@23: (- (point) (length YaTeX-help-delimiter)))) yuuji@23: (YaTeX-showup-buffer yuuji@354: hbuf 'YaTeX-showup-buffer-bottom-most t) yuuji@59: (set-buffer hbuf) yuuji@80: (setq buffer-read-only nil) yuuji@23: (if append (goto-char (point-max)) (erase-buffer)) yuuji@16: (insert YaTeX-help-synopsis "\n") yuuji@16: (insert-buffer-substring hfbuf sb se) yuuji@16: (insert "\n" YaTeX-help-description "\n") yuuji@16: (insert-buffer-substring hfbuf db de) yuuji@23: (YaTeX-help-resolve-reference hbuf hfbuf (list (list command))) yuuji@16: (goto-char (point-min)) yuuji@80: (setq buffer-read-only t) yuuji@80: (set-buffer-modified-p nil) yuuji@80: (YaTeX-help-mode) yuuji@16: (select-window curwin) yuuji@80: t))) yuuji@80: yuuji@80: (defun YaTeX-help-mode () yuuji@80: (interactive) yuuji@80: (use-local-map YaTeX-help-mode-map) yuuji@80: (setq major-mode 'yatex-help-mode yuuji@80: mode-name "YaTeX-HELP")) yuuji@80: yuuji@16: (defun YaTeX-help-newline (&optional arg) yuuji@16: (interactive "P") yuuji@16: (if (and (= (current-column) 1) (= (preceding-char) ?.) (eolp)) yuuji@16: (let ((cbuf (current-buffer))) yuuji@16: (beginning-of-line) yuuji@53: (delete-region (point) (progn (forward-line 1) (point))) yuuji@16: (save-excursion yuuji@16: (YaTeX-help-add-entry yuuji@16: YaTeX-help-command-current YaTeX-help-file-current)) yuuji@16: (set-window-configuration YaTeX-help-saved-config) yuuji@16: (bury-buffer cbuf)) yuuji@80: (newline arg))) yuuji@80: yuuji@16: (defun YaTeX-help-add-entry (command help-file) yuuji@16: (let ((hfbuf (find-file-noselect help-file)) yuuji@16: (dbuf (current-buffer)) beg end) yuuji@16: (goto-char (point-min)) yuuji@16: (re-search-forward (concat "^" (regexp-quote YaTeX-help-synopsis))) yuuji@16: (forward-line 1) (setq beg (point)) yuuji@16: (end-of-line) (setq end (point)) yuuji@16: (set-buffer hfbuf) yuuji@16: (goto-char (point-min)) yuuji@16: (insert YaTeX-help-delimiter command "\n") yuuji@16: (insert-buffer-substring dbuf beg end) yuuji@16: (insert "\n") yuuji@16: (set-buffer dbuf) yuuji@16: (re-search-forward (concat "^" (regexp-quote YaTeX-help-description))) yuuji@16: (forward-line 1) yuuji@16: (setq beg (point)) yuuji@16: (setq end (point-max)) yuuji@16: (set-buffer hfbuf) yuuji@16: (insert-buffer-substring dbuf beg end) yuuji@16: (insert "\n\n") yuuji@16: (forward-line -1) yuuji@16: (delete-blank-lines) yuuji@16: (let ((make-backup-files t)) yuuji@16: (basic-save-buffer)) yuuji@23: (bury-buffer hfbuf) yuuji@80: (setq YaTeX-help-entries (cons (list command) YaTeX-help-entries)))) yuuji@80: yuuji@16: (defun YaTeX-help-prepare-entry (command help-file) yuuji@16: "Read help description on COMMAND and add it to HELP-FILE." yuuji@16: (let ((buf (get-buffer-create "**Description**")) yuuji@16: (conf (current-window-configuration))) yuuji@23: (YaTeX-showup-buffer yuuji@354: buf 'YaTeX-showup-buffer-bottom-most t) yuuji@16: (make-local-variable 'YaTeX-help-file-current) yuuji@16: (make-local-variable 'YaTeX-help-command-current) yuuji@16: (make-local-variable 'YaTeX-help-saved-config) yuuji@16: (setq YaTeX-help-file-current help-file yuuji@16: YaTeX-help-command-current command yuuji@16: YaTeX-help-saved-config conf yuuji@16: mode-name "Text" yuuji@16: major-mode 'text) yuuji@16: (erase-buffer) yuuji@16: (insert YaTeX-help-synopsis "\n\n" YaTeX-help-description "\n\n") yuuji@16: (define-key YaTeX-help-entry-map "\r" 'YaTeX-help-newline) yuuji@16: (use-local-map YaTeX-help-entry-map) yuuji@16: (message yuuji@16: (cond (YaTeX-japan "入力を終えたら . のみ入力してRET") yuuji@80: (t "Type only `.' and RET to exit."))))) yuuji@80: yuuji@16: (defun YaTeX-enrich-help (command) yuuji@16: "Add the COMMAND's help to help file." yuuji@16: (if (y-or-n-p (format "No help on `%s'. Create help?" command)) yuuji@16: (YaTeX-help-prepare-entry yuuji@16: command yuuji@16: (if (y-or-n-p "Add help to global documentation?") yuuji@80: YaTeX-help-file YaTeX-help-file-private)))) yuuji@16: yuuji@16: (defun YaTeX-help-sort (&optional help-file) yuuji@16: "Sort help file HELP-FILE. yuuji@16: If HELP-FILE is nil or called interactively, sort current buffer yuuji@16: as a help file." yuuji@16: (interactive) yuuji@16: (if help-file (set-buffer (find-file-noselect help-file))) yuuji@16: (sort-regexp-fields yuuji@80: nil "\\(\\sw+\\)\\([^]+\\|\\s'\\)" "\\1" (point-min) (point-max))) yuuji@16: yuuji@23: (defun YaTeX-apropos-file (keyword help-file &optional append) yuuji@23: (let ((hb (find-file-noselect help-file)) yuuji@23: (ab (get-buffer-create YaTeX-help-buffer)) yuuji@23: (sw (selected-window)) yuuji@23: (head (concat "^" (regexp-quote YaTeX-help-delimiter))) yuuji@23: pt command) yuuji@354: (YaTeX-showup-buffer ab 'YaTeX-showup-buffer-bottom-most) yuuji@23: (select-window (get-buffer-window ab)) yuuji@23: (set-buffer ab) ;assertion yuuji@80: (setq buffer-read-only nil) yuuji@23: (or append (erase-buffer)) yuuji@23: (set-buffer hb) yuuji@23: (goto-char (point-min)) yuuji@23: (while (re-search-forward keyword nil t) yuuji@23: (setq pt (point)) yuuji@23: (re-search-backward head nil t) yuuji@23: (setq command (buffer-substring (match-end 0) (point-end-of-line))) yuuji@23: (switch-to-buffer ab) yuuji@23: (goto-char (point-max)) yuuji@23: (insert-char ?- (1- (window-width))) yuuji@23: (insert (format "\n<<%s>>\n" command)) yuuji@23: (YaTeX-refer-help command help-file t) ;append mode yuuji@80: (setq buffer-read-only nil) yuuji@23: (set-buffer hb) yuuji@23: (goto-char pt) yuuji@23: (if (re-search-forward head nil 1) yuuji@23: (goto-char (1- (match-beginning 0))))) yuuji@80: (setq buffer-read-only t) yuuji@23: (select-window sw) yuuji@80: pt)) yuuji@23: yuuji@23: ;;;###autoload yuuji@23: (defun YaTeX-apropos (key) yuuji@23: (interactive "sLaTeX apropos (regexp): ") yuuji@58: (if (string= "" key) (error "Nothing to show")) yuuji@80: (setq YaTeX-help-saved-config (current-window-configuration)) yuuji@23: (or (YaTeX-apropos-file key YaTeX-help-file) yuuji@23: (YaTeX-apropos-file key YaTeX-help-file-private t) yuuji@80: (message "No matches found."))) yuuji@23: yuuji@16: ;;;###autoload yuuji@546: (defun YaTeX-help (&optional macro ref-only) yuuji@339: "Show help buffer of LaTeX/TeX commands or macros. yuuji@546: Optional argument MACRO, if supplied, is directly selected to keyword. yuuji@546: Non-nil for optional second argument REF-ONLY inhibits call enrich-help yuuji@546: for non-interactive use." yuuji@16: (interactive) yuuji@16: (let (p beg end command) yuuji@16: (save-excursion yuuji@16: (if (looking-at YaTeX-ec-regexp) yuuji@16: (goto-char (match-end 0))) yuuji@16: (setq p (point)) ;remember current position. yuuji@16: (cond yuuji@339: (macro nil) yuuji@16: ((YaTeX-on-begin-end-p) yuuji@16: ;;if on \begin or \end, extract its environment. yuuji@16: (setq command yuuji@16: (cond ((match-beginning 1) yuuji@16: (buffer-substring (match-beginning 1) (match-end 1))) yuuji@16: ((match-beginning 2) yuuji@16: (buffer-substring (match-beginning 2) (match-end 2)))))) yuuji@16: ((search-backward YaTeX-ec (point-beginning-of-line) t) yuuji@16: (goto-char (setq beg (match-end 0))) yuuji@23: (re-search-forward YaTeX-TeX-token-regexp (point-end-of-line) t) yuuji@16: (setq end (point)) yuuji@16: (if (and (<= beg p) (<= p end)) yuuji@16: (setq command (buffer-substring beg end))))) yuuji@16: (if (or (string= command "begin") (string= command "end")) yuuji@16: (progn yuuji@16: (search-forward "{" (point-end-of-line)) yuuji@16: (setq beg (point)) yuuji@16: (search-forward "}" (point-end-of-line)) yuuji@16: (setq command (buffer-substring beg (match-beginning 0))))) yuuji@16: (setq command yuuji@339: (or macro yuuji@339: (completing-read yuuji@339: "Describe (La)TeX command: " yuuji@339: YaTeX-help-entries nil nil command))));end excursion yuuji@339: yuuji@80: (setq YaTeX-help-saved-config (current-window-configuration)) yuuji@16: (or (YaTeX-refer-help command YaTeX-help-file) yuuji@16: (YaTeX-refer-help command YaTeX-help-file-private) yuuji@546: ref-only yuuji@80: (YaTeX-enrich-help command))))