1/* 2 * Display_abbreviations.bsh - a BeanShell macro script for the 3 * jEdit text editor - displays all defined abbreviations 4 * Copyright (C) 2001 John Gellene 5 * email: jgellene@nyc.rr.com 6 * http://community.jedit.org 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 2 11 * of the License, or any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 * 22 * $Id: Display_Abbreviations.bsh 23920 2015-05-22 08:03:45Z ezust $ 23 * 24 * requires JDK 1.2, jEdit3.0 25 * 26 * Notes on use: 27 * 28 * This macro will display a sorted list of all defined abbreviations 29 * in a dialog. A combo box lists all eidting modes for which abbreviations 30 * are currently defined, as well as the "global" abbreviation set. 31 * 32 * Pressing a letter key will cause the table to scroll to the first row 33 * with a label beginning with the letter (or the imeediately preceding row if 34 * no item begins with that letter). The table is read-only; the dialog is 35 * dismissed by clicking "OK" or pressing Esc or Enter. 36 * 37 * The macro has two global constants defined to permit customization of the 38 * script's behavior. STARTING_SET contains the name of the abbreviation set 39 * that will be first displayed. If the other variable, EXCLUDE_EMPTY_SETS, 40 * is set to true, the drop-down menu and the results of clicking the 41 * "Write All" button will only include abbreviations sets containing 42 * entries. 43 * 44 * The table being displayed at any time is not updated if changes are made to 45 * the abbreviation set in the "Global Options" dialog. If EXCLUDE_EMPTY_SETS 46 * is set to true, the drop-down list will not by updated. Clsoing the dialog 47 * and running the macro again will obtain current data. 48 * 49 * 50 * Checked for jEdit 4.0 API 51 * 52 */ 53 54import javax.swing.table.*; 55 56//Localization 57final static String AbbreviationLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.Abbreviation.label", "Abbreviation"); 58final static String ExpansionLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.Expansion.label", "Expansion"); 59final static String AbbreviationSetLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.AbbreviationSet.label", "Abbreviation set:"); 60final static String CloseLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.Close.label", "Close"); 61final static String WriteSetLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.WriteSet.label", "Write set"); 62final static String WriteAllLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.WriteAll.label", "Write all"); 63final static String AbbreviationListLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.AbbreviationList.label", "Abbreviation list"); 64final static String CallingWTTNBLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.CallingWTTNB.label", "calling writeTableToNewBuffer for"); 65final static String SizeVectorLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.SizeVector.label", "size of vector ="); 66final static String jEditAbbreviationTableLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.jEditAbbreviationTable.label", "jEdit Abbreviation Table"); 67final static String AbbreviationExpansionLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.AbbreviationExpansion.label", "Abbreviation Expansion"); 68final static String NoAbbreviationsLabel = jEdit.getProperty("macro.rs.DisplayAbbreviations.NoAbbreviations.label", "<< No abbreviations >>"); 69 70/* 71 * getActiveSets() 72 * This returns an array with the names of the abbreviation sets 73 * (beginning with "global"). If EXCLUDE_EMPTY_SETS is set to true, only sets 74 * with abbreviations are included. 75 */ 76Object[] getActiveSets() 77{ 78 Mode[] modes = jEdit.getModes(); 79 Vector setVector = new Vector(modes.length + 1); 80 setVector.addElement("global"); 81 for(int i = 0; i < modes.length; i++) 82 { 83 String name = modes[i].getName(); 84 if(EXCLUDE_EMPTY_SETS) 85 { 86 Hashtable ht = Abbrevs.getModeAbbrevs().get(name); 87 if( ht == null || ht.isEmpty()) 88 continue; 89 } 90 setVector.addElement(name); 91 } 92 Object[] sets = new Object[setVector.size()]; 93 setVector.copyInto(sets); 94 return sets; 95} 96 97/* 98 * makeTableDataForMode() 99 * This extracts the abbreviations from the named set. If extraction is 100 * successful, the vector named by the first parameter will have its 101 * elements removed before the variable is set to the newly created vector. 102 */ 103Vector makeTableDataForMode(Vector v, String name) 104{ 105 if(name.equals(currentSet)) 106 return v; 107 Hashtable htable = null; 108 if(name.equals("global")) 109 { 110 htable = Abbrevs.getGlobalAbbrevs(); 111 } 112 else 113 { 114 Hashtable modeAbbrevs = Abbrevs.getModeAbbrevs(); 115 htable = modeAbbrevs.get(name); 116 } 117 if(htable != null) 118 { 119 Enumeration abbrevEnum = htable.keys(); 120 Enumeration expandEnum = htable.elements(); 121 Vector newData = new Vector(20, 5); 122 while(abbrevEnum.hasMoreElements()) 123 { 124 Vector row = new Vector(2); 125 row.addElement(abbrevEnum.nextElement()); 126 row.addElement(expandEnum.nextElement()); 127 newData.addElement(row); 128 } 129 Collections.sort(newData, 130 new StandardUtilities.StringCompare(true)); 131 currentSet = name; 132 if( v != null) 133 v.removeAllElements(); 134 v = newData; 135 } 136 return v; 137} 138 139/* 140 * showAbbrevs() 141 * This is the macro's principal method. 142 */ 143void showAbbrevs() 144{ 145 currentSet = null; 146 data = makeTableDataForMode(data, STARTING_SET); 147 if(data.size() == 0) 148 { 149 STARTING_SET = "global"; 150 data = makeTableDataForMode(data, STARTING_SET); 151 } 152 Vector columnNames = new Vector(2); 153 columnNames.addElement(new String(AbbreviationLabel)); 154 columnNames.addElement(new String(ExpansionLabel)); 155 table = new JTable(); 156 table.setRowHeight(GUIUtilities.defaultRowHeight()); 157 table.setModel(new DefaultTableModel(data, columnNames)); 158 table.setRowSelectionAllowed(true); 159 /* The next line prevents the table from being edited. 160 * The normal approach in Java would be to subclass the TableModel 161 * associated with the JTable and define TableModel.isCellEditable() 162 * to return false. However, BeanShell does not allow conventional 163 * class creation, and the desired behavior cannot be achieved using 164 * its scripted object feature. 165 */ 166 table.setDefaultEditor(Object.class, null); 167 if(table.getRowCount() != 0) 168 table.setRowSelectionInterval(0,0); 169 tablePane = new JScrollPane(table); 170 tablePane.setPreferredSize(new Dimension(450, 300)); 171 172 combo = new JComboBox(abbrevSets); 173 Dimension dim = combo.getPreferredSize(); 174 dim.width = Math.max(dim.width, 120); 175 combo.setPreferredSize(dim); 176 combo.setSelectedItem(STARTING_SET); 177 comboPanel = new JPanel(new FlowLayout()); 178 comboPanel.add(new JLabel(AbbreviationSetLabel)); 179 comboPanel.add(combo); 180 181 close = new JButton(CloseLabel); 182 write_set = new JButton(WriteSetLabel); 183 write_all = new JButton(WriteAllLabel); 184 buttonPanel = new JPanel(new FlowLayout()); 185 buttonPanel.add(write_set); 186 buttonPanel.add(write_all); 187 buttonPanel.add(close); 188 189 close.addActionListener(this); 190 write_set.addActionListener(this); 191 write_all.addActionListener(this); 192 combo.addActionListener(this); 193 void actionPerformed(e) 194 { 195 Component source = e.getSource(); 196 if(source == close) 197 dialog.hide(); 198 else if(source == write_set) 199 writeTableToNewBuffer(super.data, (String)combo.getSelectedItem()); 200 else if(source == write_all) 201 writeAllToNewBuffer(); 202 else if(source == combo) 203 { 204 super.data = makeTableDataForMode(super.data, (String)combo.getSelectedItem()); 205 if( data != null) 206 { 207 DefaultTableModel model = (DefaultTableModel)table.getModel(); 208 model.setDataVector(super.data, columnNames); 209 } 210 } 211 } 212 213 // workaround required by Swing bug; scheduled to be fixed in JDK 1.4 214 combo.getComponent(0).addKeyListener(this); 215 table.addKeyListener(this); 216 write_set.addKeyListener(this); 217 write_all.addKeyListener(this); 218 close.addKeyListener(this); 219 void keyPressed(e) 220 { 221 if(combo.isPopupVisible()) return; 222 if(e.getKeyCode() == KeyEvent.VK_ESCAPE || 223 e.getKeyCode() == KeyEvent.VK_ENTER) 224 { 225 dialog.hide(); 226 } 227 else if(e.getSource() != combo) 228 { 229 char ch = e.getKeyChar(); 230 if(Character.isLetter(ch)) 231 { 232 e.consume(); 233 row = findFirstItem(ch); 234 /* The next few lines set the last visible row 235 * of the table so that you can look ahead of 236 * the selected row. 237 */ 238 visibleRows = 239 table.getVisibleRect().height / table.getRowHeight(); 240 oldRow = table.getSelectedRow(); 241 table.setRowSelectionInterval(row,row); 242 if (visibleRows > 5 && row - oldRow > visibleRows - 3) 243 { 244 row = Math.min( super.data.size() - 1, row + 3); 245 } 246 table.scrollRectToVisible(table.getCellRect(row,0,true)); 247 } 248 } 249 } 250 /* 251 * Having these members of KeyListener implemented as no-ops 252 * will speedup execution. Otherwise BeanShell throws an 253 * exception that jEdit handles internally. 254 * Under BeanShell 1.2, implementation of these methods is 255 * required. 256 */ 257 void keyReleased(e) {} 258 void keyTyped(e) {} 259 260 /* 261 * findFirstItem() 262 * A simple linear search for the table entry that begins with the 263 * given letter. It returns the first row with an entry beginning with 264 * the letter, or the immdediately preceding row if there is no match 265 * on the letter. 266 * 267 */ 268 int findFirstItem(char ch) 269 { 270 ch = Character.toUpperCase(ch); 271 int row = 0; 272 for(int i = 0; i < data.size(); ++i) 273 { 274 String name = ((Vector)data.elementAt(i)).elementAt(0); 275 char ch_test = Character.toUpperCase(name.charAt(0)); 276 if( ch_test > ch) break; 277 else 278 { 279 row = i; 280 if( ch_test == ch) break; 281 } 282 } 283 return row; 284 } 285 286 title = AbbreviationListLabel; 287 dialog = new JDialog(view, title, false); 288 c = dialog.getContentPane(); 289 c.add(tablePane, "Center"); 290 c.add(comboPanel, "North"); 291 c.add(buttonPanel, "South"); 292 dialog.getRootPane().setDefaultButton(close); 293 dialog.pack(); 294 dialog.setLocationRelativeTo(view); 295 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 296 dialog.show(); 297} 298 299/* 300 * The next four methods deal with writing the abbreviation sets to a new 301 * text buffer. 302 */ 303void writeTableToNewBuffer(Vector v, String setName) 304{ 305 Log.log(Log.DEBUG, BeanShell.class, 306 CallingWTTNBLabel + " " + setName); 307 writeHeader(); 308 Log.log(Log.DEBUG, BeanShell.class, SizeVectorLabel + " " 309 + String.valueOf(v.size())); 310 writeSet(v, setName); 311} 312 313// saved the currentSet and deleted it for makeTableDataForMode()-invocation 314// because otherwise the currently in the Dialog displayed set has no abbrevs 315// in the output written to the buffer. 316void writeAllToNewBuffer() 317{ 318 writeHeader(); 319 Vector vOut = new Vector(); 320 savedCurrentSet = currentSet; 321 for( int i = 0; i < abbrevSets.length; ++i) 322 { 323 currentSet = null; 324 String setName = (String)abbrevSets[i]; 325 vOut = makeTableDataForMode(vOut, setName); 326 writeSet(vOut, setName); 327 textArea.setSelectedText("\n\n"); 328 } 329 currentSet = savedCurrentSet; 330} 331 332void writeHeader() 333{ 334 jEdit.newFile(view); 335 textArea.setSelectedText(jEditAbbreviationTableLabel + "\n\n"); 336} 337 338/* 339 * This truncates the definition text at 17 characters and the expansion text 340 * at 58. 341 */ 342void writeSet(Vector v, String setName) 343{ 344 textArea.setSelectedText(AbbreviationSetLabel + " " + setName + "\n"); 345 textArea.setSelectedText(AbbreviationExpansionLabel + "\n\n"); 346 if(v.size() == 0) 347 textArea.setSelectedText(NoAbbreviationsLabel + "\n"); 348 else for( int i = 0; i < v.size(); ++i) 349 { 350 StringBuffer sb = new StringBuffer(85); 351 spaceString = " "; 352 char[] space = spaceString.toCharArray(); 353 Vector row = (Vector)v.elementAt(i); 354 abbrevName = (String)row.elementAt(0); 355 if(abbrevName == null) continue; 356 if(abbrevName.length() > 17) 357 abbrevName = abbrevName.substring(0, 14) + "..."; 358 sb.append(abbrevName); 359 sb.append(space, 0, 18 - (abbrevName.length())); 360 expansion = row.elementAt(1); 361 if(shortcut1 != null) 362 { 363 if(expansion.length() > 58) 364 expansion = expansion.substring(0, 55) + "..."; 365 sb.append(expansion); 366 } 367 sb.append('\n'); 368 textArea.setSelectedText(sb.toString()); 369 } 370} 371 372 373/* 374 * main routine, including definition of global variables 375 */ 376STARTING_SET = "global"; 377EXCLUDE_EMPTY_SETS = true; 378abbrevSets = getActiveSets(); 379currentSet = null; 380Vector data = new Vector(20, 5); 381showAbbrevs(); 382 383/* 384 Macro index data (in DocBook format) 385 386<listitem> 387 <para><filename>Display_Abbreviations.bsh</filename></para> 388 <abstract><para> 389 Displays the abbreviations registered for each of jEdit's 390 editing modes. 391 </para></abstract> 392 <para> 393 The macro provides a read-only view of the abbreviations 394 contained in the <quote>Abbreviations</quote> option pane. Pressing 395 a letter key will scroll the table to the first entry beginning with 396 that letter. A further option is provided to write a selected mode's 397 abbreviations or all abbreviations in a text buffer for printing as a 398 reference. Notes in the source code listing point out some display options 399 that are configured by modifying global variables. 400 </para> 401</listitem> 402 403*/ 404 405// end Display_Abbreviations.bsh 406 407