]> rtime.felk.cvut.cz Git - pes-rpp/rpp-test-sw.git/blob - rpp-test-sw/commands/doc/help-format.el
doc: Improve Emacs macros for editing command help texts
[pes-rpp/rpp-test-sw.git] / rpp-test-sw / commands / doc / help-format.el
1 ;;; help-format.el --- Macros for editing and formating multiline strings in C
2
3 ;; Copyright (C) 2013  Michal Sojka
4
5 ;; Author: Michal Sojka <sojkam1@fel.cvut.cz>
6 ;; Keywords:
7
8 ;; This program is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation, either version 3 of the License, or
11 ;; (at your option) any later version.
12
13 ;; This program is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;;; Commentary:
22
23 ;; To use these macros, evaluate this buffer in emacs (M-x
24 ;; eval-buffer), open a C file, run M-x wsh/edit-setup, locate a
25 ;; multiline text and press C-c C-c to edit the text in text mode.
26 ;; When you are done, press C-c C-c again and you will be switched
27 ;; back to the full C file.
28
29 ;;; Code:
30
31 (defun wsh/quoted-line-regexp (&optional ending)
32   (concat "^[ \t]*\"\\(.*\\)\\\\n\"[ \t]*" (cond ((not ending) "$")
33                                                  ((equal ending ",") ","))))
34
35 (defun wsh/strip-quotes-and-newline (beg end)
36   (interactive "r")
37   (save-excursion
38     (save-restriction
39       (narrow-to-region beg end)
40       (goto-char (point-min))
41       (while (re-search-forward (wsh/quoted-line-regexp) nil t)
42         (replace-match "\\1")))))
43
44 (defun wsh/add-quotes-and-newline (beg end)
45   (interactive "r")
46   (save-excursion
47     (save-restriction
48       (narrow-to-region beg end)
49       (goto-char (point-max))
50       (when (bolp)
51         (delete-backward-char 1))
52       (goto-char (point-min))
53       (while (re-search-forward "^\\(.*\\)$" nil t)
54         (replace-match "\"\\1\\\\n\"" t)))))
55
56 (defun wsh/escape-quotes (beg end)
57   (interactive "r")
58   (save-excursion
59     (save-restriction
60       (narrow-to-region beg end)
61       (goto-char (point-min))
62       (while (re-search-forward "\"" nil t)
63         (replace-match "\\\\\"" t)))))
64
65 (defun wsh/unescape-quotes (beg end)
66   (interactive "r")
67   (save-excursion
68     (save-restriction
69       (narrow-to-region beg end)
70       (goto-char (point-min))
71       (while (re-search-forward "\\\\\"" nil t)
72         (replace-match "\"" t)))))
73
74 (defun wsh/edit-multiline-string (beg end)
75   (interactive "r")
76   (let ((text (buffer-substring beg end))
77         (text-buffer (get-buffer-create (concat (buffer-name) "-multiline.txt")))
78         (pos (- (point) beg))
79         (c-buffer (current-buffer))
80         (beg-marker (copy-marker beg))
81         (end-marker (copy-marker end)))
82     (switch-to-buffer text-buffer)
83     (delete-region (point-min) (point-max))
84     (insert text)
85     (goto-char pos)
86     (wsh/strip-quotes-and-newline (point-min) (point-max))
87     (wsh/unescape-quotes (point-min) (point-max))
88     (markdown-mode)
89     (save-excursion
90       (goto-char (point-max))
91       (skip-chars-backward "\n")
92       (let ((eols-at-eof (- (point-max) (point))))
93         (when (eq eols-at-eof 0)
94           (insert "\n"))))
95     (flyspell-mode 1)
96     (ispell-change-dictionary "american")
97     (flyspell-buffer)
98     (make-local-variable 'wsh/c-buffer)
99     (make-local-variable 'wsh/c-region)
100     (setq wsh/c-buffer c-buffer)
101     (setq wsh/c-region (cons beg-marker end-marker))
102     (local-set-key (kbd "C-c C-c") 'wsh/finish-editing)
103     (local-set-key (kbd "C-c x") 'wsh/eval-examples)
104     (message "Edit the text; when done press C-c C-c")))
105
106 (defun wsh/finish-editing ()
107   (interactive)
108   (delete-trailing-whitespace)
109   (let ((pos (point-marker))
110         (min (point-min-marker))
111         (text-buffer (current-buffer))
112         (beg (car wsh/c-region))
113         (end (cdr wsh/c-region)))
114     (goto-char (point-max))
115     (skip-chars-backward " \t\n\r\f\v")
116     (delete-region (point) (point-max))
117     (wsh/escape-quotes (point-min) (point-max))
118     (wsh/add-quotes-and-newline (point-min) (point-max))
119     (let ((text (buffer-string)))
120       (switch-to-buffer wsh/c-buffer)
121       (delete-region beg end)
122       (goto-char beg)
123       (insert text)
124       (setq end (point))
125       (goto-char (+ beg (- pos min)))
126       (indent-region beg end)
127       (kill-buffer text-buffer))))
128
129 (defun wsh/at-multiline-string ()
130   (save-excursion
131     (beginning-of-line)
132     (or (looking-at (wsh/quoted-line-regexp))
133         (looking-at (wsh/quoted-line-regexp ",")))))
134
135 (defun wsh/find-and-edit-multiline-string ()
136   (interactive)
137   (cond ((not (wsh/at-multiline-string))
138          (message "No multiline text found at current line"))
139         (t
140          (let (beg end)
141            (save-excursion
142              (beginning-of-line)
143              (when (looking-at (wsh/quoted-line-regexp ","))
144                (beginning-of-line 0))
145              (while (looking-at (wsh/quoted-line-regexp))
146                (beginning-of-line 0))
147              (beginning-of-line 2)
148              (setq beg (point))
149              (while (looking-at (wsh/quoted-line-regexp))
150                (beginning-of-line 2))
151              (if (looking-at (wsh/quoted-line-regexp ","))
152                  (goto-char (1- (match-end 0)))
153                (end-of-line 0))
154              (setq end (point)))
155            (wsh/edit-multiline-string beg end)))))
156
157 (defun wsh/add-angle-brackets ()
158   (interactive)
159   (save-excursion
160     (forward-word 1)
161     (insert ">")
162     (backward-word 1)
163     (insert "<")))
164
165 (defvar wsh/serial-dev "/dev/ttyUSB1")
166 (defvar wsh/serial-process nil)
167
168 (defun wsh/eval-command (command)
169   (unless (and wsh/serial-process
170                (process-live-p wsh/serial-process))
171     (setq wsh/serial-process (make-serial-process :port wsh/serial-dev :speed 115200 :coding '(utf-8-dos . utf-8))))
172   (let* ((buf (process-buffer wsh/serial-process))
173          (beg (marker-position (process-mark wsh/serial-process)))
174          (pos beg)
175          (end nil)
176          (finished nil))
177     (with-temp-message (format "Evaluating '%s'" command)
178       (process-send-string wsh/serial-process (concat command "\n"))
179       (with-current-buffer buf
180         (while (not finished)
181           (if (or (not (equal pos (marker-position (process-mark wsh/serial-process))))
182                   (accept-process-output wsh/serial-process 10.0))
183               (progn
184                 (setq pos (marker-position (process-mark wsh/serial-process)))
185                 (goto-char beg)
186                 (when (re-search-forward "^-->" nil t)
187                   (setq end (match-beginning 0))
188                   (setq finished t)))
189             (progn
190               (message "Serial line timeout")
191               (setq finished t))))
192         (when end
193            (buffer-substring beg end))))))
194
195 (defun wsh/eval-examples (&optional arg)
196   "Evaluates one or all examples. Without a C-u prefix, only a
197   single example is evaluated, otherwise all examples are
198   evaluated."
199   (interactive "P")
200   (let ((prompt "^\\([ \t]+\\)--> \\(.*\\)")
201         (first t)
202         (all (not (equal arg nil))))
203     (while (and (re-search-forward prompt nil t)
204                 (or first all))
205       (setq first nil)
206       (let* ((prefix (match-string 1))
207              (command (match-string 2))
208              (beg (match-beginning 2))
209              (reply (wsh/eval-command command)))
210         (if reply
211             (progn
212               (beginning-of-line 2)
213               (while (and (looking-at " +")
214                           (not (looking-at prompt)))
215                 (beginning-of-line 2))
216               (backward-char)
217               (delete-region beg (point))
218               (insert reply)
219               (save-restriction
220                 (narrow-to-region beg (point))
221                 (goto-char (point-max))
222                 (skip-chars-backward " \t\n\r\f\v")
223                 (delete-region (point) (point-max))
224                 (goto-char (point-min))
225                 (beginning-of-line 2)
226                 (while (not (eobp))
227                   (insert prefix)
228                   (beginning-of-line 2))))
229           (message "No reply"))))))
230
231
232
233 (defun wsh/edit-setup ()
234   (interactive)
235   (local-set-key (kbd "C-c C-c") 'wsh/find-and-edit-multiline-string)
236   (local-set-key (kbd "C-c <") 'wsh/add-angle-brackets))
237
238 ;; (add-hook 'c-mode-hook 'wsh/edit-setup)
239 ;; (remove-hook 'c-mode-hook 'wsh/edit-setup)
240
241 (provide 'help-format)
242 ;;; help-format.el ends here