Source code: com/maddyhome/idea/vim/ex/range/SearchRange.java
1 package com.maddyhome.idea.vim.ex.range;
2
3 /*
4 * IdeaVim - A Vim emulator plugin for IntelliJ Idea
5 * Copyright (C) 2003 Rick Maddy
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 import com.intellij.openapi.actionSystem.DataContext;
23 import com.intellij.openapi.diagnostic.Logger;
24 import com.intellij.openapi.editor.Editor;
25 import com.maddyhome.idea.vim.command.Command;
26 import com.maddyhome.idea.vim.group.CommandGroups;
27 import com.maddyhome.idea.vim.helper.EditorHelper;
28 import java.util.ArrayList;
29 import java.util.StringTokenizer;
30
31 /**
32 * Represents a range given by a search pattern. The pattern can be '\\/', '\\?', '\\&', /{pattern}/,
33 * or ?{pattern}?. The last two can be repeated 0 or more times after any of the others.
34 */
35 public class SearchRange extends AbstractRange
36 {
37 /**
38 * Create the pattern range
39 * @param pattern The text of the pattern. Each subpattern must be separated by the nul character (\\u0000)
40 * @param offset The range offset
41 * @param move True if the cursor should be moved
42 */
43 public SearchRange(String pattern, int offset, boolean move)
44 {
45 super(offset, move);
46 setPattern(pattern);
47 }
48
49 /**
50 * Parses the pattern into a list of subpatterns and flags
51 * @param pattern The full search pattern
52 */
53 private void setPattern(String pattern)
54 {
55 logger.debug("pattern=" + pattern);
56 StringTokenizer tok = new StringTokenizer(pattern, "\u0000");
57 while (tok.hasMoreTokens())
58 {
59 String pat = tok.nextToken();
60 if (pat.equals("\\/"))
61 {
62 patterns.add(CommandGroups.getInstance().getSearch().getLastSearch());
63 flags.add(new Integer(Command.FLAG_SEARCH_FWD));
64 }
65 else if (pat.equals("\\?"))
66 {
67 patterns.add(CommandGroups.getInstance().getSearch().getLastSearch());
68 flags.add(new Integer(Command.FLAG_SEARCH_REV));
69 }
70 else if (pat.equals("\\&"))
71 {
72 patterns.add(CommandGroups.getInstance().getSearch().getLastPattern());
73 flags.add(new Integer(Command.FLAG_SEARCH_FWD));
74 }
75 else
76 {
77 if (pat.charAt(0) == '/')
78 {
79 flags.add(new Integer(Command.FLAG_SEARCH_FWD));
80 }
81 else
82 {
83 flags.add(new Integer(Command.FLAG_SEARCH_REV));
84 }
85
86 pat = pat.substring(1);
87 if (pat.charAt(pat.length() - 1) == pat.charAt(0))
88 {
89 pat = pat.substring(0, pat.length() - 1);
90 }
91 patterns.add(pat);
92 }
93 }
94 }
95
96 /**
97 * Gets the line number specified by this range without regard to any offset.
98 * @param editor The editor to get the line for
99 * @param context The data context
100 * @param lastZero True if last line was set to start of file
101 * @return The zero based line number, -1 if the text was not found
102 */
103 protected int getRangeLine(Editor editor, DataContext context, boolean lastZero)
104 {
105 // Each subsequent pattern is searched for starting in the line after the previous search match
106 int line = EditorHelper.getCurrentLogicalLine(editor);
107 int pos = -1;
108 for (int i = 0; i < patterns.size(); i++)
109 {
110 String pattern = (String)patterns.get(i);
111 int flag = ((Integer)flags.get(i)).intValue();
112 if ((flag & Command.FLAG_SEARCH_FWD) != 0 && !lastZero)
113 {
114 pos = CommandGroups.getInstance().getMotion().moveCaretToLineEnd(editor, line, true);
115 }
116 else
117 {
118 pos = CommandGroups.getInstance().getMotion().moveCaretToLineStart(editor, line);
119 }
120
121 pos = CommandGroups.getInstance().getSearch().search(editor, context, pattern, pos, 1, flag);
122 if (pos == -1)
123 {
124 break;
125 }
126 else
127 {
128 line = editor.offsetToLogicalPosition(pos).line;
129 }
130 }
131
132 if (pos != -1)
133 {
134 return line;
135 }
136 else
137 {
138 return -1;
139 }
140 }
141
142 public String toString()
143 {
144 StringBuffer res = new StringBuffer();
145 res.append("SearchRange[");
146 res.append("patterns=");
147 res.append(patterns);
148 res.append(", ");
149 res.append(super.toString());
150 res.append("]");
151
152 return res.toString();
153 }
154
155 private ArrayList patterns = new ArrayList();
156 private ArrayList flags = new ArrayList();
157
158 private static Logger logger = Logger.getInstance(SearchRange.class.getName());
159 }