1 # This file is part of lyx2lyx
2 # -*- coding: utf-8 -*-
3 # Copyright (C) 2002-2010 Dekel Tsur <dekel@lyx.org>,
4 # José Matos <jamatos@lyx.org>, Richard Heck <rgheck@comcast.net>
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 " This modules offer several free functions to help parse lines. "
22 # Utilities for one line
23 def check_token(line, token):
24 """ check_token(line, token) -> bool
26 Return True if token is present in line and is the first element
27 else returns False."""
29 return line[:len(token)] == token
32 def is_nonempty_line(line):
33 """ is_nonempty_line(line) -> bool
35 Return False if line is either empty or it has only whitespaces,
37 return line != " "*len(line)
40 # Utilities for a list of lines
41 def find_token(lines, token, start, end = 0, exact = False):
42 """ find_token(lines, token, start[[, end], exact]) -> int
44 Return the lowest line where token is found, and is the first
45 element, in lines[start, end].
47 If exact is True (default is False), then differences in
48 whitespace are ignored.
50 Return -1 on failure."""
52 if end == 0 or end > len(lines):
55 for i in xrange(start, end):
64 if lines[i][:m] == token:
69 def find_token_exact(lines, token, start, end = 0):
70 return find_token(lines, token, start, end, True)
73 def find_tokens(lines, tokens, start, end = 0, exact = False):
74 """ find_tokens(lines, tokens, start[[, end], exact]) -> int
76 Return the lowest line where one token in tokens is found, and is
77 the first element, in lines[start, end].
79 Return -1 on failure."""
83 for i in xrange(start, end):
93 if lines[i][:len(token)] == token:
98 def find_tokens_exact(lines, tokens, start, end = 0):
99 return find_tokens(lines, tokens, start, end, True)
102 def find_re(lines, rexp, start, end = 0):
103 """ find_token_re(lines, rexp, start[, end]) -> int
105 Return the lowest line where rexp, a regular expression, is found
106 in lines[start, end].
108 Return -1 on failure."""
112 for i in xrange(start, end):
113 if rexp.match(lines[i]):
118 def find_token_backwards(lines, token, start):
119 """ find_token_backwards(lines, token, start) -> int
121 Return the highest line where token is found, and is the first
122 element, in lines[start, end].
124 Return -1 on failure."""
126 for i in xrange(start, -1, -1):
128 if line[:m] == token:
133 def find_tokens_backwards(lines, tokens, start):
134 """ find_tokens_backwards(lines, token, start) -> int
136 Return the highest line where token is found, and is the first
137 element, in lines[end, start].
139 Return -1 on failure."""
140 for i in xrange(start, -1, -1):
143 if line[:len(token)] == token:
148 def get_value(lines, token, start, end = 0, default = ""):
149 """ get_value(lines, token, start[[, end], default]) -> string
151 Find the next line that looks like:
152 token followed by other stuff
153 Returns "followed by other stuff" with leading and trailing
157 i = find_token_exact(lines, token, start, end)
160 l = lines[i].split(None, 1)
166 def get_quoted_value(lines, token, start, end = 0, default = ""):
167 """ get_quoted_value(lines, token, start[[, end], default]) -> string
169 Find the next line that looks like:
170 token "followed by other stuff"
171 Returns "followed by other stuff" with leading and trailing
172 whitespace and quotes removed. If there are no quotes, that is OK too.
173 So use get_value to preserve possible quotes, this one to remove them,
175 Note that we will NOT strip quotes from default!
177 val = get_value(lines, token, start, end, "")
180 return val.strip('"')
183 def del_token(lines, token, start, end):
184 """ del_token(lines, token, start, end) -> int
186 Find the lower line in lines where token is the first element and
189 Returns the number of lines remaining."""
191 k = find_token_exact(lines, token, start, end)
199 def find_beginning_of(lines, i, start_token, end_token):
202 i = find_tokens_backwards(lines, [start_token, end_token], i-1)
205 if check_token(lines[i], end_token):
214 def find_end_of(lines, i, start_token, end_token):
218 i = find_tokens(lines, [end_token, start_token], i+1)
221 if check_token(lines[i], start_token):
230 def find_nonempty_line(lines, start, end = 0):
233 for i in xrange(start, end):
234 if is_nonempty_line(lines[i]):
239 def find_end_of_inset(lines, i):
240 " Find end of inset, where lines[i] is included."
241 return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
244 def find_end_of_layout(lines, i):
245 " Find end of layout, where lines[i] is included."
246 return find_end_of(lines, i, "\\begin_layout", "\\end_layout")
249 def is_in_inset(lines, i, inset):
251 Checks if line i is in an inset of the given type.
252 If so, returns starting and ending lines.
253 Otherwise, returns False.
255 is_in_inset(document.body, i, "\\begin_inset Tabular")
256 returns False unless i is within a table. If it is, then
257 it returns the line on which the table begins and the one
258 on which it ends. Note that this pair will evaulate to
261 will do what you expect.
264 stins = find_token_backwards(lines, inset, i)
267 endins = find_end_of_inset(lines, stins)
268 # note that this includes the notfound case.
271 return (stins, endins)
274 def get_containing_inset(lines, i):
276 Finds out what kind of inset line i is within. Returns a
277 list containing (i) what follows \begin_inset on the the line
278 on which the inset begins, plus the starting and ending line.
279 Returns False on any kind of error or if it isn't in an inset.
281 stins = find_token_backwards(lines, i, "\\begin_inset")
284 endins = find_end_of_inset(lines, stins)
287 inset = get_value(lines, "\\begin_inset", stins)
291 return (inset, stins, endins)
294 def get_containing_layout(lines, i):
296 Finds out what kind of layout line i is within. Returns a
297 list containing (i) what follows \begin_layout on the the line
298 on which the layout begins, plus the starting and ending line.
299 Returns False on any kind of error.
301 stins = find_token_backwards(lines, i, "\\begin_layout")
304 endins = find_end_of_layout(lines, stins)
307 lay = get_value(lines, "\\begin_layout", stins)
311 return (lay, stins, endins)