Skip to content
This repository

Vimium Omnibox implementation, with fuzzy completion #459

Merged
merged 78 commits into from almost 2 years ago

5 participants

Niklas Baumstark Phil Crosby Jez Ng Ilya Adam Stankiewicz
Niklas Baumstark

As seen in #442, this pull requests suggests a sophisticated new UI and infrastructure that allows for efficient, keyboard-controlled navigation of history items, bookmarks, tabs and for user-defined commands like web search, URL input and accessing different search engines.

Parts of the changes included in this request could be applied on their own (for example the changes to lib/utils.js), but this wouldn't be of a significant advantage within the context of the existing Vimium code base. The approach I take is therefore to suggest all the changes as a whole and explain how they are structured.

Motivation

I really like Vimium in its current state, but what I always missed about it was a really efficient way to navigate away from a page. The Omnibox is quite good, but I find it's a pain to use it with Vimium, as pressing Ctrl+L causes the current page to lose focus, which defeats almost all of Vimium's bindings. Returning focus to the page is near impossible without using the mouse. Also, the Omnibox is not as configurable as I like it to be. It doesn't do fuzzy matching (which I love and use a lot inside vim), doesn't help in searching lost tabs and adding search engines is a bit of a pain. One more reason is that the location bar takes away vertical space, which I have better use for on my laptop screen.

Changes to the existing library code

  • background_page.html: added new background API elements to access bookmarks, history and tabs from content scripts
  • lib/utils.js: refactored the existing URL detection to be a bit more useful. Also added some helpers I needed that I think are general enough to be included here
  • lib/keyboardUtils.js: Handle uppercase input (don't know why this wasn't the case before, maybe it's not the right thing to add this here)

Logic for different kinds of completion

The underlying model is a simple one. A completion driver is something that gets input and returns a list of suggestions together with a rendering routing to transform them into HTML and with a relevancy value. There are 5 different drivers already implemented:

  • smart: A driver that takes an input string and tries to make sense of it. It tries to detect whether the input is

    • a user-defined command (wiki Obama) => suggests to evaluate the command
    • an URL => suggests to visit it
    • nothing special at all => suggests a basic web search
  • bookmarks, history, tabs: they fuzzy match the different kinds of items

  • merging completer: a driver that can be used to combine and sort the results of multiple driver instances

The library code includes a comprehensive class to manage fuzzy string matching which implements filtering and ranking, together with some basic optimization like result caching.

I think this approach is very flexible and can be extended for other use cases as well.

User interface

The user interface is a simple HTML box which takes input and presents the results returned by the underlying completion driver. It is designed to be easily readable, with a rather large font and dark background for maximum contrast (although the styling is only a matter of CSS, of course):

Example integration

As a suggestion, three Vimium commands are implemented to demonstrate the usefulness of this addition:

  • Generic complete (bound to o => open in current tab, O => open in new tab). Fuzzy-matches history, bookmarks, tabs and uses the smart completer to suggest sensible actions depending on input
  • Tab complete (bound to T). Fuzzy-matches open tabs in the current window for people who never close tabs and therefore got lots of them open at the same time (like me)

Maintenance

I am aware that this pull request, with its 700 LoC+, is pretty large, compared to the existing combination of completionDialog.js and bookmarks.js, which together have under 300 lines. However, my approach has the advantage of unifying different kinds of dialogs, which makes it easy to drop, add or recombine functionality in the future.

I am also aware that the maintainers of this project keep a focus on efficiency and maintainability. I did my best to improve usability and responsiveness of the UI and to add documentation for the significant pieces of code, but I am convinced that my code in the current state leaves room for improvement. If this gets a chance, I will put some effort into code reduction. I am also willing to support and improve this facility in the future, if that would be of help. Hacking Vimium is really fun :)

Phil Crosby
Owner

Wow, this is epic. Nice start Niklas. It will take some time for the team to review it, and in doing so we'll evaluate

  1. whether this UX fits with Vimium
  2. the design of the system
  3. the code

I'll begin looking at your branch in detail in the next couple of days. @int3, if you have time to do the same and come up with an initial round of comments, that would be really helpful.

Niklas Baumstark

@philc: Thank you, I am absolutely willing to work together with you guys to make this a good fit for Vimium.

Jez Ng
Collaborator

I'm a little busier now since school's started again, but yeah, I'll find some time to help review this. Thanks @niklasb for the awesome work!

Ilya
Collaborator

Wow. Epic indeed. I will try this out.

Jez Ng
Collaborator

I haven't had time to really look through the code yet, but I noticed that I wasn't getting some history results that I ought to. Skimming over your code, it looks like you limit the number of history entries that can be transmitted from the background page to the content script, and then you calculate the relevancy after that. Hence some highly-relevant results could get discarded. Indeed, when I increase maxResults to a very large number, I obtained the result I was looking for.

I think we could solve this problem by calculating relevancy in the background page first, and sending the X most relevant results to the content scripts.

Niklas Baumstark

@int3: That is indeed a problem I don't know how to solve yet. The relevancy calculation is executed in the content script on a pre-cached set of history items. This is because transferring to and from the background page seems to be quite slow compared to the actual filtering and ranking algorithm.

So what I currently do is to fetch the most visited 1500 pages from the background page once and then operate on the result. I am not sure how to transfer parts of the logic to the background page without losing performance, but I'll try something out later.

Jez Ng
Collaborator

If you are only transferring the top 10 or so results on each keystroke, shouldn't it be reasonably fast?

Niklas Baumstark

@int3: Yeah, that's what I was thinking. I'll try to transfer as much of the logic as possible to the background page. An additional benefit would be lower memory consumption (only one cache instead of one for every page that's used to access the omnibox). There are some caveats however, for example that I can't transfer the rendering function to the content page. I think I can work around this, but it might not be as clean as it is now.

Niklas Baumstark

@int3: I rethought this and see more clearly now what the problem is. It's not a matter of where the results are filtered but how many history items are actually included in the search. I don't make use of the search facility included in the Chrome API, because I use a custom, fuzzy algorithm to filter the results. I limited the number to 1500 because the fuzzy matching takes a quite bit of time, which obviously is O(n) to the number of entries. Raising this number significantly (e.g. to 15000) will inevitably make the dialog less responsive (at least if you don't have a high-end CPU). The only thing I can imagine how the impact of this could be reduced is by

  • a) making the filtering significantly more efficient (which I am not sure how to do, it's currently using fast regex matching and uses caching to only search within plausible sets of previous results)
  • b) initially using a different sort algorithm, so that relevant history items are more likely to be amongst the search set of (for example, we could sort by last access time rather than visit count?)

Moving logic to background page is still sensible (and I am going to do it), but it wouldn't solve this particular problem.

Jez Ng
Collaborator

Given that you're calling Array.sort() in your code, I think your runtime should be O(n lg n), not O(n). Since we only really need the top k results, we might be able to speed things up. One way is to use the quickselect algorithm to find the kth largest element, and then loop over the array once more to collect all the k elements whose relevancy is >= to the kth largest one. The running time for that should be O(n) on average. The question, however, is whether the constant overhead of having this algorithm in JS instead of native C will outweigh the O(lg n) savings.

I think the matching / relevancy algorithm might be amenable to some optimizations as well... let me mull over that for a bit.

Jez Ng
Collaborator

Oh, my bad, I think I misunderstood your comment. You were trying to say that the filtering of the results was the bottleneck, and not the sorting, hence the O(n) runtime. Yeah, I guess that makes sense, considering that the matching algorithm takes O(m) time to run where m is the size of the query. Hmm...

Edit: On closer inspection of match(), I realize the runtime is actually much slower than that.

Niklas Baumstark

@int3: fuzzyMatcher.match() is only ever called on the results that are actually displayed (as the documentation says). It uses a more complicated, backtracking algorithm to prefer marking consecutive letters in the dialog. fuzzyMatcher.filter() is used to filter the results, and it's O(n) with n being the number of matches of the last call or the number of total history items if this is the first call.

Jez Ng
Collaborator

Oh. Well in that case... I can think of two things to try:

  1. Build a trie and match on that
  2. Filter the completions lazily. I.e. whenever the filter function finds a match, call a callback and pass that match to it.
Niklas Baumstark

@int3: The idea about using a prefix-based search tree also came to my mind, but it would take huge amounts of memory. Do you have something specific in mind?

About your second suggestion: There are three steps involved in filtering/ranking the results:

  1. roughly filter the source list for possible matches using regexes (fuzzyMatcher.filter)
  2. assign a relevancy value to each match (fuzzyMatcher.calculateRelevancy)
  3. sort results by relevancy (MergingCompleter.filter)

I fail to see how laziness would buy us anything here, as we need to sort (or quickselect) the complete set of results after the complete list of filtered results are available. The only way I think this could be helpful is if this is used with some kind of insertion sort. I doubt that it will give better performance, though, Array.sort() should be quite fast already (the filtering really is the bottleneck!).

UPDATE: Also, I added a commit that causes the dialog to use the last visited 2000 pages as a source, instead of the 1500 most frequently visited. Do you think this is an improvement?

UPDATE 2: About fuzzy matching and tries: If the user gives us input like "abcde", we want to match the source list against a pattern like *a*b*c*d*e*. So already a simple string like "12345" would have several paths leading to it, like "123", "134", ..., so it would need to be inserted at N = bin(5,1) + bin(5,2) + bin(5,3) + bin(5,4) + bin(5,5) = 31 locations within a primitive search tree of depth 5. I can experiment a bit with this, but I think optimizing this is not a simple task.

UPDATE 3: I played around a bit and managed to optimize quite a lot by deferring some calculations as long as possible, so thanks for your hint. I think this allows us to raise the number of history items searched by default, at least it works on my system rather smoothly with ~10000 items. Can you try the changes?

Jez Ng
Collaborator

Well, I'm getting the particular result I was looking for earlier, so that's nice :) Let me play around with it for a bit more to see how it fares.

Anyway, to clarify my earlier comment on lazy evaluation, I was indeed thinking about sorting incrementally via insertion sort -- it would be slower than the native Array.sort(), but it seems like it'd work around the slowness with filtering. What approach did you take in the end?

Niklas Baumstark
Jez Ng
Collaborator

Yes, we might take a while to get a particular desired result, but lazy filtering would allow us to start sending the results sooner. It would not decrease total runtime in the worst case, but it would increase the responsiveness of Vimium, and responsiveness is a bigger determinant of how fast an application feels. Moreover, pre-sorting by last visit time / number of visits would allow us to return more likely hits first. Just think about searching in Spotlight -- you get a few results almost instantly, usually of frequently used programs and files, but more results trickle in afterwards.

Niklas Baumstark

@int3: I get it now. This is what I had in mind too, but it seems to be much more complicated to implement, so I dropped the idea in favor of code simplicity (for the moment). Maybe I'll come back to this, though.

Niklas Baumstark

The logic now lives in the background page. This seems to greatly improve performance and overall responsiveness.

Phil Crosby
Owner

I still haven't gotten to diving into this deeply, and I want to do a 1.31 release shortly before we pull something this large in.

Niklas Baumstark

@philc: I understand. It's actually still a bit of work in progress, as it turns out (especially regarding optimization). That's why I keep pushing one change after the other :P When you think you can spend some time on checking this out, I will concentrate on bringing it into a more consistent and stable state. Do you think this is okay?

UPDATE I just noticed that the above formulation is a bit suboptimal. Please don't get me wrong, I think this is absolutely usable right now (I use it every day), I just think it can be improved even further.

Phil Crosby
Owner

Sounds good

Phil Crosby
Owner

This feature and bookmarks would benefit from a fix to #411 -- our dialogs show under Flash, not on top of it, on windows.

Niklas Baumstark

@philc: Thanks for the hint, I will integrate that fix.

Ilya
Collaborator
ilya commented April 06, 2012

What's the status here?

Niklas Baumstark

@ilya: Using it every day, so it's kinda ready :) philc said something about coming back to this if his time allows? Haven't checked since, I guess this needs some rebasing (not a lot).

Phil Crosby
Owner
philc commented April 06, 2012

It sounds like the feature is usable. I haven't been using it myself, but the next steps are to review the implementation and tidy it up if necessary, and style the UI where necessary.

Phil Crosby
Owner
philc commented April 06, 2012

@niklasb can you rebase this?

Niklas Baumstark

@philc: Can't finish that today, but I think I can do it by the middle of next week, if that's okay.

added some commits January 21, 2012
Niklas Baumstark add fuzzy mode 6f589fe
Niklas Baumstark make failing test pass again :) fd549f0
Niklas Baumstark remove trimming from isUrl c808c6a
Niklas Baumstark add possibility to use custom search engines and use "wiki ", "cc ", …
…and ";" (goto) as custom commands
253dc6f
Niklas Baumstark remove useless CSS directive f4416cb
Niklas Baumstark make CSS more specific 2a9c88a
Niklas Baumstark fix some issues with asynchronous filtering and refreshing bd6f3be
Niklas Baumstark make F5 refresh the completions b6a91ff
Niklas Baumstark remove empty leading line 9e6bdef
Niklas Baumstark fix syntax error ef7084e
Niklas Baumstark allow fuzzy completion of HTML-decorated content and implement this f…
…or history and bookmarks
79b0340
Niklas Baumstark allow custom functions as commands, add example in form of forced web…
… search
69ea703
Niklas Baumstark document the HTML matching algorithm better 667f97b
Niklas Baumstark make number of completions configurable 85ae8c6
Niklas Baumstark decrease number of history items 6979cd6
Niklas Baumstark underscore is not a word character in our context 8f126b0
Niklas Baumstark improve relevancy calculation 0bcad93
Niklas Baumstark move some logic from background to content page 3520212
Niklas Baumstark fix relevancy heuristic 642694b
Niklas Baumstark add Google lucky search as command "luck " f0409c5
Niklas Baumstark add tab completion support 53f8158
Niklas Baumstark really get more history items 76b26a8
Niklas Baumstark remove debug statement 516101b
Niklas Baumstark improve string ranking fc545ea
Niklas Baumstark prefer marking continguous characters 4691478
Niklas Baumstark use background page to open URLs 2c5b916
Niklas Baumstark fix bug in query normalization 9c3ea93
Niklas Baumstark restructure fuzzy mode flow 9890e17
Niklas Baumstark add special command for tab completion 9bab5a3
Niklas Baumstark fix search URL building aa5b39f
Niklas Baumstark make CSS more robust 6be4f61
Niklas Baumstark fix ranking algorithm 8e20171
Niklas Baumstark sort results in tab completion mode de0a360
Niklas Baumstark fall back to regex matching for long queries 59b096f
Niklas Baumstark raise regex threshold to query length 15 8179e6d
Niklas Baumstark fix bad English 958dd00
Niklas Baumstark improve perfmance by caching history results in the background page.
Also decrease the number of included results slightly.
6bc1d44
Niklas Baumstark minor optimizations and code cleanup 14cb3e4
Niklas Baumstark improve comments and fix some naming style inconsistencies 2eae98f
Niklas Baumstark DRY up code a9ea93a
Niklas Baumstark add bookmark in "all" completion 82b461b
Niklas Baumstark more DRYing f69fea3
Niklas Baumstark fix small bug 4edbe74
Niklas Baumstark update results list asynchronously to take load from the CPU and impr…
…ove the perceived responsiveness
a9d89d0
Niklas Baumstark fix small bug when closing and reopening dialog in combination with a…
…sync updating
6463714
Niklas Baumstark hide completion list if no completions are available 9fd6faa
Niklas Baumstark force update after pressing Return 3f1fa91
Niklas Baumstark code cleanup 951a853
Niklas Baumstark add HTML helpers f41ebfb
Niklas Baumstark create DOM by HTML 885c633
Niklas Baumstark fix regression in 10a77d25c3 99c19d2
Niklas Baumstark move query length threshold from UI to logic
This enables to set threshold to 0 for tabs (so that tabs are shown before typing).
b226ddf
Niklas Baumstark prevent duplicate history items c397fff
Niklas Baumstark make refresh interval configurable
For example, tab completion can happen instantly while history completion shouldn't.
ff8e8aa
Niklas Baumstark make refresh <F5> work as expected a0d0d8e
Niklas Baumstark introduce a utils helper for prototype inheritance d761e42
Niklas Baumstark code cleanup + small bugfixes 386c084
Niklas Baumstark correctly handle selection after refresh ccd7998
Niklas Baumstark fix HTML tag stripping 4cfe44b
Niklas Baumstark make fuzzybox HTML more compact d1364c2
Niklas Baumstark rename "match" method to prevent confusion 66330ac
Niklas Baumstark fix small bug with selected item b23ec4b
Niklas Baumstark fix a bug in the filtering algo that causes caching not to happen 76b981c
Niklas Baumstark sort history by last visit time and raise number of history items to …
…be searched
7c2755b
Niklas Baumstark fix bug when history maxResults is too high e8b4025
Niklas Baumstark add lazy evaluation at several places 392232f
Niklas Baumstark raise number of history items searched f7f40e3
Niklas Baumstark really only update every X milliseconds 0ab64a0
Niklas Baumstark move completion logic to background page
This has the following advantages:
* searching is done in the background, UI responsiveness is improved
* caches are no longer duplicated. This saves RAM and improves performance
3449af0
Niklas Baumstark small tweaks bcc0e02
Niklas Baumstark optimization 7eb205f
Niklas Baumstark small changes f28edd6
Niklas Baumstark add domain completion a la Chrome omnibox 5ee53fc
Niklas Baumstark don't complete tabs in omni mode b56ee27
Niklas Baumstark fix strange whitespace artefacts 09aaab6
Niklas Baumstark fix domain completion bb37bcc
Niklas Baumstark

@philc: I successfully rebased this. Two problems remain that I am aware of:

  1. Issue #411 seems to apply to all Vimium dialogs, including this one, on my machine (Arch Linux x86_64, Chrome 17).
  2. Websites sometimes break the CSS of the box. I could of course incrementally add more and more CSS reset rules to overwrite certain sites' stylesheets, but that's not a final solution. Not sure how to handle this.
Ilya
Collaborator
ilya commented April 12, 2012

I'm not that worried about #1.

How often is #2 happening? I'm no CSS expert but can't you hard reset everything and scope it only to our stuff?

Niklas Baumstark

@ilya: It's not happening too often. As far as I understand, I'd have to "hard reset" every single property to really exclude every possiblity of interference. I'm already assigning the .vimimumReset class to the box, maybe I could do that for every single HTML element if necessary. We could also add !important to the .vimiumReset rules to make them a lot more specific.

I just remembered what problem number 3 was: Decoding the key presses seems to be a non-trivial task. I was unable to figure out a generic way to detect which characters was typed in by the user. The result of this is that the Shift key doesn't work properly for some non-character keys like !@#$.. on a US layout. This might be even more of a problem on different locales (though German special characters seem to work). I will look into this again.

EDIT: I should say that the same applies to the existing bookmark search. I already fixed the previous behaviour where you could only type lowercase letters.

Ilya
Collaborator
ilya commented April 12, 2012

I feel like the third problem was solved in our codebase somewhere already. I did a lot of work back in the day to make sure we supported international keyboards and such.

Niklas Baumstark

@ilya: Hm, at least it wasn't solved properly. There is lib/keyboardUtils.js:getKeyChar, but it's far from reliable from my testing. The most obvious issue was that it didn't let you type uppercase letters, which I patched (maybe in a suboptimal way). Maybe your work was at a different place? To reproduce what I mean, just press b and try to input something like aA!, it comes out as aa1 here.

Ilya
Collaborator
ilya commented April 12, 2012

Works for me on a US keyboard. I guess you're right -- the internationalization is messed up.

Niklas Baumstark

@ilya: Strange.. I have a German keyboard, but the whole system is US-localized. I guess it would be a better idea to use an <input type="text"> to receive the input, to make this a lot more reliable.

Phil Crosby
Owner
philc commented April 12, 2012

I haven't played with it yet, but if you're not using a text input to receive input, please do. There's no reason handling the platform specific shortcuts and editing via the mouse shouldn't work.

Niklas Baumstark

@philc: I'm at it :) I had just copied some of the existing code from the bookmarks search, guess that wasn't the best idea.

Ilya
Collaborator
ilya commented April 12, 2012

@philc you should play with it.

Ilya
Collaborator
ilya commented April 12, 2012

Can this omnibox subsume the bookmarks stuff? I'm really digging it.

Jez Ng
Collaborator
int3 commented April 12, 2012

I'm pretty sure we have the same internationalization problems in bookmarks search and find mode... there are a bunch of open issues somewhere.

And I agree with @ilya, the omnibox should replace the bookmarks search.

Niklas Baumstark

@ilya: Yes, it currently matches domain names, history, bookmarks and tabs. EDIT: Oh, not sure whether I understood this correctly.

Niklas Baumstark

@ilya, @philc, @int3: Fixed the input problem by using an <input>. Still not sure how to go on about the CSS issue best. What do you think of changing the .vimimumReset rules to !important?

Also, has someone an idea why that Flash issue occurs? Can we somehow work around that?

Niklas Baumstark

@ilya, @philc: What's the status here?

Phil Crosby
Owner
philc commented April 25, 2012

@niklasb Next action is on my plate. I'll be using and code reviewing this tonight.

Ilya
Collaborator
ilya commented April 25, 2012

woot!

Phil Crosby philc merged commit a26a2bf into from April 25, 2012
Phil Crosby philc closed this April 25, 2012
Phil Crosby
Owner
philc commented April 25, 2012

This is pretty amazing and the code looks good. I'm merging it into master so it can get some mileage and we can start improving it and fixing bugs on master instead of a branch. I've filed a couple to get us started (#515 and #516).

In the coming days I'll shuffle a few bits around so the style is more uniform with the rest of the Vimium code base, but on the whole the code is nicely structured and documented.

Excellent, excellent work @niklasb.

Phil Crosby
Owner
philc commented April 25, 2012

I'm calling this the "vomnibox" so we have a convenient way to refer to it. Alternate names are welcome.

Ilya
Collaborator
ilya commented April 25, 2012

This is really exciting. I think one major action item is to rip out the existing bookmarks browser.

Jez Ng
Collaborator
int3 commented April 25, 2012

I'm glad we're finally getting a omnibar :) Thanks so much @niklasb!

Re alternate names: Can we just call it 'omnibox'? The 'vom-' syllable reminds me vaguely of an unpleasant digestive phenomenon...

Niklas Baumstark

@philc: Nice!

@int3: Obviously the term "Omnibox" is already taken by Google... But I also don't like vomnibox very much (although I don't really care :P)

Jez Ng
Collaborator
int3 commented April 27, 2012

Ah, I thought Chrome's one was called the 'omnibar', but apparently it has more than one name... well yeah it's not a big deal either way :)

Adam Stankiewicz

Fuzzy match does not work for me on history items..

Phil Crosby
Owner

It works for me, but I also saw it break on @harob's Vimium. There were no results and no exceptions from the content script or background script. I suspect there's some kind of bad history item that we're not handling.

Phil Crosby
Owner

Filed a new bug as #771.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 78 unique commits by 1 author.

Apr 10, 2012
Niklas Baumstark add fuzzy mode 6f589fe
Niklas Baumstark make failing test pass again :) fd549f0
Niklas Baumstark remove trimming from isUrl c808c6a
Niklas Baumstark add possibility to use custom search engines and use "wiki ", "cc ", …
…and ";" (goto) as custom commands
253dc6f
Niklas Baumstark remove useless CSS directive f4416cb
Niklas Baumstark make CSS more specific 2a9c88a
Niklas Baumstark fix some issues with asynchronous filtering and refreshing bd6f3be
Niklas Baumstark make F5 refresh the completions b6a91ff
Niklas Baumstark remove empty leading line 9e6bdef
Niklas Baumstark fix syntax error ef7084e
Niklas Baumstark allow fuzzy completion of HTML-decorated content and implement this f…
…or history and bookmarks
79b0340
Niklas Baumstark allow custom functions as commands, add example in form of forced web…
… search
69ea703
Niklas Baumstark document the HTML matching algorithm better 667f97b
Niklas Baumstark make number of completions configurable 85ae8c6
Niklas Baumstark decrease number of history items 6979cd6
Niklas Baumstark underscore is not a word character in our context 8f126b0
Niklas Baumstark improve relevancy calculation 0bcad93
Niklas Baumstark move some logic from background to content page 3520212
Niklas Baumstark fix relevancy heuristic 642694b
Niklas Baumstark add Google lucky search as command "luck " f0409c5
Niklas Baumstark add tab completion support 53f8158
Niklas Baumstark really get more history items 76b26a8
Niklas Baumstark remove debug statement 516101b
Niklas Baumstark improve string ranking fc545ea
Niklas Baumstark prefer marking continguous characters 4691478
Niklas Baumstark use background page to open URLs 2c5b916
Niklas Baumstark fix bug in query normalization 9c3ea93
Niklas Baumstark restructure fuzzy mode flow 9890e17
Niklas Baumstark add special command for tab completion 9bab5a3
Niklas Baumstark fix search URL building aa5b39f
Niklas Baumstark make CSS more robust 6be4f61
Niklas Baumstark fix ranking algorithm 8e20171
Niklas Baumstark sort results in tab completion mode de0a360
Niklas Baumstark fall back to regex matching for long queries 59b096f
Niklas Baumstark raise regex threshold to query length 15 8179e6d
Niklas Baumstark fix bad English 958dd00
Niklas Baumstark improve perfmance by caching history results in the background page.
Also decrease the number of included results slightly.
6bc1d44
Niklas Baumstark minor optimizations and code cleanup 14cb3e4
Niklas Baumstark improve comments and fix some naming style inconsistencies 2eae98f
Niklas Baumstark DRY up code a9ea93a
Niklas Baumstark add bookmark in "all" completion 82b461b
Niklas Baumstark more DRYing f69fea3
Niklas Baumstark fix small bug 4edbe74
Niklas Baumstark update results list asynchronously to take load from the CPU and impr…
…ove the perceived responsiveness
a9d89d0
Niklas Baumstark fix small bug when closing and reopening dialog in combination with a…
…sync updating
6463714
Niklas Baumstark hide completion list if no completions are available 9fd6faa
Niklas Baumstark force update after pressing Return 3f1fa91
Niklas Baumstark code cleanup 951a853
Niklas Baumstark add HTML helpers f41ebfb
Niklas Baumstark create DOM by HTML 885c633
Niklas Baumstark fix regression in 10a77d25c3 99c19d2
Niklas Baumstark move query length threshold from UI to logic
This enables to set threshold to 0 for tabs (so that tabs are shown before typing).
b226ddf
Niklas Baumstark prevent duplicate history items c397fff
Niklas Baumstark make refresh interval configurable
For example, tab completion can happen instantly while history completion shouldn't.
ff8e8aa
Niklas Baumstark make refresh <F5> work as expected a0d0d8e
Niklas Baumstark introduce a utils helper for prototype inheritance d761e42
Niklas Baumstark code cleanup + small bugfixes 386c084
Niklas Baumstark correctly handle selection after refresh ccd7998
Niklas Baumstark fix HTML tag stripping 4cfe44b
Niklas Baumstark make fuzzybox HTML more compact d1364c2
Niklas Baumstark rename "match" method to prevent confusion 66330ac
Niklas Baumstark fix small bug with selected item b23ec4b
Niklas Baumstark fix a bug in the filtering algo that causes caching not to happen 76b981c
Niklas Baumstark sort history by last visit time and raise number of history items to …
…be searched
7c2755b
Niklas Baumstark fix bug when history maxResults is too high e8b4025
Niklas Baumstark add lazy evaluation at several places 392232f
Niklas Baumstark raise number of history items searched f7f40e3
Niklas Baumstark really only update every X milliseconds 0ab64a0
Niklas Baumstark move completion logic to background page
This has the following advantages:
* searching is done in the background, UI responsiveness is improved
* caches are no longer duplicated. This saves RAM and improves performance
3449af0
Niklas Baumstark small tweaks bcc0e02
Niklas Baumstark optimization 7eb205f
Niklas Baumstark small changes f28edd6
Niklas Baumstark add domain completion a la Chrome omnibox 5ee53fc
Niklas Baumstark don't complete tabs in omni mode b56ee27
Apr 11, 2012
Niklas Baumstark fix strange whitespace artefacts 09aaab6
Niklas Baumstark fix domain completion bb37bcc
Apr 13, 2012
Niklas Baumstark change to real input box 549f38e
Niklas Baumstark improve CSS, fix input width cbe4416
Something went wrong with that request. Please try again.