Permalink
Browse files

Added public symbol search function

  • Loading branch information...
djspiewak committed Sep 23, 2011
1 parent 1835d06 commit 422b767f11ea6af6c3ea7df8f71778f246928b5b
@@ -36,4 +36,9 @@
com.codecommit.es.EnsimePlugin.suggestImports(view);
</CODE>
</ACTION>
+ <ACTION NAME="ensime.symbol-search">
+ <CODE>
+ com.codecommit.es.EnsimePlugin.symbolSearch(view);
+ </CODE>
+ </ACTION>
</ACTIONS>
@@ -12,15 +12,18 @@ options.ensime.code=new com.codecommit.es.ui.EnsimeOptionPane();
plugin.com.codecommit.es.EnsimePlugin.menu=ensime \
ensime.kill \
- \
- ensime.inspect-type \
ensime.jump-to-declaration \
+ ensime.symbol-search \
+ - \
+ ensime.inspect-type \
ensime.expand-selection \
ensime.suggest-imports
options.menu.label=ENSIME
ensime.label=Initialize Project
ensime.kill.label=Kill Server for Project
-ensime.inspect-type.label=Inspect Type
ensime.jump-to-declaration.label=Jump to Declaration
+ensime.symbol-search.label=Public Symbol Search
+ensime.inspect-type.label=Inspect Type
ensime.expand-selection.label=Expand Selection
ensime.suggest-imports.label=Suggest Imports
@@ -31,7 +31,7 @@ class EnsimeParser extends SideKickParser("ensime") {
}
signal synchronized {
- signal.wait(5000)
+ signal.wait(500)
}
if (finalResults != null) {
@@ -314,6 +314,37 @@ object EnsimePlugin {
}
}
+ def symbolSearch(view: View) {
+ val buffer = view.getBuffer
+ for (inst <- instanceForBuffer(buffer)) {
+ val dialog = new ui.SymbolSearchDialog(view, inst.Ensime.publicSymbolSearch)
+
+ for ((file, offset) <- dialog.open() if offset >= 0) {
+ EventQueue.invokeLater(new Runnable {
+ def run() {
+ type Navigator = { def addToHistory() }
+ type NavigatorPlugin = { def getNavigator(view: View): Navigator }
+
+ val navPlugin = Option(JEdit.getPlugin("ise.plugin.nav.NavigatorPlugin")) map { _.asInstanceOf[NavigatorPlugin] }
+ navPlugin foreach { _.getNavigator(view).addToHistory() }
+
+ val buffer = JEdit.openFile(view, file)
+ val pane = view.goToBuffer(buffer)
+ val area = pane.getTextArea
+
+ EventQueue.invokeLater(new Runnable {
+ def run() {
+ area.setCaretPosition(offset)
+
+ navPlugin foreach { _.getNavigator(view).addToHistory() }
+ }
+ })
+ }
+ })
+ }
+ }
+ }
+
private def instanceForBuffer(buffer: Buffer) =
parentDirs(new File(buffer.getPath)) flatMap instances.get headOption
@@ -270,6 +270,36 @@ trait EnsimeProtocolComponent extends BackendComponent {
dispatchSwank(id, SExp(key("swank:import-suggestions"), file, point, SExpList(names map StringAtom), maxResults))
}
+ def publicSymbolSearch(names: List[String], maxResults: Int)(callback: List[(String, String, Int)] => Unit) {
+ val id = callId()
+
+ registerReturn(id) {
+ case SExpList(results) => {
+ val back = results collect {
+ case result: SExpList => {
+ val map = result.toKeywordMap
+
+ if (map.contains(key(":name")) && map.contains(key(":pos"))) {
+ val StringAtom(name) = map(key(":name"))
+
+ val pos = map(key(":pos")).asInstanceOf[SExpList].toKeywordMap
+ val StringAtom(file) = pos(key(":file"))
+ val IntAtom(offset) = pos(key(":offset"))
+
+ Some((name, file, offset))
+ } else {
+ None
+ }
+ }
+ }
+
+ callback(back.flatten.toList)
+ }
+ }
+
+ dispatchSwank(id, SExp(key("swank:public-symbol-search"), SExpList(names map StringAtom), maxResults))
+ }
+
private def dispatchSwank(id: Int, sexp: SExp) {
Backend.send(SExp(key(":swank-rpc"), sexp, id).toWireString)
}
@@ -297,6 +327,7 @@ trait EnsimeProtocolComponent extends BackendComponent {
def symbolAtPoint(file: String, offset: Int)(callback: Option[Location] => Unit)
def expandSelection(file: String, start: Int, end: Int)(callback: (Int, Int) => Unit)
def importSuggestions(file: String, point: Int, names: List[String], maxResults: Int)(callback: List[String] => Unit)
+ def publicSymbolSearch(names: List[String], maxResults: Int)(callback: List[(String, String, Int)] => Unit)
}
}
@@ -0,0 +1,106 @@
+package com.codecommit
+package es
+package ui
+
+import com.codecommit.es.client.EnsimeProtocolComponent
+import java.awt.EventQueue
+import java.awt.event.KeyEvent
+import java.awt.event.KeyListener
+import javax.swing.JTextField
+import javax.swing.{JButton, JDialog, JFrame, JLabel, JList, JPanel, JScrollPane, ListSelectionModel, WindowConstants}
+
+import java.awt.{BorderLayout, FlowLayout}
+import java.awt.event.{ActionEvent, ActionListener}
+
+class SymbolSearchDialog(parent: JFrame, publicSymbolSearch: (List[String], Int) => (List[(String, String, Int)] => Unit) => Unit) extends JDialog(parent, "Public Symbol Search", true) {
+ private var selected: Option[(String, Int)] = None
+ private var data = Vector[(String, Int)]()
+
+ {
+ getContentPane.setLayout(new BorderLayout)
+
+ val names = new JTextField
+ getContentPane.add(names, BorderLayout.NORTH)
+
+ val list = new JList
+ list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
+ // list.setSelectionInterval(0, 0)
+ getContentPane.add(new JScrollPane(list))
+
+ names.addKeyListener(new KeyListener {
+ var hasOutstanding = false
+ var queryNames: Option[List[String]] = None
+
+ def keyPressed(e: KeyEvent) {
+ if (e.getKeyCode == KeyEvent.VK_ESCAPE) {
+ dispose()
+ } else if (e.getKeyCode == KeyEvent.VK_ENTER) {
+ selected = if (data.isEmpty) {
+ None
+ } else {
+ if (list.getSelectedIndex < 0)
+ data.headOption
+ else
+ Some(data(list.getSelectedIndex))
+ }
+
+ dispose()
+ } else if (e.getKeyCode == KeyEvent.VK_UP) {
+ if (list.getSelectedIndex > 0) {
+ list.setSelectedIndex(list.getSelectedIndex - 1)
+ }
+ e.consume()
+ } else if (e.getKeyCode == KeyEvent.VK_DOWN) {
+ if (list.getSelectedIndex < data.length - 1) {
+ list.setSelectedIndex(list.getSelectedIndex + 1)
+ }
+ e.consume()
+ }
+ }
+
+ def keyReleased(e: KeyEvent) {
+ }
+
+ def keyTyped(e: KeyEvent) {
+ queryNames = Some(names.getText split " " toList)
+ if (!hasOutstanding) {
+ requestCompletion()
+ }
+ }
+
+ private def requestCompletion() {
+ for (tokens <- queryNames) {
+ hasOutstanding = true
+ queryNames = None
+
+ publicSymbolSearch(tokens, 50) { results =>
+ val names2 = results map { case (n, _, _) => n }
+ val data2 = results map { case (_, f, o) => (f, o) }
+
+ EventQueue.invokeLater(new Runnable {
+ def run() {
+ data = Vector(data2: _*)
+ list.setListData(names2.toArray.asInstanceOf[Array[AnyRef]])
+ }
+ })
+
+ hasOutstanding = false
+ requestCompletion()
+ }
+ }
+ }
+ })
+
+ setSize(400, 400)
+
+ val screen = getToolkit.getScreenSize
+ setLocation((screen.width - getWidth) / 2, (screen.height - getHeight) / 2)
+
+ setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
+ }
+
+ def open() = {
+ setVisible(true)
+ selected
+ }
+}

0 comments on commit 422b767

Please sign in to comment.