Fix #167: Add bmarks command for searching through bookmarks

This commit is contained in:
Oliver Blanthorn 2017-11-30 17:02:31 +00:00
parent 8695552fe6
commit 9fc0e9c0cf
No known key found for this signature in database
GPG key ID: 2BB8C36BB504BFF3
3 changed files with 112 additions and 0 deletions

View file

@ -40,6 +40,7 @@ function enableCompletions() {
activeCompletions = [
new Completions.BufferCompletionSource(completionsDiv),
new Completions.HistoryCompletionSource(completionsDiv),
new Completions.BmarkCompletionSource(completionsDiv),
]
const fragment = document.createDocumentFragment()

View file

@ -338,11 +338,109 @@ class HistoryCompletionOption extends CompletionOptionHTML implements Completion
}
}
class BmarkCompletionOption extends CompletionOptionHTML implements CompletionOptionFuse {
public fuseKeys = []
constructor(public value: string, bmark: browser.bookmarks.BookmarkTreeNode) {
super()
if (! bmark.title) {
bmark.title = new URL(bmark.url).host
}
// Push properties we want to fuzmatch on
this.fuseKeys.push(bmark.title, bmark.url)
// Create HTMLElement
// need to download favicon
const favIconUrl = DEFAULT_FAVICON
// const favIconUrl = tab.favIconUrl ? tab.favIconUrl : DEFAULT_FAVICON
this.html = html`<tr class="HistoryCompletionOption option">
<td class="prefix">${"".padEnd(2)}</td>
<td></td>
<td>${bmark.title}</td>
<td><a class="url" target="_blank" href=${bmark.url}>${bmark.url}</a></td>
</tr>`
}
}
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
}
export class BmarkCompletionSource extends CompletionSourceFuse {
public options: BmarkCompletionOption[]
constructor(private _parent) {
super(
[
"bmarks ",
],
"BmarkCompletionSource", "Bookmarks"
)
this._parent.appendChild(this.node)
}
public async filter(exstr: string) {
this.lastExstr = exstr
const [prefix, query] = this.splitOnPrefix(exstr)
// Hide self and stop if prefixes don't match
if (prefix) {
// Show self if prefix and currently hidden
if (this.state === 'hidden') {
this.state = 'normal'
}
} else {
this.state = 'hidden'
return
}
this.options = (await this.scoreOptions(query, 10)).map(
page => new BmarkCompletionOption(page.url, page)
)
this.updateChain()
}
updateChain() {
// Options are pre-trimmed to the right length.
this.options.forEach(option => option.state = 'normal')
// Call concrete class
this.updateDisplay()
}
onInput() {}
private async scoreOptions(query: string, n: number) {
// Search bookmarks, dedupe and sort by frecency
let bookmarks = await browserBg.bookmarks.search({query})
bookmarks = bookmarks.filter(b=>{
try {
return new URL(b.url)
} catch (e) {
return false;
}
})
bookmarks.sort((a, b) => b.dateAdded - a.dateAdded)
return bookmarks.slice(0, n)
}
select(option: CompletionOption) {
if (this.lastExstr !== undefined && option !== undefined) {
this.completion = "open " + option.value
option.state = 'focused'
this.lastFocused = option
} else {
throw new Error("lastExstr and option must be defined!")
}
}
}
export class HistoryCompletionSource extends CompletionSourceFuse {
public options: HistoryCompletionOption[]

View file

@ -42,6 +42,19 @@ input {
border-spacing: 0;
table-layout: fixed;
}
/* redundancy 2: redundancy 2: more redundancy */
#completions .BmarkCompletionSource {
max-height: calc(20 * var(--option-height));
min-height: calc(10 * var(--option-height));
}
#completions .BmarkCompletionSource table {
width: 100%;
font-size: 9pt;
border-spacing: 0;
table-layout: fixed;
}
/* redundancy ends */
#completions .BufferCompletionSource {