1 ;;; help-format.el --- Macros for editing and formating multiline strings in C
3 ;; Copyright (C) 2013 Michal Sojka
5 ;; Author: Michal Sojka <sojkam1@fel.cvut.cz>
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.
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.
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/>.
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.
31 (defun wsh/quoted-line-regexp (&optional ending)
32 (concat "^[ \t]*\"\\(.*\\)\\\\n\"[ \t]*" (cond ((not ending) "$")
33 ((equal ending ",") ","))))
35 (defun wsh/strip-quotes-and-newline (beg end)
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")))))
44 (defun wsh/add-quotes-and-newline (beg end)
48 (narrow-to-region beg end)
49 (goto-char (point-max))
51 (delete-backward-char 1))
52 (goto-char (point-min))
53 (while (re-search-forward "^\\(.*\\)$" nil t)
54 (replace-match "\"\\1\\\\n\"" t)))))
56 (defun wsh/escape-quotes (beg end)
60 (narrow-to-region beg end)
61 (goto-char (point-min))
62 (while (re-search-forward "\"" nil t)
63 (replace-match "\\\\\"" t)))))
65 (defun wsh/unescape-quotes (beg end)
69 (narrow-to-region beg end)
70 (goto-char (point-min))
71 (while (re-search-forward "\\\\\"" nil t)
72 (replace-match "\"" t)))))
74 (defun wsh/edit-multiline-string (beg end)
76 (let ((text (buffer-substring beg end))
77 (text-buffer (get-buffer-create (concat (buffer-name) "-multiline.txt")))
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))
86 (wsh/strip-quotes-and-newline (point-min) (point-max))
87 (wsh/unescape-quotes (point-min) (point-max))
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)
96 (ispell-change-dictionary "american")
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")))
106 (defun wsh/finish-editing ()
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)
125 (goto-char (+ beg (- pos min)))
126 (indent-region beg end)
127 (kill-buffer text-buffer))))
129 (defun wsh/at-multiline-string ()
132 (or (looking-at (wsh/quoted-line-regexp))
133 (looking-at (wsh/quoted-line-regexp ",")))))
135 (defun wsh/find-and-edit-multiline-string ()
137 (cond ((not (wsh/at-multiline-string))
138 (message "No multiline text found at current 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)
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)))
155 (wsh/edit-multiline-string beg end)))))
157 (defun wsh/add-angle-brackets ()
165 (defvar wsh/serial-dev "/dev/ttyUSB1")
166 (defvar wsh/serial-process nil)
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)))
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))
184 (setq pos (marker-position (process-mark wsh/serial-process)))
186 (when (re-search-forward "^-->" nil t)
187 (setq end (match-beginning 0))
190 (message "Serial line timeout")
193 (buffer-substring beg end))))))
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
200 (let ((prompt "^\\([ \t]+\\)--> \\(.*\\)")
202 (all (not (equal arg nil))))
203 (while (and (re-search-forward prompt nil t)
206 (let* ((prefix (match-string 1))
207 (command (match-string 2))
208 (beg (match-beginning 2))
209 (reply (wsh/eval-command command)))
212 (beginning-of-line 2)
213 (while (and (looking-at " +")
214 (not (looking-at prompt)))
215 (beginning-of-line 2))
217 (delete-region beg (point))
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)
228 (beginning-of-line 2))))
229 (message "No reply"))))))
233 (defun wsh/edit-setup ()
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))
238 ;; (add-hook 'c-mode-hook 'wsh/edit-setup)
239 ;; (remove-hook 'c-mode-hook 'wsh/edit-setup)
241 (provide 'help-format)
242 ;;; help-format.el ends here