Latexをwordなどに貼り付けやすい形に変換して編集edit-indirect-region-latex

wordなどに貼り付けるとエラーになるLatex、例えば

```edit-indirect-region-latex-example.tex
Equation (\ref{eq:aa}) and (\ref{eq:bb}) shows an results.
X shows an results\cite{AAa,Bb}.
$x=234$
Prolog is logical languages.
\verb|<Opinions>|
hello
\scheme|(setq q 2)|
hello
\lstinline$category$
xxxxxxxxxxxxx
\footnote{[1234]}
\footnote{\url{http://example.com/}}
Newton method find an solutions.
```
を

```edit-indirect-region-latex-example.txt
Equation ([26530]) and ([98699]) shows an results.
X shows an results[96852].
[11593]
[78137] is logical languages.
[26630]
hello
[39322]
hello
[99858]
xxxxxxxxxxxx
[21335]
[16739]
[89154] method find an solutions.
```

のような形に変換してからwordになどに張り付けて文章校閲や文法チェックできるようにする
[edit-indirect-region](http://emacs.rubikitch.com/edit-indirect/)
の拡張を作った。プログラム本体は以下の edit-indirect-region-latex と edit-indirect-latex 関数

```edit-indirect-region-latex.el


(require 'ht) 

(defun ht-valueds (table valued)
  "Retuen keys which has value"
  (let (results)
    (maphash
     (lambda (key value)
       (when (equal value valued)
	 (push key results)))
       table)
    results))

(defun ht-valued (table valued)
  "Retuen key which has value"
  (car (ht-valueds table valued)))


(defun ht-gen-key (table)  
  "generate identilcal key"
  (let* ((keynum (+ 10000 (random 90000)))
         (key (concat "[" (number-to-string keynum) "]")))
    (if (ht-get table key)
	(ht-gen-key (table))
      key)))

(defun ht-store-value! (table value)
  "store value with identical new key. and return new identical key"
  (let ((key (ht-valued table value)))
    (if key key
      (let ((key-new (ht-gen-key table)))
	(ht-set! table key-new value)
	key-new))))

(defun edit-indirect-region-latex-ht-resister (word &optional key)
  (when (or (not (boundp 'edit-indirect-region-latex-ht))
            (not (ht? edit-indirect-region-latex-ht)) )
    (setq edit-indirect-region-latex-ht (ht-create)))
  (if key
      (if (ht-get edit-indirect-region-latex-ht key)
          key
        (progn (ht-set! edit-indirect-region-latex-ht key word)
               key))
      (ht-store-value! edit-indirect-region-latex-ht word)))


(defun edit-indirect-region-latex-prepossess ()
  (beginning-of-buffer)
  (while (re-search-forward "[\[0-9\]+]" nil t)
    (let ((key (buffer-substring-no-properties (match-beginning 0) (match-end 0) )))
      (edit-indirect-region-latex-ht-resister key key))))

(defun edit-indirect-region-latex-after-creation-hook ()
     (ht-each
      (lambda (key value)
        (beginning-of-buffer)
        (while (search-forward value nil t) (replace-match key)) )
      edit-indirect-region-latex-ht)
     
     (mapcar
      (lambda (pat)
        (beginning-of-buffer)
        (while (re-search-forward pat nil t)
          (let ((key (edit-indirect-region-latex-ht-resister
                  (buffer-substring-no-properties (match-beginning 0) (match-end 0)))))
            (replace-match key))))
      (list
       "\\(\\\\\\(verb\\|scheme\\|lstinline\\)|[^|]*|\\|\\\\\\(cite\\|label\\|ref\\|url\\|lstinline\\){[^}]*}\\|\\\\lstinline\\$[^\\$]*\\$\\)"  ;;;1st step
       "\\$[^\\$]*\\$" ;;2nd
       "\\\\footnote{[^}]*}"  ;; 3rd
       ))
     
     ;;(write-file "/tmp/indirect.md" nil)

     ;;you can insert initial spell check etc. for example
     ;;(langtool-check-buffer)
     ;;(redpen-paragraph)

     )

(defun edit-indirect-region-latex-after-commit (beg end)
  (dotimes (number 3 value)
        (setq value number)
        (mapcar
         (lambda (key)
           (beginning-of-buffer)
           (while (search-forward key nil  t)
             (replace-match (ht-get edit-indirect-region-latex-ht key) 'fixed-case 'literal)  ))
         (ht-keys edit-indirect-region-latex-ht)   ))  )


(require 'edit-indirect)

(defun edit-indirect-region-wrap-latex (s e o)
  (save-excursion (edit-indirect-region-latex-prepossess))
  (setq edit-indirect-after-creation-hook #'edit-indirect-region-latex-after-creation-hook)
  (setq edit-indirect-after-commit-functions (list  #'edit-indirect-region-latex-after-commit))
  (edit-indirect-region s e o)
  )

(defun edit-indirect-latex (s e)
  (interactive "r")
  (let ((pt (point)))
    (cond ((region-active-p)
           (edit-indirect-region-wrap-latex s e t)
           ;(markdown-mode)
           )
          ((progn
             (save-excursion
               (setq s (re-search-backward "\\(\\\\begin{[^{}]+}\\|\\\\end{[^{}]+}\\)" nil t)
                     region-start (match-end 0))
               (goto-char pt)
               (setq e (re-search-forward "\\(\\\\begin{[^{}]+}\\|\\\\end{[^{}]+}\\)" nil t)
                     region-end (match-beginning 0))
               (print (list s pt (point) e ))
               (and s e (< s pt e))))
           (edit-indirect-region-wrap-latex region-start region-end t)
           ;(markdown-mode)
           )
          (t (user-error "No region")))))


  
(defun edit-indirect-region-latex (beg end &optional display-buffer)
  (interactive
   (if (or (use-region-p) (not transient-mark-mode))
       (prog1 (list (region-beginning) (region-end) t)
         (deactivate-mark))
     (user-error "No region")))

  (setq edit-indirect-after-creation-hook #'edit-indirect-region-latex-after-creation-hook)
  (setq edit-indirect-after-commit-functions (list  #'edit-indirect-region-latex-after-commit))
  
  (let ((buffer (edit-indirect--get-edit-indirect-buffer beg end)))
    (when display-buffer
      (with-current-buffer buffer
        (setq-local edit-indirect--should-quit-window t))
      (select-window (display-buffer buffer)))
    buffer))

```

(ついでにhtの拡張も少ししている)

PrologやNewtonなどのマイナーな専門用語で校閲ソフトにスペルミスと言われる用語は、変換辞書edit-indirect-region-latex-htに事前に登録しておくと、一括して変換してくれる

```edit-indirect-region-latex-preprocess-example.el
(edit-indirect-region-latex-ht-resister "Prolog")
(edit-indirect-region-latex-ht-resister "Newton")
```

なおコメントアウトされている
;;(write-file "/tmp/indirect.md" nil)
を有効にするとgrammarlyのファイルアップロード機能が使えて操作が少しだけ楽になる


(setq edit-indirect-after-creation-hook ...)
(setq edit-indirect-after-commit-functions ...)
がオリジナルのedit-indirect-regionに追加されているだけなので、これをグローバル スコープで定義してオリジナルのedit-indirect-regionを呼んでも同じ動作になると思う。

ついでにいちいち範囲選択しないで前後範囲を自動設定する
edit-indirect-latex
を[edit-indirect-dwim](http://emacs.rubikitch.com/edit-indirect/)参考にして作った．

Latexの文章間違いチェックの方法としては
[pandocでmarkdownへ変換してからtextlintに入力する処理をmakefileに追加しておく方法](http://rentwi.textfile.org/?743702479393587200s)
などもあるようだが、pandocはtikzがあると動かないようなので、これを作った。