1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
|
/**
* LineFilter.bsh - a BeanShell macro for the jEdit 4.3 text editor
* that filters lines of a buffer due to a provided regular expression.
*
* :folding=indent:collapseFolds=1:
*
* The filter actions are: - Write to a new buffer (grep-like).
* - Remove from current buffer.
* The filter is applied on: - matching lines, or
* - not matching lines
* The filter works on: - the whole buffer, or
* - the selection, if it spans over mor than one line
*
*
* Copyright (C) 2008 Robert Schwenn
*
* History:
* 08.08.2005 1.0 initial Version
* 29.01.2008 1.2 - changed regexp to java.util.regex
* - consolidated gui and code
* 01.06.2008 1.3 - "Remove from current buffer" is only available,
* if the buffer is editable and nor multiple or
* rectangular selection is present.
* - Input field is pre-filled with the selection.
*
*
* This macro is based on the following macros:
* - Retain_Or_Remove_Lines.bsh by Jia Zhiming
* - Grep_Buffer.bsh, Reverse_Grep_Buffer.bsh by Robert Fletcher
*
* 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 2
* of the License, or 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.
*/
import java.util.regex.*;
import javax.swing.border.*;
// constants used in more than one methods
final String DELETE_COMMAND = "delete";
final String WRITE_TO_NEW_BUFFER_COMMAND = "writeToNewBuffer";
// GUI
void LineFilterDialog() {
//
// constants
final static String processNotMatchedCommand = "notMatching";
final static String processMatchedCommand = "matching";
// Common Dialog Labels
final static String PROPERTY_COMMON_OK = jEdit.getProperty("common.ok");
final static String PROPERTY_COMMON_CANCEL = jEdit.getProperty("common.cancel");
final static String NotEditableMessage = jEdit.getProperty("macro.rs.general.ErrorNotEditableDialog.message", "Buffer is not editable");
final static String MultipleSelectionMessage = jEdit.getProperty("macro.rs.LineFilter.MultipleSelection.message", "Multiple selection is not supported");
final static String BlockSelectionMessage = jEdit.getProperty("macro.rs.LineFilter.BlockSelection.message", "Rectangular selection is not supported");
final static String DeleteActionDisabledMessage = jEdit.getProperty("macro.rs.LineFilter.DeleteActionDisabled.message", "Delete is not available");
// Special Dialog Labels
final static String MainDialogTitle = jEdit.getProperty("macro.rs.LineFilter.MainDialog.title", "LineFilter");
final static String ignoreCaseCheckBoxText = jEdit.getProperty("macro.rs.LineFilter.ignoreCaseCheckBox.label", "Ignore case");
final static String regexpPanelBorderTitle = jEdit.getProperty("macro.rs.LineFilter.regexpPanelBorder.title", "Pattern to compare (Regular Expression)");
final static String processModeRadioButtonMatching = jEdit.getProperty("macro.rs.LineFilter.processModeRadioButtonMatching.label", "Matching");
final static String processModeRadioButtonNotMatching = jEdit.getProperty("macro.rs.LineFilter.processModeRadioButtonNotMatching.label", "Not Matching");
final static String processModeOptionPanelBorderTitle = jEdit.getProperty("macro.rs.LineFilter.processModeOptionPanelBorder.title", "Lines");
final static String actionModeRadioButtonWrite = jEdit.getProperty("macro.rs.LineFilter.actionModeRadioButtonWrite.label", "Write to new buffer");
final static String actionModeRadioButtonDelete = jEdit.getProperty("macro.rs.LineFilter.actionModeRadioButtonDelete.label", "Delete");
final static String actionModeOptionPanelBorderTitle = jEdit.getProperty("macro.rs.LineFilter.actionModeOptionPanelBorder.title", "Action");
//
// *** Eventhandler *********************************************************
// Button oder ENTER key pressed
public void actionPerformed(ActionEvent e) {
//Macros.message(view, "actionPerformed: ''" + e.getActionCommand() + "'");
boolean processMatchedLines;
if (e.getActionCommand() != PROPERTY_COMMON_CANCEL) {
// evaluate status of radio buttons
if (processModeButtonGroup.getSelection().getActionCommand() == processMatchedCommand) {
processMatchedLines = true;
} else {
processMatchedLines = false;
}
//String actionModeCommand = e.getactionModeCommand();
String actionModeCommand = actionModeButtonGroup.getSelection().getActionCommand();
String regExp = regexpTextfield.getText();
boolean ignoreCase = ignoreCaseCheckBox.isSelected();
regexpTextfield.addCurrentToHistory();
if (processText(regExp, ignoreCase, processMatchedLines, actionModeCommand)) dialog.dispose();
} else {
dialog.dispose();
}
}
public void keyPressed(KeyEvent e) {
//Macros.message(view, "keyPressed..." + e.getKeyCode());
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
//Macros.message(view, "ESCAPE pressed.");
dialog.setVisible(false);
dialog.dispose();
}
}
// to avoid BeanShell throwing exceptions each time one of these events occur.
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) { }
// ****************************************************************************
//
// prepare dialog
dialog = new JDialog(view, MainDialogTitle, true);
content = new JPanel(new BorderLayout());
content.setBorder(new EmptyBorder(8, 8, 8, 8));
dialog.setContentPane(content);
// prepare Buttons and button panel
JButton okButton = new JButton(PROPERTY_COMMON_OK);
JButton cancelButton = new JButton(PROPERTY_COMMON_CANCEL);
dialog.getRootPane().setDefaultButton(okButton);
buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.X_AXIS));
buttonPanel.setBorder(new EmptyBorder(10, 10, 0, 10));
buttonPanel.add(Box.createGlue());
buttonPanel.add(cancelButton);
buttonPanel.add(Box.createHorizontalStrut(15));
buttonPanel.add(okButton);
buttonPanel.add(Box.createGlue());
// prepare regexp input frame
regexpTextfield = new HistoryTextField("macro.rs.LineFilter.regexp");
regexpTextfield.setActionCommand(dialog.getRootPane().getDefaultButton().getActionCommand());
ignoreCaseCheckBox = new JCheckBox(ignoreCaseCheckBoxText, false);
regexpPanel = new JPanel(new GridLayout(2, 1, 5, 8));
regexpPanel.add(regexpTextfield);
regexpPanel.add(ignoreCaseCheckBox);
regexpPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(" " + regexpPanelBorderTitle + " "),
BorderFactory.createEmptyBorder(0,0,0,0)));
// prepare process mode option panel
ButtonGroup processModeButtonGroup = new ButtonGroup();
JRadioButton[] processModeRadioButtons = new JRadioButton[2];
processModeRadioButtons[0] = new JRadioButton(processModeRadioButtonMatching);
processModeRadioButtons[1] = new JRadioButton(processModeRadioButtonNotMatching);
processModeRadioButtons[0].setActionCommand(processMatchedCommand);
processModeRadioButtons[1].setActionCommand(processNotMatchedCommand);
processModeRadioButtons[0].setSelected(true);
processModeButtonGroup.add(processModeRadioButtons[0]);
processModeButtonGroup.add(processModeRadioButtons[1]);
processModeOptionPanel = new JPanel(new GridLayout(2, 1, 0, 0));
processModeOptionPanel.add(processModeRadioButtons[0]);
processModeOptionPanel.add(processModeRadioButtons[1]);
processModeOptionPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(" " + processModeOptionPanelBorderTitle + " "),
BorderFactory.createEmptyBorder(0,0,0,0)));
// prepare action mode option panel
ButtonGroup actionModeButtonGroup = new ButtonGroup();
JRadioButton[] actionModeRadioButtons = new JRadioButton[2];
actionModeRadioButtons[0] = new JRadioButton(actionModeRadioButtonWrite);
actionModeRadioButtons[1] = new JRadioButton(actionModeRadioButtonDelete);
actionModeRadioButtons[0].setActionCommand(WRITE_TO_NEW_BUFFER_COMMAND);
actionModeRadioButtons[1].setActionCommand(DELETE_COMMAND);
actionModeRadioButtons[0].setSelected(true);
actionModeButtonGroup.add(actionModeRadioButtons[0]);
actionModeButtonGroup.add(actionModeRadioButtons[1]);
actionModeOptionPanel = new JPanel(new GridLayout(2, 1, 0, 0));
actionModeOptionPanel.add(actionModeRadioButtons[0]);
actionModeOptionPanel.add(actionModeRadioButtons[1]);
actionModeOptionPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder(" " + actionModeOptionPanelBorderTitle + " "),
BorderFactory.createEmptyBorder(0,0,0,0)));
// place panels at dialog
content.add(regexpPanel, BorderLayout.NORTH);
content.add(processModeOptionPanel, BorderLayout.WEST);
content.add(actionModeOptionPanel, BorderLayout.EAST);
content.add(buttonPanel, BorderLayout.SOUTH);
//
// add event listeners to components
okButton.addActionListener(this);
cancelButton.addActionListener(this);
regexpTextfield.addActionListener(this);
okButton.addKeyListener(this);
cancelButton.addKeyListener(this);
regexpTextfield.addKeyListener(this);
ignoreCaseCheckBox.addKeyListener(this);
processModeRadioButtons[0].addKeyListener(this);
processModeRadioButtons[1].addKeyListener(this);
actionModeRadioButtons[0].addKeyListener(this);
actionModeRadioButtons[1].addKeyListener(this);
//
// change GUI environment-dependent
Selection[] selection = textArea.getSelection();
// pre-fill input field with selection
if (selection.length != 0) {
if (selection[0].getStartLine() == selection[0].getEndLine()) {
String SelectedText = textArea.getSelectedText(selection[0]);
regexpTextfield.setText(SelectedText);
}
}
// availability of delete action is conditioned:
delete_ok = true;
if (! buffer.isEditable()) {
delete_ok = false;
Msg = NotEditableMessage;
}
if (selection.length > 1) {
// multiple selection present!
delete_ok = false;
Msg = MultipleSelectionMessage;
} else if (selection.length == 1) {
if ((textArea.getSelectedLines().length > 1) && (! (selection[0] instanceof Selection.Range))) {
// single selection consists of more than one line, but is not of range type.
delete_ok = false;
Msg = BlockSelectionMessage;
}
}
if (! delete_ok) {
actionModeRadioButtons[1].setEnabled(false);
view.getStatus().setMessageAndClear(MainDialogTitle + ": " + DeleteActionDisabledMessage + " (" + Msg + ")");
}
//
// start dialog
dialog.pack();
dialog.setLocationRelativeTo(view);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
// do the job
boolean processText(String regexpString, boolean ignoreCase, boolean processMatchedLines, String actionModeCommand) {
// returns false, if regular expression is invalid, else true.
// debug
//Macros.message(view, "processText: regexpString = ''" + regexpString + "'"
// + "'\nprocessMatchedLines = " + processMatchedLines
// + "\nactionModeCommand = " + actionModeCommand
// );
// labels
final static String ErrorRegexpDialogTitle = jEdit.getProperty("macro.rs.LineFilter.ErrorRegexpDialog.title", "Invalid regular expression");
final static String ErrorRegexpDialogMessage = jEdit.getProperty("macro.rs.LineFilter.ErrorRegexpDialog.message", "The Regular expression is invalid!");
final static String SummaryDeletedText = jEdit.getProperty("macro.rs.LineFilter.SummaryDeleted.label", "Lines deleted!");
final static String SummaryWrittenText = jEdit.getProperty("macro.rs.LineFilter.SummaryWritten.label", "Lines written to a new buffer.");
// declarations
boolean writeLinesToNewBuffer = false;
boolean deleteLines = false;
boolean lineMatches;
boolean appendLine;
int regexpFlags = 0;
int deletedLines = 0;
int writtenLines = 0;
int sbfLength;
StringBuffer sbf = new StringBuffer();
Pattern pattern = null;
Matcher matcher = null;
// evaluate parameters
if (actionModeCommand == DELETE_COMMAND) deleteLines = true;
if (actionModeCommand == WRITE_TO_NEW_BUFFER_COMMAND) writeLinesToNewBuffer = true;
if (ignoreCase) regexpFlags += Pattern.CASE_INSENSITIVE;
//
// create the regexp matcher
try {
pattern = Pattern.compile(regexpString, regexpFlags);
matcher = pattern.matcher("x");
}
catch (PatternSyntaxException e) {
JOptionPane.showMessageDialog(view, ErrorRegexpDialogMessage, ErrorRegexpDialogTitle, JOptionPane.ERROR_MESSAGE);
return false;
}
//
// get lines to process
int[] lines = textArea.getSelectedLines();
if (lines == null || lines.length <= 1) {
// no selection ==> process all lines
iMax = textArea.getLineCount();
linesSelected = false;
} else {
// selection exist
iMax = lines.length;
linesSelected = true;
}
// parse every line to process
for (int i = 0; i < iMax; i++) {
// get currentLineNr
if (linesSelected) {
currentLineNr = lines[i];
} else {
currentLineNr = i;
}
// compare current line's text against regxep
lineText = textArea.getLineText(currentLineNr);
matcher.reset(lineText);
lineMatches = matcher.find();
appendLine = false;
//Macros.message(view, "matcher.matches() = " + matcher.find());
// collect lines for result (which is a new or the current buffer)
if (writeLinesToNewBuffer) {
appendLine = ((processMatchedLines && lineMatches) || (!processMatchedLines && !lineMatches));
} else if (deleteLines) {
appendLine = ((processMatchedLines && !lineMatches) || (!processMatchedLines && lineMatches));
}
if (appendLine) sbf.append(lineText).append("\n");
}
sbfLength = sbf.length();
// write collected lines (to new or current buffer)
if (deleteLines) {
if (sbfLength > 0) sbf.deleteCharAt(sbfLength - 1);
int oldLineCount = textArea.getLineCount();
if (linesSelected) {
textArea.setSelectedText(sbf.toString());
} else {
textArea.setText(sbf.toString());
}
int newLineCount = textArea.getLineCount();
deletedLines = oldLineCount - newLineCount;
Msg = deletedLines.toString() + " " + SummaryDeletedText;
} else if (writeLinesToNewBuffer) {
if (sbfLength > 0) {
jEdit.newFile(view);
textArea.setSelectedText(sbf.toString());
writtenLines = textArea.getLineCount() - 1;
}
Msg = writtenLines.toString() + " " + SummaryWrittenText;
}
view.getStatus().setMessageAndClear(Msg);
return true;
}
// starting point
LineFilterDialog();
|