219
|
1 ;;;; $Id: string.el,v 1.1 1997/12/02 08:48:41 steve Exp $
|
|
2 ;;;; This file contains some miscellaneous string functions
|
|
3
|
|
4 ;; Copyright (C) 1991-1995 Free Software Foundation
|
|
5
|
|
6 ;; Author: Sebastian Kremer <sk@thp.Uni-Koeln.DE>
|
|
7 ;; Per Cederqvist <ceder@lysator.liu.se>
|
|
8 ;; Inge Wallin <inge@lysator.liu.se>
|
|
9 ;; Maintainer: elib-maintainers@lysator.liu.se
|
|
10 ;; Created: before 9 May 1991
|
|
11 ;; Keywords: extensions, lisp
|
|
12
|
|
13 ;;;; This file is part of the GNU Emacs lisp library, Elib.
|
|
14 ;;;;
|
|
15 ;;;; GNU Elib is free software; you can redistribute it and/or modify
|
|
16 ;;;; it under the terms of the GNU General Public License as published by
|
|
17 ;;;; the Free Software Foundation; either version 2, or (at your option)
|
|
18 ;;;; any later version.
|
|
19 ;;;;
|
|
20 ;;;; GNU Elib is distributed in the hope that it will be useful,
|
|
21 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
22 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
23 ;;;; GNU General Public License for more details.
|
|
24 ;;;;
|
|
25 ;;;; You should have received a copy of the GNU General Public License
|
|
26 ;;;; along with GNU Elib; see the file COPYING. If not, write to
|
|
27 ;;;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
28 ;;;; Boston, MA 02111-1307, USA
|
|
29 ;;;;
|
|
30 ;;;; Author: Sebastian Kremer
|
|
31 ;;;; sk@thp.Uni-Koeln.DE
|
|
32 ;;;;
|
|
33
|
|
34
|
|
35 ;;; Commentary:
|
|
36
|
|
37 ;;;
|
|
38 ;;; This file is part of the elisp library Elib.
|
|
39 ;;; It implements simple generic string functions for use in other
|
|
40 ;;; elisp code: replace regexps in strings, split strings on regexps.
|
|
41 ;;;
|
|
42
|
|
43
|
|
44 ;;; Code:
|
|
45
|
|
46 (require 'queue-m)
|
|
47 (provide 'string)
|
|
48
|
|
49
|
|
50 ;; This function is a near-equivalent of the elisp function replace-match
|
|
51 ;; which work on strings instead of a buffer. The FIXEDCASE parameter
|
|
52 ;; of replace-match is not implemented.
|
|
53
|
|
54 (defun string-replace-match (regexp string newtext &optional literal global)
|
|
55 "Replace first match of REGEXP in STRING with NEWTEXT.
|
|
56 If no match is found, nil is returned instead of the new string.
|
|
57
|
|
58 Optional arg LITERAL non-nil means to take NEWTEXT literally. If LITERAL is
|
|
59 nil, character `\\' is the start of one of the following sequences:
|
|
60 \\\\ will be replaced by a single \\.
|
|
61 \\& will be replaced by the text which matched the regexp.
|
|
62 \\N where N is a number and 1 <= N <= 9, will be replaced
|
|
63 by the Nth subexpression in REGEXP. Subexpressions are grouped
|
|
64 inside \\( \\).
|
|
65
|
|
66 Optional arg GLOBAL means to replace all matches instead of only the first."
|
|
67
|
|
68 (let ((data (match-data)))
|
|
69 (unwind-protect
|
|
70
|
|
71 (if global
|
|
72 (let ((result "")
|
|
73 (start 0)
|
|
74 matchbeginning
|
|
75 matchend)
|
|
76 (while (string-match regexp string start)
|
|
77 (setq matchbeginning (match-beginning 0)
|
|
78 matchend (match-end 0)
|
|
79 result (concat result
|
|
80 (substring string start matchbeginning)
|
|
81 (if literal
|
|
82 newtext
|
|
83 (elib-string-expand-newtext string
|
|
84 newtext )))
|
|
85 start matchend))
|
|
86
|
|
87 (if matchbeginning ; matched at least once
|
|
88 (concat result (substring string start))
|
|
89 nil))
|
|
90
|
|
91 ;; not GLOBAL
|
|
92 (if (not (string-match regexp string 0))
|
|
93 nil
|
|
94 (concat (substring string 0 (match-beginning 0))
|
|
95 (if literal newtext (elib-string-expand-newtext string
|
|
96 newtext ))
|
|
97 (substring string (match-end 0)))))
|
|
98 (store-match-data data))))
|
|
99
|
|
100
|
|
101 (defun elib-string-expand-newtext (string newtext)
|
|
102 ;; Expand \& and \1..\9 (referring to STRING) in NEWTEXT.
|
|
103 ;; Uses match data and fluid vars `newtext', `string'.
|
|
104 ;; Note that in Emacs 18 match data are clipped to current buffer
|
|
105 ;; size...so the buffer should better not be smaller than STRING.
|
|
106 (let ((pos 0)
|
|
107 (len (length newtext))
|
|
108 (expanded-newtext ""))
|
|
109 (while (< pos len)
|
|
110 (setq expanded-newtext
|
|
111 (concat expanded-newtext
|
|
112 (let ((c (aref newtext pos)))
|
|
113 (if (= ?\\ c)
|
|
114 (cond ((= ?\& (setq c (aref newtext
|
|
115 (setq pos (1+ pos)))))
|
|
116 (match-string 0 string) )
|
|
117 ((and (>= c ?1)
|
|
118 (<= c ?9))
|
|
119 ;; return empty string if N'th
|
|
120 ;; sub-regexp did not match:
|
|
121 (let ((n (- c ?0)))
|
|
122 (if (match-beginning n)
|
|
123 (substring string
|
|
124 (match-beginning n)
|
|
125 (match-end n))
|
|
126 "")))
|
|
127 (t (char-to-string c)))
|
|
128 (char-to-string c)))))
|
|
129 (setq pos (1+ pos)))
|
|
130 expanded-newtext))
|
|
131
|
|
132
|
|
133 (defun string-split (pattern string &optional limit)
|
|
134 "Splitting on regexp PATTERN, turn string STRING into a list of substrings.
|
|
135 Optional third arg LIMIT (>= 1) is a limit to the length of the
|
|
136 resulting list."
|
|
137
|
|
138 (let* ((data (match-data))
|
|
139 (start (string-match pattern string))
|
|
140 (result-q (queue-create))
|
|
141 (count 1)
|
|
142 (end (if start (match-end 0))) )
|
|
143 (unwind-protect
|
|
144 (progn
|
|
145 (queue-enqueue result-q (substring string 0 start))
|
|
146 (if end ; else nothing left
|
|
147 (while (and (or (not (integerp limit))
|
|
148 (< count limit))
|
|
149 (string-match pattern string end))
|
|
150 (setq start (match-beginning 0)
|
|
151 count (1+ count) )
|
|
152 (queue-enqueue result-q (substring string end start))
|
|
153 (setq end (match-end 0)
|
|
154 start end )))
|
|
155 (if (and (or (not (integerp limit))
|
|
156 (< count limit) )
|
|
157 end) ; else nothing left
|
|
158 (queue-enqueue result-q (substring string end)) )
|
|
159 (queue-all result-q) )
|
|
160 (store-match-data data) )))
|
|
161
|
|
162 ;;; string.el ends here
|