mirror of
https://github.com/huhu/rust-search-extension
synced 2024-11-13 23:27:13 +00:00
Add RustSearchOmnibox class
This commit is contained in:
parent
2cd58ec1d6
commit
68d011e310
2 changed files with 346 additions and 305 deletions
334
extension/lib.js
Normal file
334
extension/lib.js
Normal file
|
@ -0,0 +1,334 @@
|
|||
import settings from "./settings.js";
|
||||
import Statistics from "./statistics.js";
|
||||
import HistoryCommand from "./core/command/history.js";
|
||||
import CrateDocManager from "./crate-manager.js";
|
||||
import { Compat } from "./core/index.js";
|
||||
import {
|
||||
LINT_URL,
|
||||
REDIRECT_URL,
|
||||
} from "./constants.js";
|
||||
|
||||
export default class RustSearchOmnibox {
|
||||
static async run({
|
||||
omnibox,
|
||||
stdSearcher,
|
||||
nightlySearcher,
|
||||
crateDocSearcher,
|
||||
crateSearcher,
|
||||
attributeSearcher,
|
||||
bookSearcher,
|
||||
caniuseSearcher,
|
||||
lintSearcher,
|
||||
commandManager,
|
||||
}) {
|
||||
// All dynamic setting items. Those items will been updated
|
||||
// in chrome.storage.onchange listener callback.
|
||||
let isOfflineMode = await settings.isOfflineMode;
|
||||
let offlineDocPath = await settings.offlineDocPath;
|
||||
let defaultSearch = await settings.defaultSearch;
|
||||
let crateRegistry = await settings.crateRegistry;
|
||||
|
||||
function formatDoc(index, doc) {
|
||||
let content = doc.href;
|
||||
let description = doc.displayPath + `<match>${doc.name}</match>`;
|
||||
if (doc.desc) {
|
||||
description += ` - <dim>${Compat.escape(Compat.eliminateTags(doc.desc))}</dim>`;
|
||||
}
|
||||
|
||||
if (doc.queryType === "s" || doc.queryType === "src") {
|
||||
let url = new URL(doc.href);
|
||||
url.search = "?mode=src";
|
||||
content = url.toString();
|
||||
description = `[Source code] ${description}`;
|
||||
}
|
||||
return { content, description };
|
||||
}
|
||||
|
||||
function wrapCrateSearchAppendix(appendix) {
|
||||
return [
|
||||
appendix,
|
||||
{
|
||||
content: "remind",
|
||||
description: `Remind: <dim>We only indexed the top 20K crates. Sorry for the inconvenience if your desired crate not show.</dim>`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
omnibox.bootstrap({
|
||||
onSearch: (query) => {
|
||||
return stdSearcher.search(query);
|
||||
},
|
||||
onFormat: formatDoc,
|
||||
onAppend: (query) => {
|
||||
return [{
|
||||
content: stdSearcher.getSearchUrl(query),
|
||||
description: `Search Rust docs <match>${query}</match> on ${isOfflineMode ? "offline mode" : stdSearcher.getRootPath()}`,
|
||||
}];
|
||||
},
|
||||
onEmptyNavigate: (content, disposition) => {
|
||||
commandManager.handleCommandEnterEvent(content, disposition);
|
||||
},
|
||||
beforeNavigate: async (query, content) => {
|
||||
if (content && /^@\w+$/i.test(content.trim())) {
|
||||
// Case: @crate, redirect to that crate's docs.rs page
|
||||
return `https://docs.rs/${content.replace("@", "")}`;
|
||||
} else if (content && /^https?.*\/~\/\*\/.*/ig.test(content)) {
|
||||
// Sanitize docs url which from all crates doc search mode. (Prefix with "~")
|
||||
// Here is the url instance: https://docs.rs/~/*/reqwest/fn.get.html
|
||||
let [_, __, libName] = new URL(content).pathname.slice(1).split("/");
|
||||
let crate = await CrateDocManager.getCrateByName(libName);
|
||||
const crateVersion = await settings.keepCratesUpToDate ? "latest" : crate.version;
|
||||
return content.replace("/~/", `/${crate.crateName || libName}/`).replace("/*/", `/${crateVersion}/`);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
},
|
||||
afterNavigated: async (query, result) => {
|
||||
// Ignore the command history
|
||||
if (query?.startsWith(":")) return;
|
||||
|
||||
// Only keep the latest 100 of search history.
|
||||
let historyItem = await HistoryCommand.record(query, result, 100);
|
||||
let statistics = await Statistics.load();
|
||||
await statistics.record(historyItem, true);
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addRegexQueryEvent(/^s(?:rc)?:/i, {
|
||||
name: "Source code",
|
||||
onSearch: (query) => {
|
||||
return stdSearcher.search(query);
|
||||
},
|
||||
onFormat: formatDoc,
|
||||
onAppend: (query) => {
|
||||
return [{
|
||||
content: stdSearcher.getSearchUrl(query),
|
||||
description: `Search Rust docs <match>${query}</match> on ${isOfflineMode ? "offline mode" : stdSearcher.getRootPath()}`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
// Nightly std docs search
|
||||
omnibox.addPrefixQueryEvent("/", {
|
||||
name: "Nightly docs",
|
||||
onSearch: (query) => {
|
||||
query = query.replaceAll("/", "").trim();
|
||||
return nightlySearcher.search(query);
|
||||
},
|
||||
onFormat: (index, doc) => {
|
||||
let { content, description } = formatDoc(index, doc);
|
||||
return { content, description: '[Nightly] ' + description };
|
||||
},
|
||||
onAppend: (query) => {
|
||||
query = query.replaceAll("/", "").trim();
|
||||
return [{
|
||||
content: nightlySearcher.getSearchUrl(query),
|
||||
description: `Search nightly Rust docs <match>${query}</match> on ${nightlySearcher.getRootPath()}`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("~", {
|
||||
name: "External docs",
|
||||
isDefaultSearch: () => {
|
||||
return defaultSearch.thirdPartyDocs;
|
||||
},
|
||||
searchPriority: 1,
|
||||
onSearch: async (query) => {
|
||||
return await crateDocSearcher.searchAll(query);
|
||||
},
|
||||
onFormat: formatDoc,
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("@", {
|
||||
name: "Crate docs",
|
||||
onSearch: async (query) => {
|
||||
return await crateDocSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, item) => {
|
||||
if ('content' in item) {
|
||||
// 1. Crate list header.
|
||||
// 2. Crate result footer
|
||||
return item;
|
||||
} else if ('href' in item) {
|
||||
return formatDoc(index, item);
|
||||
} else {
|
||||
// Crate name list.
|
||||
let content = `@${item.name}`;
|
||||
return {
|
||||
content,
|
||||
description: `<match>${content}</match> v${item.version} - <dim>${Compat.escape(Compat.eliminateTags(item.doc))}</dim>`,
|
||||
};
|
||||
}
|
||||
},
|
||||
onAppend: () => {
|
||||
return [{
|
||||
content: chrome.runtime.getURL("manage/crates.html"),
|
||||
description: `Remind: <dim>Select here to manage all your indexed crates</dim>`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("!", {
|
||||
name: "docs.rs",
|
||||
isDefaultSearch: () => {
|
||||
return defaultSearch.docsRs;
|
||||
},
|
||||
searchPriority: 2,
|
||||
onSearch: (query) => {
|
||||
return crateSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, crate) => {
|
||||
return {
|
||||
content: `https://docs.rs/${crate.id}`,
|
||||
description: `${Compat.capitalize("docs.rs")}: <match>${crate.id}</match> v${crate.version} - <dim>${Compat.escape(Compat.eliminateTags(crate.description))}</dim>`,
|
||||
};
|
||||
},
|
||||
onAppend: (query) => {
|
||||
let keyword = query.replace(/[!\s]/g, "");
|
||||
return wrapCrateSearchAppendix({
|
||||
content: "https://docs.rs/releases/search?query=" + encodeURIComponent(keyword),
|
||||
description: "Search Rust crates for " + `<match>${keyword}</match>` + " on https://docs.rs",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("!!", {
|
||||
name: "crates.io",
|
||||
onSearch: (query) => {
|
||||
return crateSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, crate) => {
|
||||
return {
|
||||
content: `https://${crateRegistry}/crates/${crate.id}`,
|
||||
description: `${Compat.capitalize(crateRegistry)}: <match>${crate.id}</match> v${crate.version} - <dim>${Compat.escape(Compat.eliminateTags(crate.description))}</dim>`,
|
||||
};
|
||||
},
|
||||
onAppend: (query) => {
|
||||
let keyword = query.replace(/[!\s]/g, "");
|
||||
return wrapCrateSearchAppendix({
|
||||
content: `https://${crateRegistry}/search?q=` + encodeURIComponent(keyword),
|
||||
description: "Search Rust crates for " + `<match>${keyword}</match>` + ` on https://${crateRegistry}`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("!!!", {
|
||||
name: "Repository",
|
||||
onSearch: (query) => {
|
||||
return crateSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, crate) => {
|
||||
return {
|
||||
content: `${REDIRECT_URL}?crate=${crate.id}`,
|
||||
description: `${Compat.capitalize("repository")}: <match>${crate.id}</match> v${crate.version} - <dim>${Compat.escape(Compat.eliminateTags(crate.description))}</dim>`,
|
||||
};
|
||||
},
|
||||
onAppend: (query) => {
|
||||
let keyword = query.replace(/[!\s]/g, "");
|
||||
return wrapCrateSearchAppendix({
|
||||
content: "https://github.com/search?q=" + encodeURIComponent(keyword),
|
||||
description: "Search Rust crates for " + `<match>${keyword}</match>` + " on https://github.com",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("#", {
|
||||
name: "Attributes",
|
||||
isDefaultSearch: () => {
|
||||
return defaultSearch.attributes;
|
||||
},
|
||||
searchPriority: 3,
|
||||
onSearch: (query) => {
|
||||
query = query.replace(/[[\]]/g, "");
|
||||
return attributeSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, attribute) => {
|
||||
return {
|
||||
content: attribute.href,
|
||||
description: `Attribute: <match>#[${attribute.name}]</match> <dim>${Compat.escape(attribute.description)}</dim>`,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("?", {
|
||||
name: "Can I use",
|
||||
onSearch: (query) => {
|
||||
return caniuseSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, feat, query) => {
|
||||
return {
|
||||
content: `https://caniuse.rs/features/${feat.slug}`,
|
||||
description: `Can I use: <match>${Compat.escape(feat.match)}</match> [${feat.version}] - <dim>${Compat.escape(feat.description)}</dim>`
|
||||
};
|
||||
},
|
||||
onAppend: () => {
|
||||
return [{
|
||||
content: ":rfc",
|
||||
description: `Remind: <dim>you can use</dim> :rfc <dim>command to search all Rust RFCs.</dim>`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addRegexQueryEvent(/^`?e\d{2,4}`?$/i, {
|
||||
name: "Error code",
|
||||
onSearch: (query) => {
|
||||
query = query.replace("`", "");
|
||||
let baseIndex = parseInt(query.slice(1).padEnd(4, '0'));
|
||||
let result = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let errorIndex = 'E' + String(baseIndex++).padStart(4, "0").toUpperCase();
|
||||
result.push(errorIndex);
|
||||
}
|
||||
let baseUrl = isOfflineMode ? offlineDocPath : 'https://doc.rust-lang.org/';
|
||||
return result.map(errorCode => {
|
||||
return {
|
||||
content: `${baseUrl}error_codes/${errorCode}.html`,
|
||||
description: `Open error code <match>${errorCode}</match> on ${isOfflineMode ? 'offline mode' : 'https://doc.rust-lang.org/error_codes/error-index.html'}`,
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("%", {
|
||||
name: "Books",
|
||||
onSearch: (query) => {
|
||||
return bookSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, page) => {
|
||||
let parentTitles = page.parentTitles || [];
|
||||
return {
|
||||
content: page.url,
|
||||
description: `${[...parentTitles.map(t => Compat.escape(t)), `<match>${Compat.escape(page.title)}</match>`].join(" > ")} - <dim>${page.name}</dim>`
|
||||
}
|
||||
},
|
||||
onAppend: () => {
|
||||
return [{
|
||||
content: ":book",
|
||||
description: `Remind: <dim>you can use</dim> :book <dim>command to search all Rust books.</dim>`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent(">", {
|
||||
name: "Clippy lints",
|
||||
onSearch: (query) => {
|
||||
return lintSearcher.search(query);
|
||||
},
|
||||
onFormat: (_, lint) => {
|
||||
return {
|
||||
content: `${LINT_URL}#${lint.name}`,
|
||||
description: `Clippy lint: [${lint.level}] <match>${lint.name}</match> - <dim>${Compat.escape(Compat.eliminateTags(lint.description))}</dim>`,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent(":", {
|
||||
name: "Commands",
|
||||
onSearch: async (query) => {
|
||||
return commandManager.execute(query);
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
import settings from "./settings.js";
|
||||
import Statistics from "./statistics.js";
|
||||
import attributesIndex from "./index/attributes.js";
|
||||
import IndexManager from "./index-manager.js";
|
||||
import CrateSearch from "./search/crate.js";
|
||||
|
@ -19,14 +18,11 @@ import SimpleCommand from "./core/command/simple.js";
|
|||
import OpenCommand from "./core/command/open.js";
|
||||
import HistoryCommand from "./core/command/history.js";
|
||||
import CommandManager from "./core/command/manager.js";
|
||||
import CrateDocManager from "./crate-manager.js";
|
||||
import { Compat } from "./core/index.js";
|
||||
import {
|
||||
INDEX_UPDATE_URL,
|
||||
LINT_URL,
|
||||
REDIRECT_URL,
|
||||
RUST_RELEASE_README_URL,
|
||||
} from "./constants.js";
|
||||
import RustSearchOmnibox from "./lib.js";
|
||||
|
||||
|
||||
async function start(omnibox) {
|
||||
|
@ -96,306 +92,17 @@ async function start(omnibox) {
|
|||
return "https://doc.rust-lang.org/nightly/";
|
||||
});
|
||||
|
||||
let formatDoc = (index, doc) => {
|
||||
let content = doc.href;
|
||||
let description = doc.displayPath + `<match>${doc.name}</match>`;
|
||||
if (doc.desc) {
|
||||
description += ` - <dim>${Compat.escape(Compat.eliminateTags(doc.desc))}</dim>`;
|
||||
}
|
||||
|
||||
if (doc.queryType === "s" || doc.queryType === "src") {
|
||||
let url = new URL(doc.href);
|
||||
url.search = "?mode=src";
|
||||
content = url.toString();
|
||||
description = `[Source code] ${description}`;
|
||||
}
|
||||
return { content, description };
|
||||
};
|
||||
|
||||
omnibox.bootstrap({
|
||||
onSearch: (query) => {
|
||||
return stdSearcher.search(query);
|
||||
},
|
||||
onFormat: formatDoc,
|
||||
onAppend: (query) => {
|
||||
return [{
|
||||
content: stdSearcher.getSearchUrl(query),
|
||||
description: `Search Rust docs <match>${query}</match> on ${isOfflineMode ? "offline mode" : stdSearcher.getRootPath()}`,
|
||||
}];
|
||||
},
|
||||
onEmptyNavigate: (content, disposition) => {
|
||||
commandManager.handleCommandEnterEvent(content, disposition);
|
||||
},
|
||||
beforeNavigate: async (query, content) => {
|
||||
if (content && /^@\w+$/i.test(content.trim())) {
|
||||
// Case: @crate, redirect to that crate's docs.rs page
|
||||
return `https://docs.rs/${content.replace("@", "")}`;
|
||||
} else if (content && /^https?.*\/~\/\*\/.*/ig.test(content)) {
|
||||
// Sanitize docs url which from all crates doc search mode. (Prefix with "~")
|
||||
// Here is the url instance: https://docs.rs/~/*/reqwest/fn.get.html
|
||||
let [_, __, libName] = new URL(content).pathname.slice(1).split("/");
|
||||
let crate = await CrateDocManager.getCrateByName(libName);
|
||||
const crateVersion = await settings.keepCratesUpToDate ? "latest" : crate.version;
|
||||
return content.replace("/~/", `/${crate.crateName || libName}/`).replace("/*/", `/${crateVersion}/`);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
},
|
||||
afterNavigated: async (query, result) => {
|
||||
// Ignore the command history
|
||||
if (query?.startsWith(":")) return;
|
||||
|
||||
// Only keep the latest 100 of search history.
|
||||
let historyItem = await HistoryCommand.record(query, result, 100);
|
||||
let statistics = await Statistics.load();
|
||||
await statistics.record(historyItem, true);
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addRegexQueryEvent(/^s(?:rc)?:/i, {
|
||||
name: "Source code",
|
||||
onSearch: (query) => {
|
||||
return stdSearcher.search(query);
|
||||
},
|
||||
onFormat: formatDoc,
|
||||
onAppend: (query) => {
|
||||
return [{
|
||||
content: stdSearcher.getSearchUrl(query),
|
||||
description: `Search Rust docs <match>${query}</match> on ${isOfflineMode ? "offline mode" : stdSearcher.getRootPath()}`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
// Nightly std docs search
|
||||
omnibox.addPrefixQueryEvent("/", {
|
||||
name: "Nightly docs",
|
||||
onSearch: (query) => {
|
||||
query = query.replaceAll("/", "").trim();
|
||||
return nightlySearcher.search(query);
|
||||
},
|
||||
onFormat: (index, doc) => {
|
||||
let { content, description } = formatDoc(index, doc);
|
||||
return { content, description: '[Nightly] ' + description };
|
||||
},
|
||||
onAppend: (query) => {
|
||||
query = query.replaceAll("/", "").trim();
|
||||
return [{
|
||||
content: nightlySearcher.getSearchUrl(query),
|
||||
description: `Search nightly Rust docs <match>${query}</match> on ${nightlySearcher.getRootPath()}`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("~", {
|
||||
name: "External docs",
|
||||
isDefaultSearch: () => {
|
||||
return defaultSearch.thirdPartyDocs;
|
||||
},
|
||||
searchPriority: 1,
|
||||
onSearch: async (query) => {
|
||||
return await crateDocSearcher.searchAll(query);
|
||||
},
|
||||
onFormat: formatDoc,
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("@", {
|
||||
name: "Crate docs",
|
||||
onSearch: async (query) => {
|
||||
return await crateDocSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, item) => {
|
||||
if ('content' in item) {
|
||||
// 1. Crate list header.
|
||||
// 2. Crate result footer
|
||||
return item;
|
||||
} else if ('href' in item) {
|
||||
return formatDoc(index, item);
|
||||
} else {
|
||||
// Crate name list.
|
||||
let content = `@${item.name}`;
|
||||
return {
|
||||
content,
|
||||
description: `<match>${content}</match> v${item.version} - <dim>${Compat.escape(Compat.eliminateTags(item.doc))}</dim>`,
|
||||
};
|
||||
}
|
||||
},
|
||||
onAppend: () => {
|
||||
return [{
|
||||
content: chrome.runtime.getURL("manage/crates.html"),
|
||||
description: `Remind: <dim>Select here to manage all your indexed crates</dim>`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
function wrapCrateSearchAppendix(appendix) {
|
||||
return [
|
||||
appendix,
|
||||
{
|
||||
content: "remind",
|
||||
description: `Remind: <dim>We only indexed the top 20K crates. Sorry for the inconvenience if your desired crate not show.</dim>`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
omnibox.addPrefixQueryEvent("!", {
|
||||
name: "docs.rs",
|
||||
isDefaultSearch: () => {
|
||||
return defaultSearch.docsRs;
|
||||
},
|
||||
searchPriority: 2,
|
||||
onSearch: (query) => {
|
||||
return crateSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, crate) => {
|
||||
return {
|
||||
content: `https://docs.rs/${crate.id}`,
|
||||
description: `${Compat.capitalize("docs.rs")}: <match>${crate.id}</match> v${crate.version} - <dim>${Compat.escape(Compat.eliminateTags(crate.description))}</dim>`,
|
||||
};
|
||||
},
|
||||
onAppend: (query) => {
|
||||
let keyword = query.replace(/[!\s]/g, "");
|
||||
return wrapCrateSearchAppendix({
|
||||
content: "https://docs.rs/releases/search?query=" + encodeURIComponent(keyword),
|
||||
description: "Search Rust crates for " + `<match>${keyword}</match>` + " on https://docs.rs",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("!!", {
|
||||
name: "crates.io",
|
||||
onSearch: (query) => {
|
||||
return crateSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, crate) => {
|
||||
return {
|
||||
content: `https://${crateRegistry}/crates/${crate.id}`,
|
||||
description: `${Compat.capitalize(crateRegistry)}: <match>${crate.id}</match> v${crate.version} - <dim>${Compat.escape(Compat.eliminateTags(crate.description))}</dim>`,
|
||||
};
|
||||
},
|
||||
onAppend: (query) => {
|
||||
let keyword = query.replace(/[!\s]/g, "");
|
||||
return wrapCrateSearchAppendix({
|
||||
content: `https://${crateRegistry}/search?q=` + encodeURIComponent(keyword),
|
||||
description: "Search Rust crates for " + `<match>${keyword}</match>` + ` on https://${crateRegistry}`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("!!!", {
|
||||
name: "Repository",
|
||||
onSearch: (query) => {
|
||||
return crateSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, crate) => {
|
||||
return {
|
||||
content: `${REDIRECT_URL}?crate=${crate.id}`,
|
||||
description: `${Compat.capitalize("repository")}: <match>${crate.id}</match> v${crate.version} - <dim>${Compat.escape(Compat.eliminateTags(crate.description))}</dim>`,
|
||||
};
|
||||
},
|
||||
onAppend: (query) => {
|
||||
let keyword = query.replace(/[!\s]/g, "");
|
||||
return wrapCrateSearchAppendix({
|
||||
content: "https://github.com/search?q=" + encodeURIComponent(keyword),
|
||||
description: "Search Rust crates for " + `<match>${keyword}</match>` + " on https://github.com",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("#", {
|
||||
name: "Attributes",
|
||||
isDefaultSearch: () => {
|
||||
return defaultSearch.attributes;
|
||||
},
|
||||
searchPriority: 3,
|
||||
onSearch: (query) => {
|
||||
query = query.replace(/[[\]]/g, "");
|
||||
return attributeSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, attribute) => {
|
||||
return {
|
||||
content: attribute.href,
|
||||
description: `Attribute: <match>#[${attribute.name}]</match> <dim>${Compat.escape(attribute.description)}</dim>`,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("?", {
|
||||
name: "Can I use",
|
||||
onSearch: (query) => {
|
||||
return caniuseSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, feat, query) => {
|
||||
return {
|
||||
content: `https://caniuse.rs/features/${feat.slug}`,
|
||||
description: `Can I use: <match>${Compat.escape(feat.match)}</match> [${feat.version}] - <dim>${Compat.escape(feat.description)}</dim>`
|
||||
};
|
||||
},
|
||||
onAppend: () => {
|
||||
return [{
|
||||
content: ":rfc",
|
||||
description: `Remind: <dim>you can use</dim> :rfc <dim>command to search all Rust RFCs.</dim>`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addRegexQueryEvent(/^`?e\d{2,4}`?$/i, {
|
||||
name: "Error code",
|
||||
onSearch: (query) => {
|
||||
query = query.replace("`", "");
|
||||
let baseIndex = parseInt(query.slice(1).padEnd(4, '0'));
|
||||
let result = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let errorIndex = 'E' + String(baseIndex++).padStart(4, "0").toUpperCase();
|
||||
result.push(errorIndex);
|
||||
}
|
||||
let baseUrl = isOfflineMode ? offlineDocPath : 'https://doc.rust-lang.org/';
|
||||
return result.map(errorCode => {
|
||||
return {
|
||||
content: `${baseUrl}error_codes/${errorCode}.html`,
|
||||
description: `Open error code <match>${errorCode}</match> on ${isOfflineMode ? 'offline mode' : 'https://doc.rust-lang.org/error_codes/error-index.html'}`,
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent("%", {
|
||||
name: "Books",
|
||||
onSearch: (query) => {
|
||||
return bookSearcher.search(query);
|
||||
},
|
||||
onFormat: (index, page) => {
|
||||
let parentTitles = page.parentTitles || [];
|
||||
return {
|
||||
content: page.url,
|
||||
description: `${[...parentTitles.map(t => Compat.escape(t)), `<match>${Compat.escape(page.title)}</match>`].join(" > ")} - <dim>${page.name}</dim>`
|
||||
}
|
||||
},
|
||||
onAppend: () => {
|
||||
return [{
|
||||
content: ":book",
|
||||
description: `Remind: <dim>you can use</dim> :book <dim>command to search all Rust books.</dim>`,
|
||||
}];
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent(">", {
|
||||
name: "Clippy lints",
|
||||
onSearch: (query) => {
|
||||
return lintSearcher.search(query);
|
||||
},
|
||||
onFormat: (_, lint) => {
|
||||
return {
|
||||
content: `${LINT_URL}#${lint.name}`,
|
||||
description: `Clippy lint: [${lint.level}] <match>${lint.name}</match> - <dim>${Compat.escape(Compat.eliminateTags(lint.description))}</dim>`,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
omnibox.addPrefixQueryEvent(":", {
|
||||
name: "Commands",
|
||||
onSearch: async (query) => {
|
||||
return commandManager.execute(query);
|
||||
},
|
||||
RustSearchOmnibox.run({
|
||||
omnibox,
|
||||
stdSearcher,
|
||||
nightlySearcher,
|
||||
crateDocSearcher,
|
||||
crateSearcher,
|
||||
attributeSearcher,
|
||||
bookSearcher,
|
||||
caniuseSearcher,
|
||||
lintSearcher,
|
||||
commandManager,
|
||||
});
|
||||
|
||||
if (!omnibox.extensionMode) return;
|
||||
|
|
Loading…
Reference in a new issue