初マクロ
帰省して、やることがないのでマクロを作ってみた。
SVNのCommitマクロを作るつもりだったが、実家からはリポジトリにアクセスできないのでテスト不能。
ローカルにリポジトリを作るのも面倒なので休み明けかな。
作ったのはショートカットを開くマクロ。
jFD2はショートカットの作成・削除が簡単で良いのだが、開く時の操作性がDFに比べるといまいちなので、それを改善するのが目標。
機能:ショートカットを開く
(1) 起動した時にショートカットフォルダーにあるショートカットを一覧表示。
(2) その段階でインクリメンタルサーチ(Migemoが使えればMigemo)できる*1。
(3) Enterキーで選択したショートカットを開く。
(4) Shift+Enterキーで選択したショートカットを新しいタブで開く。
Swingでちょっとはまった。実家ではネット環境が貧弱なので調べるのも大変。
Groovyではインターフェイスの実装が楽でいいなぁ。KeyAdapterを使わなくてもKeyListenerの実装が簡単にできる。
import com.nullfish.lib.vfs.VFS import com.nullfish.lib.keymap.KeyStrokeMap import com.nullfish.app.jfd2.ui.container2.NumberedJFD2 import com.nullfish.app.jfd2.ui.container2.JFD2TitleUpdater import com.nullfish.app.jfd2.ui.container2.ContainerPosition import com.nullfish.app.jfd2.util.IncrementalSearcher import com.nullfish.app.jfd2.util.WildCardUtil import com.nullfish.app.jfd2.util.MigemoInfo import org.monazilla.migemo.Migemo import java.awt.event.KeyListener import java.awt.event.KeyEvent import java.awt.event.InputEvent import java.awt.event.KeyAdapter import javax.swing.KeyStroke files=[] shortcutDir=(String)jfd.getCommonConfigulation().getParam("shortcut_dir", "") new File(shortcutDir).list().each{ m=(it=~/(.+)\.jfdlnk$/) if(m.size()>0) files<<=m[0][1] } if(files.size()<1) return files=files.sort() dlg=new groovy.swing.SwingBuilder().dialog(title:"Open shortcut"){ box(axis:javax.swing.BoxLayout.Y_AXIS){ scrollPane(){ ls=list(listData:files,selectionMode:javax.swing.ListSelectionModel.SINGLE_SELECTION,selectedIndex:0) } panel(){ label(text:"Search:") word=label() } panel(){ label(text:"Enter:Open, Shift+Enter:NewTab, ESC:Cancel, Chars:Search") } } } dlg.pack() dlg.setLocationRelativeTo(null) dlg.setVisible(true) ls.addKeyListener([keyPressed:{e-> setIndex={pos-> ls.selectedIndex=pos ls.ensureIndexIsVisible(pos) ls.updateUI() } searchWord={ wd=MigemoInfo.usesMigemo()?Migemo.lookup(word.text):"^"+WildCardUtil.wildCard2Regex(word.text).toLowerCase() pattern=wd.bitwiseNegate() for(i in 0..files.size()-1){ if(files[i].toLowerCase()=~pattern){ setIndex(i) break } } } switch(KeyStrokeMap.getKeyStrokeForEvent(e)){ case KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0): case KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.SHIFT_DOWN_MASK): file=new File(new File(shortcutDir),files[ls.selectedIndex]+".jfdlnk") newPath=new String(file.readBytes()) newFile = VFS.getInstance(jfd).getFile(newPath) if(newFile != null){ if(e.modifiersEx&KeyEvent.SHIFT_DOWN_MASK){ newJFD = new NumberedJFD2() newJFD.init(jfd.jFDOwner.configDirectory) jfd.jFDOwner.addComponent(newJFD, ContainerPosition.MAIN_PANEL, new JFD2TitleUpdater(newJFD)) newJFD.model.setDirectoryAsynchIfNecessary(newFile, newFile.getParent(), newJFD) }else{ jfd.model.setDirectoryAsynchIfNecessary(newFile, newFile.parent, jfd) } } case KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0): dlg.dispose() break case KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0): case KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.CTRL_DOWN_MASK): switch(word.text.size()){ case 0:break case 1: word.text="" setIndex(0) break default: word.text=word.text.getAt(0..-2) searchWord() } break default: c=Character.toUpperCase(e.getKeyChar()).toString() if(word.text.size()<30&&IncrementalSearcher.ACCEPTABLE_CHARS.indexOf(c)>=0){ word.text+=(e.modifiersEx&KeyEvent.SHIFT_DOWN_MASK) ? c:e.getKeyChar().toString() searchWord() } } }] as KeyListener)