File: Line_Filter.bsh

package info (click to toggle)
jedit 5.3.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 14,252 kB
  • ctags: 11,190
  • sloc: java: 98,480; xml: 94,070; makefile: 52; sh: 42; cpp: 6; python: 6
file content (377 lines) | stat: -rw-r--r-- 16,403 bytes parent folder | download | duplicates (7)
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();