123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- ;;; multistring.el --- editing multiline strings.
- ;; Copyright (C) 2000, 2006 Free Software Foundation, Inc.
- ;;;; This library is free software; you can redistribute it and/or
- ;;;; modify it under the terms of the GNU Lesser General Public
- ;;;; License as published by the Free Software Foundation; either
- ;;;; version 3 of the License, or (at your option) any later version.
- ;;;;
- ;;;; This library 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
- ;;;; Lesser General Public License for more details.
- ;;;;
- ;;;; You should have received a copy of the GNU Lesser General Public
- ;;;; License along with this library; if not, write to the Free
- ;;;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- ;;;; 02111-1307 USA
- ;;; Author: Mikael Djurfeldt <djurfeldt@nada.kth.se>
- ;;; Commentary:
- ;; Commands for editing multiline ANSI C compatible string literals.
- ;;; Code:
- (defun ms-ansify-string (arg)
- "Convert a string literal spanning multiple lines into multiple literals.
- With no argument, convert the single string at point to multiple strings.
- With an argument, convert multiple strings to a single one.
- ANSI C doesn't allow a string literal to span multiple lines. This
- function makes editing of multiline strings easier.
- The programmer can edit a string spanning multiple lines and then use
- this function to convert it into multiple literals representing the
- original string through the ANSI C string concatenation feature:
- \"A string consisting of
- multiple
- lines.\"
- is converted into
- \"A string consisting of\n\"
- \"multiple\n\"
- \"lines\""
- (interactive "*P")
- (save-excursion
- (let (beg end)
- (save-restriction
- (ms-narrow-canonicalize-ansi-c-string)
- (if (not arg)
- (ms-break-string))
- (setq beg (point-min))
- (setq end (point-max)))
- (if (not arg)
- (c-indent-region beg end)))))
- (defun ms-pack-region (from to &optional unpack-flag)
- "Pack paragraphs into single lines and remove one newline after paragraphs.
- With no argument, do the conversion.
- With an argument, do the reverse.
- When doing the reverse conversion, \\[fill-region] is used to break up
- the text into multiple lines."
- (interactive "*r\nP")
- (save-excursion
- (save-restriction
- (narrow-to-region from to)
- (if (not unpack-flag)
- (ms-pack-buffer)
- (ms-unpack-buffer)))))
- (defun ms-pack-ansify-string (arg)
- "Pack text in a string literal and convert into multiple literals.
- With no argument, do the conversion.
- With an argument, do the reverse.
- This command has the combined effect of \\[ms-pack-region] and
- \\[ms-ansify-string]. It is typically used if you want to store
- entire paragraphs without newlines in an ANSI C literal, but want to
- split it into multiple literals in order for the program text to look
- sensible. Using the reverse command, you can \"unpack\" the text,
- edit it and repack the text using the forward conversion."
- (interactive "*P")
- (save-excursion
- (let (beg end)
- (save-restriction
- (ms-narrow-canonicalize-ansi-c-string)
- (if (not arg)
- (ms-break-string " " "" "\\n")
- (ms-unpack-buffer))
- (setq beg (point-min))
- (setq end (point-max)))
- (if (not arg)
- (c-indent-region beg end)))))
- (defun ms-pack-buffer ()
- "Pack paragraphs into single lines and remove one newline after paragraphs."
- (interactive "*")
- (goto-char (point-min))
- (skip-chars-forward "^\n")
- (while (not (eobp))
- (delete-char 1)
- (skip-chars-forward "\n")
- (skip-chars-forward "^\n")))
- (defun ms-unpack-buffer ()
- "Break single lines into paragraphs and add an extra newline between each."
- (interactive "*")
- (goto-char (point-min))
- (skip-chars-forward "^\n")
- (while (not (eobp))
- (insert ?\n)
- (skip-chars-forward "\n")
- (skip-chars-forward "^\n"))
- (fill-region (point-min) (point-max) nil t))
- (defconst ms-whitespace " \t\n")
- (defconst ms-string-beginning "\"")
- (defconst ms-string-end "\\(\\\\*\\)\"")
- (defconst ms-quoted-newline "\\(\\\\*\\)\\(\\\\n\\)")
- (defun ms-in-string-p ()
- (eq (c-in-literal) 'string))
- (defun ms-narrow-canonicalize-ansi-c-string ()
- ;; Find and check reference point
- (cond ((ms-in-string-p))
- ((eq (char-after) ?\") (forward-char))
- (t (error "Not in string.")))
- (set-mark (point))
- ;; Find beginning
- (ms-beginning-of-string)
- (let ((beg (point)))
- ;; Extend string backwards
- (while (ms-extend-backwards)
- (setq beg (point)))
- (goto-char (mark))
- ;; Find end
- (ms-end-of-string)
- (let ((end (point)))
- ;; Extend string forwards
- (while (ms-extend-forwards)
- (setq end (point)))
- ;; Narrow
- (narrow-to-region beg end)
- ;; Convert \n into explicit newlines
- (ms-convert-quoted-newlines))))
- (defun ms-beginning-of-string ()
- (let ((pos (search-backward ms-string-beginning nil t)))
- (while (and pos
- (char-before)
- (eq (char-before) ?\\))
- (setq pos (search-backward ms-string-beginning nil t)))
- (if pos
- (progn
- (forward-char)
- (1+ pos)))))
- (defun ms-extend-backwards ()
- (let ((end (point)))
- (backward-char)
- (skip-chars-backward ms-whitespace)
- (if (eq (char-before) ?\")
- (progn
- (backward-char)
- (delete-region (point) end)
- (ms-beginning-of-string)))))
- (defun ms-end-of-string ()
- (let ((pos (search-forward-regexp ms-string-end nil t)))
- (while (and pos (= (logand (- (match-end 1) (match-beginning 1)) 1) 1))
- (setq pos (search-forward-regexp ms-string-end nil t)))
- (if pos
- (progn
- (backward-char)
- (match-end 1)))))
- (defun ms-extend-forwards ()
- (let ((start (point)))
- (forward-char)
- (skip-chars-forward ms-whitespace)
- (if (eq (char-after) ?\")
- (progn
- (forward-char)
- (delete-region start (point))
- (ms-end-of-string)))))
- (defun ms-convert-quoted-newlines ()
- (goto-char (point-min))
- (while (search-forward-regexp ms-quoted-newline nil t)
- (if (= (logand (- (match-end 1) (match-beginning 1)) 1) 0)
- (replace-match "\n" nil t nil 2))))
- (defun ms-break-string (&optional single-term multi-term-1 multi-term-n)
- (let ((single-term (or single-term "\\n"))
- (multi-term-1 (or multi-term-1 "\\n"))
- (multi-term-n (or multi-term-n "\\n")))
- (goto-char (point-min))
- (skip-chars-forward "^\n")
- (while (not (eobp))
- (delete-char 1)
- (if (not (eq (char-after) ?\n))
- (insert single-term)
- (insert multi-term-1)
- (while (eq (char-after) ?\n)
- (delete-char 1)
- (insert multi-term-n)))
- (insert "\"\n\"")
- (skip-chars-forward "^\n"))))
- (eval-after-load "cc-mode"
- (progn
- (define-key c-mode-base-map "\C-ca" 'ms-ansify-string)
- (define-key c-mode-base-map "\C-cd" 'ms-pack-ansify-string)
- ))
|