;;; help-format.el --- Macros for editing and formating multiline strings in C ;; Copyright (C) 2013 Michal Sojka ;; Author: Michal Sojka ;; Keywords: ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; To use these macros, evaluate this buffer in emacs (M-x ;; eval-buffer), open a C file, run M-x wsh/edit-setup, locate a ;; multiline text and press C-c C-c to edit the text in text mode. ;; When you are done, press C-c C-c again and you will be switched ;; back to the full C file. ;;; Code: (defun wsh/quoted-line-regexp (&optional ending) (concat "^[ \t]*\"\\(.*\\)\\\\n\"[ \t]*" (cond ((not ending) "$") ((equal ending ",") ",")))) (defun wsh/strip-quotes-and-newline (beg end) (interactive "r") (save-excursion (save-restriction (narrow-to-region beg end) (goto-char (point-min)) (while (re-search-forward (wsh/quoted-line-regexp) nil t) (replace-match "\\1"))))) (defun wsh/add-quotes-and-newline (beg end) (interactive "r") (save-excursion (save-restriction (narrow-to-region beg end) (goto-char (point-max)) (when (bolp) (delete-backward-char 1)) (goto-char (point-min)) (while (re-search-forward "^\\(.*\\)$" nil t) (replace-match "\"\\1\\\\n\"" t))))) (defun wsh/edit-multiline-string (beg end) (interactive "r") (let ((text (buffer-substring beg end)) (text-buffer (get-buffer-create (concat (buffer-name) "-multiline.txt"))) (pos (- (point) beg)) (c-buffer (current-buffer)) (beg-marker (copy-marker beg)) (end-marker (copy-marker end))) (switch-to-buffer text-buffer) (delete-region (point-min) (point-max)) (insert text) (goto-char pos) (wsh/strip-quotes-and-newline (point-min) (point-max)) (text-mode) (save-excursion (goto-char (point-max)) (skip-chars-backward "\n") (let ((eols-at-eof (- (point-max) (point)))) (when (eq eols-at-eof 0) (insert "\n")))) (flyspell-mode 1) (ispell-change-dictionary "american") (flyspell-buffer) (make-local-variable 'wsh/c-buffer) (make-local-variable 'wsh/c-region) (setq wsh/c-buffer c-buffer) (setq wsh/c-region (cons beg-marker end-marker)) (local-set-key (kbd "C-c C-c") 'wsh/finish-editing) (local-set-key (kbd "C-c x") 'wsh/eval-examples) (message "Edit the text; when done press C-c C-c"))) (defun wsh/finish-editing () (interactive) (delete-trailing-whitespace) (let ((pos (point-marker)) (min (point-min-marker)) (text-buffer (current-buffer)) (beg (car wsh/c-region)) (end (cdr wsh/c-region))) (goto-char (point-max)) (skip-chars-backward " \t\n\r\f\v") (delete-region (point) (point-max)) (wsh/add-quotes-and-newline (point-min) (point-max)) (let ((text (buffer-string))) (switch-to-buffer wsh/c-buffer) (delete-region beg end) (goto-char beg) (insert text) (setq end (point)) (goto-char (+ beg (- pos min))) (indent-region beg end) (kill-buffer text-buffer)))) (defun wsh/at-multiline-string () (save-excursion (beginning-of-line) (or (looking-at (wsh/quoted-line-regexp)) (looking-at (wsh/quoted-line-regexp ","))))) (defun wsh/find-and-edit-multiline-string () (interactive) (cond ((not (wsh/at-multiline-string)) (message "No multiline text found at current line")) (t (let (beg end) (save-excursion (beginning-of-line) (when (looking-at (wsh/quoted-line-regexp ",")) (beginning-of-line 0)) (while (looking-at (wsh/quoted-line-regexp)) (beginning-of-line 0)) (beginning-of-line 2) (setq beg (point)) (while (looking-at (wsh/quoted-line-regexp)) (beginning-of-line 2)) (if (looking-at (wsh/quoted-line-regexp ",")) (goto-char (1- (match-end 0))) (end-of-line 0)) (setq end (point))) (wsh/edit-multiline-string beg end))))) (defun wsh/add-angle-brackets () (interactive) (save-excursion (forward-word 1) (insert ">") (backward-word 1) (insert "<"))) (defvar wsh/serial-dev "/dev/ttyUSB1") (defvar wsh/serial-process nil) (defun wsh/eval-command (command) (unless (and wsh/serial-process (process-live-p wsh/serial-process)) (setq wsh/serial-process (make-serial-process :port wsh/serial-dev :speed 115200 :coding '(utf-8-dos . utf-8)))) (let* ((buf (process-buffer wsh/serial-process)) (beg (marker-position (process-mark wsh/serial-process))) (pos beg) (end nil) (finished nil)) (with-temp-message (format "Evaluating '%s'" command) (process-send-string wsh/serial-process (concat command "\n")) (with-current-buffer buf (while (not finished) (if (or (not (equal pos (marker-position (process-mark wsh/serial-process)))) (accept-process-output wsh/serial-process 10.0)) (progn (setq pos (marker-position (process-mark wsh/serial-process))) (goto-char beg) (when (re-search-forward "^-->" nil t) (setq end (match-beginning 0)) (setq finished t))) (progn (message "Serial line timeout") (setq finished t)))) (when end (buffer-substring beg end)))))) (defun wsh/eval-examples (&optional arg) "Evaluates one or all examples. Without a C-u prefix, only a single example is evaluated, otherwise all examples are evaluated." (interactive "P") (let ((prompt "^\\([ \t]+\\)--> \\(.*\\)") (first t) (all (not (equal arg nil)))) (while (and (re-search-forward prompt nil t) (or first all)) (setq first nil) (let* ((prefix (match-string 1)) (command (match-string 2)) (beg (match-beginning 2)) (reply (wsh/eval-command command))) (if reply (progn (beginning-of-line 2) (while (and (looking-at " +") (not (looking-at prompt))) (beginning-of-line 2)) (backward-char) (delete-region beg (point)) (insert reply) (save-restriction (narrow-to-region beg (point)) (goto-char (point-max)) (skip-chars-backward " \t\n\r\f\v") (delete-region (point) (point-max)) (goto-char (point-min)) (beginning-of-line 2) (while (not (eobp)) (insert prefix) (beginning-of-line 2)))) (message "No reply")))))) (defun wsh/edit-setup () (interactive) (local-set-key (kbd "C-c C-c") 'wsh/find-and-edit-multiline-string) (local-set-key (kbd "C-c <") 'wsh/add-angle-brackets)) ;; (add-hook 'c-mode-hook 'wsh/edit-setup) ;; (remove-hook 'c-mode-hook 'wsh/edit-setup) (provide 'help-format) ;;; help-format.el ends here