[Mono-list] GSilver: A linux app using mono similar to QuickSilverfor mac

Jonathan Gilbert 2a5gjx302 at sneakemail.com
Mon Jun 26 13:08:41 EDT 2006

At 09:25 AM 26/06/2006 -0700, Michael Gorbach wrote:
>Hello everyone,
>I am new to the linux community and I would like to make an attempt to
>contribute some GPL software of my own. My idea is to create a framework
>for linux that would be similar to quicksilver for Mac.

I'm pretty sure this is off-topic for this list, but I did have an idea
while reading through your description of the searching engine. :-)

>The underlying architecture of quicksilver, as I understand it, is based on
>"collections" of items. There is a collection of applications, a collection
>of files, a collection of contacts, and so on. Certain actions are
>associated with collections, for example "run" is association with
>applications, "email to" or "call" or "IM" may be associated with contacts.
>They key is that collections of items and actions can be added easily
>through plugins. Supported could be implemented for things like
>thunderbird, gaim, ssh, compression (tar, gzip, etc.), scp/sftp, browser
>bookmarks, rss feeds, ... the list goes on and on. Plugins support can
>also be extended to the interface of the program itself.

This idea of "collections" may be useful for thinking about it, and
possibly in a user interface for configuring things, but when coding a
system like this, I think you'll find it is almost certainly better to
think in terms of types, rather than explicit grouping of objects. You'll
need to have a single centralized list in order to search efficiently, and
once the item is selected, any actions depend on what type of item it is.
Perhaps a better term for "collection" would be "category"?

>There are several issues I have been dealing with in which I could really
>use some help:
>2. Searching algorithms in the text
>Quicksilver is free but not open source unfortunatly. Therefore I can not
>look at how they deal with searching through text like item names or
>actions names and pulling up the right one. I have noticed a few things
>about their implementation:
>a. They have some sort of memory system that allows the catalog to remember
>   your previous choices. If you type in ff the first time, firefox will
>   show up but will not be the first thing on the list. If you then start
>   firefox using "ff", firefox will be first on the list next time you type
>   "ff".
>b. They do not require the strings you type to be found consecutively in
>   the word, so typing ff brings up firefox even if the two characters are
>   not found together in the name.
>c. Somehow, it seems that programs where more of your letters typed show up
>   consecutively together seem to come up higher in the list than those
>   where they are farther apart.
>I have no real idea how to implement these algorithms, and even if I did I
>can't figure out how to merge the different ratings items get from criteria
>a, b, and c into an ordering. Also, there may be other criteria. If someone
>could suggest either implementation ideas or more ideas for criteria, that
>would be great.

Well, clearly, you need some way of assigning a score to each item, given a
sequence of characters entered by the user. The idea which came to be while
reading this is that you could use a regex match to assign an initial score
to each item.

Start by inserting a ".*" between each letter the user typed, so that if
the user typed "abcd", then your regex would be "a.*b.*c.*d". Any string
which doesn't match the regex simply isn't included in the list. For those
that are, look at the text which matched. The longer it is, the higher the
score, and a higher score means that the item goes farther down the list.

For instance, if the user typed "ff", then your regular expression would be
"f.*f". Applied to the string "firefox", this would yield the match
"firef", where the "ire" is from the ".*". (Incidentally, I believe .NET's
regular expression library lets you determine the length of the match
without actually retrieving it as a System.String object; if you are
checking against a large list, this could be a significant optimization.)
Compared to, say, "diff", for which the match is exactly "ff", "firefox"
will be lower in the list, but it won't be excluded, and it will get a
better score than (... scans local system ...) "verify_krb5_config", whose
match is the monstrous "fy_krb5_conf".

This satisfies points b. and c., and as for a., you could use a list of all
items accessed in the past [hour|day|month] and artificially extract them
from the list (but keeping their order) and re-insert them at the top. This
achieves the instant jump to the top you describe.

An alternate approach would be to count the number of times the item has
been accessed in the past [hour|day|month|forever] and simply decrease the
score by that quantity (I see no problem with negative scores). Then, you
just use the score as computed including that term to sort the list. With
this scheme, after the first time, 'firefox' might move up 1 or 2 spots in
the list, instead of going directly to the top. The more often you use it,
though, the closer it gets to the top of the list. The scores of
frequently-used items would quickly be dominated by the "frequency factor".

>3. Plugin architecture
>I dont know much about building plugin-able software in .net. If there is
>some information availible that someone could like me to, that would be

In .NET, you can dynamically load assemblies into app domains, but you
cannot dynamically unload them. In order to remove code from memory, the
entire app domain containing the code must be unloaded. So, it is fairly
typical of plugin architectures to create a child app domain, either one
for all plugins, or a separate one for each plugin (much higher overhead,
of course). In order to access a plugin across an app domain boundary, as I
understand it you must require it to derive from MarshalByRefObject (but it
does not need to do so directly -- it can derive from a class you write
which itself derives from MarshalByRefObject). In order for the code
hosting the plugins to be able to access the plugin objects, either the
plugin base class must be in a separate assembly, or the plugins must
directly reference your program file. Of course, you also need some object
to pass to the plugin so that it can contact the main application and make
requests. If you are using a separate library that both your app and the
plugin reference in order to get common types, then you could put an
interface there exposing the functionality of your application, and then
implement the interface from a class deriving from MarshalByRefObject in
your main class. With this design, you can simply pass an instance of that
object to a parameter of the plugin whose type is the interface, and .NET
will automatically create a transparent proxy object for you.

Just to throw a spanner in the works, as I understand it Mono's
implementation of unloading app domains is not quite there yet. It may or
may not work, it may or may not cause a catastrophic system crash, it
probably won't eliminate all leaking of memory. Someone else can better
fill you in on this.

>4. If someone has any ideas on how to implement the "collections" "items"
>"actions" concepts in terms of classes and inheritance, while keeping the
>system extendable with plugins, those would also be very, very helpful.

You could make an abstract base class for each of the concepts you want
plugins to be able to implement, and in the aforementioned interface to the
program, allow plugins to inject their items into the list. You should
possibly also allow a way to query a plugin based on the current state, to
say, "Given where we are now, is there anything else you'd like to
contribute?", and if the plugin is contributing context-sensitive actions
(e.g. a plugin for a popular Wysiwyg HTML editor recognizes that the HTML
file you selected as the actionable object was created by the editor in
question, then it adds actions specific to the editor), there needs to be a
way for them to stay in effect only as long as the context applies to them
(so that if you select another HTML file and it wasn't created by the
editor, those editor-specific actions are removed).

Hopefully this gives you some ideas to help you forward :-)

Jonathan Gilbert

More information about the Mono-list mailing list