jEdit應(yīng)用指南【基礎(chǔ)篇】

作者:tedeyang

創(chuàng)作時(shí)間:2005924

 

      jEdit是一個(gè)非常強(qiáng)大和靈活的文本編輯器.java開發(fā)過程中,我一直使用eclipse,UltraEditjEdit.經(jīng)常在它們之間來回切換.因?yàn)?span lang="EN-US" style="FONT-FAMILY: Arial">ultraEdit太簡單,eclipse又太復(fù)雜,所以現(xiàn)在我要介紹的就是簡單又復(fù)雜的jEdit,它將大大加速你的編程,我會(huì)將重點(diǎn)放在其內(nèi)嵌的Beanshell腳本上。

第一章 jEditJava編寫,強(qiáng)大,易用的程序員文本編輯器

以下部分介紹是我從其官方網(wǎng)站翻譯來的:

      jEdit是一個(gè)成熟的,設(shè)計(jì)優(yōu)秀的程序員文本編輯器,已經(jīng)有了7年的開發(fā)歷史。在功能和易用性方面壓倒許多昂貴的開發(fā)工具時(shí),jEditGNU公用許可證(GPL)下發(fā)布成了開源軟件。

jEdit的核心主要由Slava Pestov開發(fā)完成,一支由世界各地的程序員組成的隊(duì)伍正在為jEdit開發(fā)插件(plugin)。

下面是jEdit的幾個(gè)特色:

  • java編寫,所以它可以運(yùn)行在Mac OS X, OS/2, Unix, VMS Windows平臺(tái)上(山顛:java程序員不推薦使用)
  • 內(nèi)建宏語言;可擴(kuò)展的插件體系;目前已經(jīng)有了很多宏和插件.(山顛:內(nèi)建BeanShell腳本語言,通過插件可以支持其他腳本語言.這點(diǎn)是我之所以在這里費(fèi)力的原因 ^_^)
  • 使用jEdit的插件管理器可以下載插件并安裝.(山顛:如果網(wǎng)絡(luò)狀況允許,這個(gè)功能確實(shí)非常好.不過建議想這么干的家伙去sf看看那些插件都是干什么的先,全裝了會(huì)影響性能)
  • 提供超過130總編程語言的自動(dòng)縮進(jìn)和語法高亮.(山顛:很棒.據(jù)我所知,BeanShell的高亮顯示好象只有它支持)
  • 支持UTF8Unicode在內(nèi)的大量字符編碼
  • 代碼折疊
  • 自動(dòng)換行
  • 極高的可配置性和可定制性
  • 所有其他你希望在一個(gè)文本編輯器里找到的功能,不管是基礎(chǔ)性的還是高級(jí)的,你都可以在jEdit中找到.請(qǐng)查看全部功能清單

看看這些截圖,從直觀上感受一下jEdithttp://www.jedit.org/index.php?page=screenshots

是啊,千變?nèi)f化的jEdit。融合VIM,EditPlus,Emacs等編輯器的優(yōu)點(diǎn)于一身。請(qǐng)查看維基百科中的文本編輯器比較。在這個(gè)有些片面(顯然測試的是個(gè)陽春版本,沒有加任何插件)的比較中,jEdit的表現(xiàn)仍然很是搶眼,全面超越它的只有Emacs(這個(gè)超級(jí)難用的程序)。作為一個(gè)Java程序員,我找遍了整個(gè)地球,在苦惱地承認(rèn)自己的智商還不足以輕松學(xué)好EmacsVim后欣喜地發(fā)現(xiàn)了:開源、強(qiáng)大、易用、Java編寫的jEdit正是我要的。
相關(guān):從其他編輯器轉(zhuǎn)移到j(luò)Edit http://community.jedit.org/cgi-bin/TWiki/view/Main/SwitchingToJEdit

 

第二 jEdit的下載、安裝和插件配置

   jEdit的官方主頁是www.jedit.org,目前最高版本是4.3,穩(wěn)定版本是4.2final。因?yàn)橛行┎寮€不支持4.3,因此建議下載jEdit4.2版本。jEdit還需要JDK1.4的支持

NotejEdit的各個(gè)版本都有平臺(tái)獨(dú)立的版本和相應(yīng)平臺(tái)的版本。不過針對(duì)windows用戶,jEdit還提供了一個(gè)啟動(dòng)器jEditLauncher。(目前官方已經(jīng)不提供啟動(dòng)器了,相關(guān)的討論見:http://community.jedit.org/?q=node/view/1411,其實(shí)以前的啟動(dòng)程序還是能用的,下載我使用的啟動(dòng)程序包,釋放到jedit安裝目錄下就行了)

       安裝完jEdit,下一步就是安裝插件。和Eclipse類似,jEdit的插件安裝也有兩種途徑:直接在jEdit中升級(jí)和手工下載插件包。建議選擇直接升級(jí)。

1. 直接升級(jí)。

Plugins->Plugin Manager打開插件管理器,進(jìn)入Install,選擇你想裝的插件,點(diǎn)擊install就可以安裝了。注意,一次安裝不要選中太多插件,否則這個(gè)過程將持續(xù)很長時(shí)間。安裝完成后可以在Plugins->Plugin Options中進(jìn)行配置。

2. 手工安裝

jEdit插件是個(gè)開源項(xiàng)目,見http://sourceforge.net/projects/jedit-plugins/

在官方主頁上也有這些插件的介紹:http://plugins.jedit.org/list.php。仔細(xì)的看看插件的說明,確定你需要的。下載后把壓縮包后解壓縮到jEdit安裝目錄的jars目錄中(確保有jar文件在jars目錄下,如果你下載的是完全版的插件,jars目錄下還會(huì)有個(gè)包含源文件的同名文件夾),之后重啟jEdit。

Note:必備的幾個(gè)美化界面的插件是:Buffer Tabs(類似UltraEdit的標(biāo)簽)、Background(為View――編輯區(qū)添加背景圖片)、LookAndFeel(外觀選擇)。如果有需要,其他插件會(huì)在后續(xù)文章中按用途進(jìn)行介紹。

第三章 Beanshell腳本在jEdit的應(yīng)用

第一節(jié) 強(qiáng)大、簡單、獨(dú)到的宏

在目前的Java IDE領(lǐng)域中,Eclipse是最好的。但jEdit并不是一個(gè)IDE,而是“程序員文本編輯器”。在文本編輯領(lǐng)域,jEdit擁有很多獨(dú)到的優(yōu)勢,其中之一,也是作者最感興趣的部分,就是它的宏——其實(shí)就是Beanshell腳本。內(nèi)嵌的Beanshell引擎能夠直接訪問jEdit的內(nèi)部對(duì)象和API,例如:你可以寫出這樣的宏命令:

buffer.undo(textArea);   //撤銷當(dāng)前buffer的一個(gè)操作

Registers.paste(textArea,'$',false);//粘貼到當(dāng)前文本域

textArea.setSelectedText("    ");//將選定文本設(shè)為“   

textArea.goToNextLine(false);//移動(dòng)光標(biāo)到下一行

Registers.copy(textArea,'$');//copy

textArea.showWordCountDialog();//顯示對(duì)話框,統(tǒng)計(jì)字?jǐn)?shù)

textArea.backspace();//按一下后退鍵

       buffertextArea都是jEdit的內(nèi)部對(duì)象,RegistersjEdit中的寄存器類??梢?span lang="EN-US" style="FONT-FAMILY: Arial">Beanshell腳本具有直接訪問jEdit內(nèi)部資源的能力,這使我們寫出一個(gè)高度自動(dòng)化的宏命令成為可能。
      除了手工編寫宏文件(.bsh文件)外,jEdit也可以錄制宏。 錄制宏有三種途徑:
      1.使用菜單:打開 Macros->Record Macro,進(jìn)行操作,完成時(shí)點(diǎn)擊stop Recording。
      2.使用快捷鍵:開始錄制用c+m c+r,結(jié)束錄制用c+m c+s。(其中c+m c+r表示先按Ctrl+e,再按Ctrl+r,也可以按住Ctrl,然后再接著按m和r鍵)
      3.使用action bar:Ctrl+Enter組合鍵打開action bar,輸入record,按Tab鍵,回車,就開始錄制宏。完成后打開action bar,輸入recording,按tab,回車。
       Note:多種使用方式體現(xiàn)出jEdit強(qiáng)大的操作性;有關(guān)action bar的相關(guān)資料,請(qǐng)查看幫助。
       Note:宏文件必須存放在jedit\macros\目錄或\Documents and Settings\uername\.jedit\macros目錄下,前者是系統(tǒng)宏目錄,后者是用戶宏目錄。

      

第二節(jié) 使用 jEdit中的Beanshell編寫宏

    到了這一步,看來我們又要學(xué)一門新的語言了。“太麻煩了!”,你可能已經(jīng)決定放棄jEdit了。幸好,BeanshellJava陣營的腳本語言,我們基本上不需要什么精力就學(xué)會(huì)怎么在jEdit中使用它——當(dāng)然前提你必須熟悉Java,這就是我在前面推薦Java程序員使用jEdit的原因。

       Beanshell 有腳本語言的特性,如弱類型、閉包等,但同時(shí)也完全兼容Java語法。為了簡便起見,我們這里就象java一樣來寫beanshell,只要記住一點(diǎn):它是解釋執(zhí)行的。更深入的學(xué)習(xí)推薦訪問以下網(wǎng)站:

1.        http://dev.csdn.net/develop/article/15/15090.shtm

2.        http://www-128.ibm.com/developerworks/cn/java/l-beanshell/index.html

3.        官方網(wǎng)站:http://www.beanshell.org

4.        在線教程:http://www.beanshell.org/manual/contents.html

下面通過jEdit自帶的一個(gè)宏文件來看看宏是怎么“煉成”的。
實(shí)例:jEdit 4.2\macros\java\Java_File_Save.bsh

文件源代碼如下:中文部分是添加的注釋

/*
 * Java_File_Save.bsh - a BeanShell macro for saving new java files.
 *
 * Copyright (C) 2004 Nicholas O'Leary nol@deferential.net
 * 
 * :mode=beanshell:tabSize=3:indentSize=3:maxLineLen=0:noTabs=true:
 * :indentOnTab=true:indentOnEnter=true:folding=explicit:collapseFolds=1:
 *
 *
 * Notes:
 *  Only the first 250 lines of the buffer are scanned for a suitable
 *  class or interface declaration.
 *  
 * Changes:
 *  17-May-04: Only scans if the edit mode is either 'java' or the default mode
 *           : Ignores declarations that are in multiline comments
 *  08-Jun-04: If an infinite loop is hit (1000 iterations) in the comment
 *           : parsing, it now opens the default save dialog, rather than
 *           : just returning.
 * $Id: Java_File_Save.bsh,v 1.1 2004/06/26 19:10:58 spestov Exp $
 
*/

//以上是宏作者寫的說明

// Check this is a new file。
// 在jEdit中buffer對(duì)象指向當(dāng)前正在編輯的文件,打開一個(gè)文件,就是在當(dāng)前視圖(view)的textArea中創(chuàng)建一個(gè)buffer
// 在幫助中可以查看這些類的API:對(duì)象buffer: org.gjt.sp.jedit.Buffer,
//                           對(duì)象textArea: org.gjt.sp.jedit.textarea.JEditTextArea
//                           對(duì)象view:    org.gjt.sp.jedit.View
// beanshell能訪問的內(nèi)存中的對(duì)象有view,buffer,textArea,editPane,wm,scriptPath,
// 詳情請(qǐng)看幫助中的 Chapter 13. Macro Basics-->Predefined Variables in BeanShell小節(jié)
if (buffer.isNewFile() && buffer.getPath() != null)
{
   
// Only look further if the mode is 'java', or still the default
   String buffer_mode = buffer.getMode().toString();//編輯模式,jEdit的默認(rèn)編輯模式是text
   if (buffer_mode.equals("java"|| buffer_mode.equals(jEdit.getProperty("buffer.defaultMode","")))
   
{
      String fullpath 
= buffer.getPath();//打開文件的路徑
      VFS vfs = VFSManager.getVFSForPath(fullpath);//根據(jù)路徑生成虛擬文件系統(tǒng)
      
// Split into constituent parts
      String path = vfs.getParentOfPath(fullpath);//獲得所在目錄
      String name = vfs.getFileName(fullpath);//獲得文件名
      
      
// At most, check the first 250 lines - this sounds reasonable to me
      
//以下利用GNU的正則表達(dá)式包檢查代碼,提取出類名(最多檢查250行)
      int maxLine = Math.min(buffer.getLineCount(),250);
      
import gnu.regexp.RE;
      
import gnu.regexp.REMatch;//這樣引入包,jar文件必須能被jEdit找到(只要將jar文件放在jars目錄下)
      
// Build the regex - based on the offical java language spec.
      RE regex = new RE("^\\s*(public|protected|private|static|abstract|final|native|synchronized|transient|volatile|strictfp)?\\s*(class|interface)\\s*([^ {/]*)");
      
int regexMinimum = regex.getMinimumLength();//可能構(gòu)成一次匹配的最小字符數(shù)
      boolean inComment = false;//是否在注釋里
      for(int i=0;i<maxLine;i++)
      
{
         String txt 
= buffer.getLineText(i);//第i行的字符串
         int count = 0;
            
// See if this line has a the start or finish of a multiline comment
         
//確定提取的類名是有效的,不在注釋里
         while (txt.indexOf("/*")!=-1 || txt.indexOf("*/")!=-1)
            
{
                
// A little paranoia on my part 
            count++;
            
if (count==1000)//最多執(zhí)行1000次,如果這行長度超過2000就不管了,直接保存為默認(rèn)文件名
            {
               Log.log(Log.ERROR,BeanShell.
class,"Infinite loop:["+txt+"]");
               
//log: org.gjt.sp.util.Log jEdit的log系統(tǒng)
               buffer.save(view,null,true);//以默認(rèn)名保存
               return;//結(jié)束腳本執(zhí)行
            }

                
// Look for the next starting comment if we're not in a comment
            if (!inComment)
            
{
               
int commentStartIndex = txt.indexOf("/*");
               
if (commentStartIndex != -1)
               
{
                  inComment 
= true;
                  
if (commentStartIndex+2 == txt.length())
                     txt 
= "";
                  
else
                     txt 
= txt.substring(commentStartIndex+2);
               }

            }

                
// Look for the next ending comment if we are in a comment
            if (inComment)
            
{
               
int commentEndIndex = txt.indexOf("*/");
               
if (commentEndIndex != -1)
               
{
                  inComment 
= false;
                  
if (commentEndIndex+2 == txt.length())
                     txt 
= "";
                  
else
                     txt 
= txt.substring(commentEndIndex+2);
               }
 else {
                  
continue;
               }

            }

         }

            
            
// We now know if the remainder of the line is in a comment or not
         if (!inComment)
         
{
            
// Ignore lines that are too short for the regex
            if (txt.length() < regexMinimum)
               
continue;
            REMatch match 
= regex.getMatch(txt);
            
// See if it matches
            if (match!=null)
            
{
               
int startIndex = match.getStartIndex(3);
               
int endIndex = match.getEndIndex(3);
               
// Extract the class/interface name 得出第三個(gè)匹配,就是類名
               name = txt.substring(startIndex,endIndex)+".java";//文件名
               break;
            }

         }

      }

      
      
// Open the VFSBrowser
      String[] files = GUIUtilities.showVFSFileDialog(view,path+name,
                                                VFSBrowser.SAVE_DIALOG,
false);
      
if(files == null)
         
return false;
      buffer.save(view,files[
0],true);
      
return;
   }

}


// This isn't a file that has been scanned, so just do a normal save
buffer.save(view,null,true);

/*

Macro index data (in DocBook format)

   <listitem>
      <para><filename>Java_File_Save.bsh</filename></para>
      <abstract><para>Acts as a wrapper script to the Save As action. If the buffer
      is a new file, it scans the first 250 lines for a Java class or interface
      declaration. On finding one, it extracts the appropriate filename to be
      used in the Save As dialog.</para></abstract>   
      </listitem>

*/
         這個(gè)bsh腳本能自動(dòng)得到文件中的類名,以此作為文件名的前綴保存。要執(zhí)行這個(gè)文件,點(diǎn)擊Macros-Java-java_File_save。要快速執(zhí)行,可以設(shè)定快捷鍵。打開Utilities-Global option,選擇shortcuts-macros進(jìn)行快捷鍵設(shè)置。
          jEdit自帶的Macro就是很好的例子,配合幫助中的API,beanshell宏是很容易上手的。