Introduction
The less I have to navigate a directory tree, the happier I become. The arrival of Google Desktop hails the "flattening" of the file structure, as finally there is something that can just find my file for me, right when I want it. I have been a little slow to adopt the Google Desktop Search, because it still wants to open a file in the default way. If I tell it to open a web.config file, a new instance of TextPad will open (fine). I start getting annoyed when I go to open a C# source file, and suddenly I'm waiting for a new copy of VS.NET to open. That's bad.
So I have begun the task of integrating Google Desktop into text editors, with this ReSharper plug-in.
With this plug-in, I hit Ctrl-Alt-Z, type in a file name, and two seconds later, I'm editing it. Yah!
If you use Google Desktop and ReSharper, you might be interested in this plug-in. If you haven't gone to ReSharper yet, maybe you'll be interested in turning this into a VS.NET plug-in?
Background
I chose to use ReSharper because it comes with some fancy PopupList
user interface stuff. The next iteration will probably be more like the Common File dialog, and if possible, I will simply integrate with the Windows Common File dialog. Anyone knows how to do this?
I fooled around with the Google Desktop Native API for a long time before deciding that C# isn't the right language for doing that. Eventually, I found this .NET wrapper for the web interface to Google Desktop Search, which I included in the project.
Using the code
First, register the Action, with this bit from AssemblyInfo.cs:
[assembly : PluginTitle("OpenByGoogleDesktopSearch")]
[assembly : PluginVendor("Tyler Gannon")]
[assembly : PluginDescription("Find a file using
Google Desktop search and open it.")]
[assembly : ActionsXml("Resharper.GoogleSearchPlugin.Actions.xml")]
Then you need a bit in Actions.xml:
The GDS.SearchFiles
method returns a sorted array of SearchResult
objects, filtered to only include results that correspond to files on the local file system.
Getting the search results looks like this:
IGoogleSearch search = GoogleSearchFactory.CreateGoogleDesktopSearch();
search.ResultsPerPage = 20;
search.ResultType = ResultTypes.DataSet;
IGoogleSearchResult searchResult = search.Search(query);
DataSet currentResult;
Now, iterate through them, and get rid of any junk.
foreach (DataRow row in table.Rows)
{
if ("file".CompareTo((string) row["category"]) == 0)
{
object title = row["title"];
object url = row["url"];
if (DBNull.Value.Equals(title) || DBNull.Value.Equals(url))
continue;
object snippet = title;
try
{
snippet = row["snippet"];
if (DBNull.Value.Equals(snippet))
snippet = title;
}
catch (Exception)
{
continue;
}
string urlString = (string) url;
if (urlString.StartsWith("archive://"))
continue;
SearchResult result = new SearchResult((string) title,
urlString, (string) snippet);
resultsToReturn.Add(result);
currentResultCount++;
}
if (currentResultCount >= maxResults)
{
break;
}
}
Now, make it so that file names most similar to the actual search query will show up first.
Array.Sort(resultsArray, new SearchResultComparer(query));
Making use of the ReSharper popup requires implementing a few interfaces:
IPositionProvider
, which tells the system where it can present the popup.
IPopupListItemDescriptor
, a list of which are given to the PopupList
by the PopupListProvider
. In this project, SearchResult
implements that interface.
IPopupListProvider
, which is the liaison between the GDS search and the PopUpList
.
IPopupWindowContext
, which provides general functionality around PopupWindow
s. I inherited my PopupWindowContext
from PopupWindowContextBase
, and then I only had to implement CreateDefaultPositionProvider()
, which is defined as abstract
on the base class.
The SearchPopup
form code ties it all together:
public SearchPopup()
{
InitializeComponent();
textBox1.Enter += new EventHandler(TextBox1_OnEnter);
}
internal void UpdateList()
{
if (textBox1.Text.Trim().Equals(string.Empty))
{
TrimWindowSize();
return;
}
list = new EscapingPopupList(new SearchResultListProvider(
GDS.SearchFiles(textBox1.Text, MAX_RECORDS_TO_SHOW), this));
list.Escape += new PopupListEscapeEvent(TrimWindowSize);
list.Show(positionProvider);
}
private void TrimWindowSize()
{
this.ResizeRedraw = true;
this.Size = textBox1.Size;
}
protected void TextBox1_OnEnter(Object Sender, EventArgs e)
{
if (popupWindowContext==null)
popupWindowContext = new PopupWindowContext(this);
if (positionProvider==null)
positionProvider =
popupWindowContext.CreateDefaultPositionProvider();
base.OnEnter(e);
}
protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == (Keys.Control| Keys.W) || keyData==(Keys.Escape))
Close();
if (keyData == Keys.Tab || keyData == Keys.Enter)
UpdateList();
return base.ProcessDialogKey (keyData);
}
Installation
Once it's built and ready, you need to register the plug-in with ReSharper, and finally you must set up a Command Key. Copy the DLL into its own subdirectory of the PlugIns directory underneath where ReSharper is installed. The directory should be named the same as the plug-in. In this case, the assembly is named Resharper.GoogleSearchPlugin, so that's what I named the directory. Then, start VS.NET, and do the following settings in the ReSharper Plug-Ins dialog, followed by the Keyboard tab on the VS.NET general options:
And you're ready to go! Have fun.
History
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.