Files
obsidian_note/.obsidian/plugins/obsidian-another-quick-switcher/main.js
2025-12-04 09:12:56 +08:00

6032 lines
208 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// node_modules/ts-deepmerge/dist/index.js
var require_dist = __commonJS({
"node_modules/ts-deepmerge/dist/index.js"(exports) {
"use strict";
var __assign = exports && exports.__assign || function() {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = exports && exports.__read || function(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
} catch (error) {
e = { error };
} finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
} finally {
if (e)
throw e.error;
}
}
return ar;
};
var __spreadArray = exports && exports.__spreadArray || function(to, from, pack) {
if (pack || arguments.length === 2)
for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar)
ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
var isObject = function(obj) {
if (typeof obj === "object" && obj !== null) {
if (typeof Object.getPrototypeOf === "function") {
var prototype = Object.getPrototypeOf(obj);
return prototype === Object.prototype || prototype === null;
}
return Object.prototype.toString.call(obj) === "[object Object]";
}
return false;
};
var merge3 = function() {
var objects = [];
for (var _i = 0; _i < arguments.length; _i++) {
objects[_i] = arguments[_i];
}
return objects.reduce(function(result, current) {
if (Array.isArray(current)) {
throw new TypeError("Arguments provided to ts-deepmerge must be objects, not arrays.");
}
Object.keys(current).forEach(function(key) {
if (["__proto__", "constructor", "prototype"].includes(key)) {
return;
}
if (Array.isArray(result[key]) && Array.isArray(current[key])) {
result[key] = merge3.options.mergeArrays ? Array.from(new Set(result[key].concat(current[key]))) : current[key];
} else if (isObject(result[key]) && isObject(current[key])) {
result[key] = merge3(result[key], current[key]);
} else {
result[key] = current[key];
}
});
return result;
}, {});
};
var defaultOptions = {
mergeArrays: true
};
merge3.options = defaultOptions;
merge3.withOptions = function(options) {
var objects = [];
for (var _i = 1; _i < arguments.length; _i++) {
objects[_i - 1] = arguments[_i];
}
merge3.options = __assign({ mergeArrays: true }, options);
var result = merge3.apply(void 0, __spreadArray([], __read(objects), false));
merge3.options = defaultOptions;
return result;
};
exports.default = merge3;
}
});
// src/main.ts
var main_exports = {};
__export(main_exports, {
default: () => AnotherQuickSwitcher
});
module.exports = __toCommonJS(main_exports);
var import_obsidian13 = require("obsidian");
var import_ts_deepmerge2 = __toESM(require_dist());
// src/app-helper.ts
var import_obsidian = require("obsidian");
var import_ts_deepmerge = __toESM(require_dist());
// src/errors.ts
var ExhaustiveError = class extends Error {
constructor(value, message = `Unsupported type: ${value}`) {
super(message);
}
};
// src/utils/collection-helper.ts
var range = (n) => [...Array(n).keys()];
var mapValues = (obj, to) => Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, to(value)])
);
var mapKeys = (obj, to) => Object.fromEntries(
Object.entries(obj).map(([key, value]) => [to(key), value])
);
var sorter = (toOrdered, order = "asc") => {
return (a, b) => order === "asc" ? toOrdered(a) > toOrdered(b) ? 1 : toOrdered(b) > toOrdered(a) ? -1 : 0 : toOrdered(a) < toOrdered(b) ? 1 : toOrdered(b) < toOrdered(a) ? -1 : 0;
};
var groupBy = (values, toKey) => {
const grouped = {};
for (const value of values) {
const key = toKey(value);
if (!grouped[key]) {
grouped[key] = [];
}
grouped[key].push(value);
}
return grouped;
};
var keyBy = (values, toKey) => {
const indexing = {};
for (const value of values) {
const key = toKey(value);
indexing[key] = value;
}
return indexing;
};
var count = (values) => {
const ret = {};
for (const value of values) {
if (ret[value]) {
ret[value]++;
} else {
ret[value] = 1;
}
}
return ret;
};
function flatten(matrix) {
return matrix.reduce((a, c) => {
a.push(...c);
return a;
}, []);
}
function uniq(values) {
return [...new Set(values)];
}
function uniqBy(values, fn) {
const m = /* @__PURE__ */ new Map();
for (const x of values) {
const k = fn(x);
if (!m.has(k)) {
m.set(k, x);
}
}
return Array.from(m.values());
}
function uniqFlatMap(values, mapper) {
return uniq(flatten(values.map(mapper)));
}
function intersection(matrix) {
return matrix.length === 0 ? [] : matrix.reduce((acc, xs) => acc.filter((x) => xs.includes(x)));
}
var minBy = (collection, toNum) => {
const select = (a, b) => toNum(a) <= toNum(b) ? a : b;
return collection.reduce(select);
};
function includeItems(items, patterns, toPath) {
return patterns.length === 0 ? items : items.filter((x) => patterns.some((p) => toPath(x).startsWith(p)));
}
function excludeItems(items, patterns, toPath) {
return patterns.length === 0 ? items : items.filter((x) => !patterns.some((p) => toPath(x).startsWith(p)));
}
function equalsAsSet(ary1, ary2) {
return [...ary1].sort().join() === [...ary2].sort().join();
}
function mirrorMap(collection, toValue) {
return collection.reduce(
(p, c) => {
const v = toValue(c);
p[v] = v;
return p;
},
{}
);
}
function mirror(collection) {
return mirrorMap(collection, (x) => x);
}
function omitBy(obj, shouldOmit) {
const cloned = { ...obj };
for (const [k, v] of Object.entries(cloned)) {
if (shouldOmit(k, v)) {
delete cloned[k];
}
}
return cloned;
}
// src/utils/path.ts
function basename(path, ext) {
var _a, _b;
const name = (_b = (_a = path.match(/.+[\\/]([^\\/]+)[\\/]?$/)) == null ? void 0 : _a[1]) != null ? _b : path;
return ext && name.endsWith(ext) ? name.replace(ext, "") : name;
}
function extname(path) {
const ext = basename(path).split(".").slice(1).pop();
return ext ? `.${ext}` : "";
}
function dirname(path) {
var _a, _b;
return (_b = (_a = path.match(/(.+)[\\/].+$/)) == null ? void 0 : _a[1]) != null ? _b : ".";
}
function normalizePath(path) {
return path.replace(/\\/g, "/").replace(/\/+/g, "/");
}
function normalizeRelativePath(path, base) {
const sep = /[\\/]/;
let es = [];
path.split(sep).forEach((x, i) => {
if (i === 0 && x === ".") {
es = base.split("/");
return;
}
if (x === "..") {
if (i === 0) {
es = base.split("/");
}
es = dirname(es.join("/")).split("/").filter((x2) => x2 !== ".");
return;
}
es = [...es, x];
});
const r = es.filter((x) => x !== "").join("/");
return base[0] === "/" ? `/${r}` : r;
}
function isExcalidraw(file) {
if (!file) {
return false;
}
return file.path.endsWith(".excalidraw.md") || // old version
file.path.endsWith(".excalidraw");
}
// src/utils/diacritics-map.ts
var defaultDiacriticsRemovalMap = [
{
base: "A",
letters: "A\u24B6\uFF21\xC0\xC1\xC2\u1EA6\u1EA4\u1EAA\u1EA8\xC3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\xC4\u01DE\u1EA2\xC5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F"
},
{ base: "AA", letters: "\uA732" },
{ base: "AE", letters: "\xC6\u01FC\u01E2" },
{ base: "AO", letters: "\uA734" },
{ base: "AU", letters: "\uA736" },
{ base: "AV", letters: "\uA738\uA73A" },
{ base: "AY", letters: "\uA73C" },
{
base: "B",
letters: "B\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181"
},
{
base: "C",
letters: "C\u24B8\uFF23\u0106\u0108\u010A\u010C\xC7\u1E08\u0187\u023B\uA73E"
},
{
base: "D",
letters: "D\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\xD0"
},
{ base: "DZ", letters: "\u01F1\u01C4" },
{ base: "Dz", letters: "\u01F2\u01C5" },
{
base: "E",
letters: "E\u24BA\uFF25\xC8\xC9\xCA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\xCB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E"
},
{ base: "F", letters: "F\u24BB\uFF26\u1E1E\u0191\uA77B" },
{
base: "G",
letters: "G\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E"
},
{
base: "H",
letters: "H\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D"
},
{
base: "I",
letters: "I\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197"
},
{ base: "J", letters: "J\u24BF\uFF2A\u0134\u0248" },
{
base: "K",
letters: "K\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2"
},
{
base: "L",
letters: "L\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780"
},
{ base: "LJ", letters: "\u01C7" },
{ base: "Lj", letters: "\u01C8" },
{ base: "M", letters: "M\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C" },
{
base: "N",
letters: "N\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4"
},
{ base: "NJ", letters: "\u01CA" },
{ base: "Nj", letters: "\u01CB" },
{
base: "O",
letters: "O\u24C4\uFF2F\xD2\xD3\xD4\u1ED2\u1ED0\u1ED6\u1ED4\xD5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\xD6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\xD8\u01FE\u0186\u019F\uA74A\uA74C"
},
{ base: "OI", letters: "\u01A2" },
{ base: "OO", letters: "\uA74E" },
{ base: "OU", letters: "\u0222" },
{ base: "OE", letters: "\x8C\u0152" },
{ base: "oe", letters: "\x9C\u0153" },
{
base: "P",
letters: "P\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754"
},
{ base: "Q", letters: "Q\u24C6\uFF31\uA756\uA758\u024A" },
{
base: "R",
letters: "R\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782"
},
{
base: "S",
letters: "S\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784"
},
{
base: "T",
letters: "T\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786"
},
{ base: "TZ", letters: "\uA728" },
{
base: "U",
letters: "U\u24CA\uFF35\xD9\xDA\xDB\u0168\u1E78\u016A\u1E7A\u016C\xDC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244"
},
{ base: "V", letters: "V\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245" },
{ base: "VY", letters: "\uA760" },
{
base: "W",
letters: "W\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72"
},
{ base: "X", letters: "X\u24CD\uFF38\u1E8A\u1E8C" },
{
base: "Y",
letters: "Y\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE"
},
{
base: "Z",
letters: "Z\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762"
},
{
base: "a",
letters: "a\u24D0\uFF41\u1E9A\xE0\xE1\xE2\u1EA7\u1EA5\u1EAB\u1EA9\xE3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\xE4\u01DF\u1EA3\xE5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250"
},
{ base: "aa", letters: "\uA733" },
{ base: "ae", letters: "\xE6\u01FD\u01E3" },
{ base: "ao", letters: "\uA735" },
{ base: "au", letters: "\uA737" },
{ base: "av", letters: "\uA739\uA73B" },
{ base: "ay", letters: "\uA73D" },
{
base: "b",
letters: "b\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253"
},
{
base: "c",
letters: "c\u24D2\uFF43\u0107\u0109\u010B\u010D\xE7\u1E09\u0188\u023C\uA73F\u2184"
},
{
base: "d",
letters: "d\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A"
},
{ base: "dz", letters: "\u01F3\u01C6" },
{
base: "e",
letters: "e\u24D4\uFF45\xE8\xE9\xEA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\xEB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD"
},
{ base: "f", letters: "f\u24D5\uFF46\u1E1F\u0192\uA77C" },
{
base: "g",
letters: "g\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F"
},
{
base: "h",
letters: "h\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265"
},
{ base: "hv", letters: "\u0195" },
{
base: "i",
letters: "i\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131"
},
{ base: "j", letters: "j\u24D9\uFF4A\u0135\u01F0\u0249" },
{
base: "k",
letters: "k\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3"
},
{
base: "l",
letters: "l\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747"
},
{ base: "lj", letters: "\u01C9" },
{ base: "m", letters: "m\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F" },
{
base: "n",
letters: "n\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5"
},
{ base: "nj", letters: "\u01CC" },
{
base: "o",
letters: "o\u24DE\uFF4F\xF2\xF3\xF4\u1ED3\u1ED1\u1ED7\u1ED5\xF5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\xF6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\xF8\u01FF\u0254\uA74B\uA74D\u0275"
},
{ base: "oi", letters: "\u01A3" },
{ base: "ou", letters: "\u0223" },
{ base: "oo", letters: "\uA74F" },
{
base: "p",
letters: "p\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755"
},
{ base: "q", letters: "q\u24E0\uFF51\u024B\uA757\uA759" },
{
base: "r",
letters: "r\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783"
},
{
base: "s",
letters: "s\u24E2\uFF53\xDF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B"
},
{
base: "t",
letters: "t\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787"
},
{ base: "tz", letters: "\uA729" },
{
base: "u",
letters: "u\u24E4\uFF55\xF9\xFA\xFB\u0169\u1E79\u016B\u1E7B\u016D\xFC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289"
},
{ base: "v", letters: "v\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C" },
{ base: "vy", letters: "\uA761" },
{
base: "w",
letters: "w\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73"
},
{ base: "x", letters: "x\u24E7\uFF58\u1E8B\u1E8D" },
{
base: "y",
letters: "y\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF"
},
{
base: "z",
letters: "z\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763"
},
// Added to original source definitions
// https://github.com/tadashi-aikawa/obsidian-another-quick-switcher/issues/131
{
base: "2",
letters: "\xB2"
},
{
base: "3",
letters: "\xB3"
}
];
var diacriticsMap = {};
for (let i = 0; i < defaultDiacriticsRemovalMap.length; i++) {
const letters = defaultDiacriticsRemovalMap[i].letters;
for (let j = 0; j < letters.length; j++) {
diacriticsMap[letters[j]] = defaultDiacriticsRemovalMap[i].base;
}
}
var diacritics_map_default = diacriticsMap;
// src/utils/strings.ts
var regEmoji = new RegExp(
// biome-ignore lint/suspicious/noMisleadingCharacterClass: <explanation>
/[\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF]|[\uFE0E-\uFE0F]/,
"g"
);
function excludeSpace(text) {
return text.replace(/ /g, "");
}
function excludeEmoji(text) {
return text.replace(regEmoji, "");
}
function normalizeAccentsDiacritics(text) {
return text.replace(/[^\u0000-\u007E]/g, (x) => {
var _a;
return (_a = diacritics_map_default[x]) != null ? _a : x;
});
}
function normalize(str, isNormalizeAccentsDiacritics) {
const t = str.toLowerCase();
return isNormalizeAccentsDiacritics ? normalizeAccentsDiacritics(t) : t;
}
function escapeRegExp(str) {
return str.replace(/[.*+?^=!:${}()|[\]\/\\]/g, "\\$&");
}
function includes(text, query, isNormalizeAccentsDiacritics) {
return normalize(text, isNormalizeAccentsDiacritics).includes(
normalize(query, isNormalizeAccentsDiacritics)
);
}
function capitalIncludes(text, query, isNormalizeAccentsDiacritics) {
if (!hasCapitalLetter(query)) {
return includes(text, query, isNormalizeAccentsDiacritics);
}
return isNormalizeAccentsDiacritics ? normalizeAccentsDiacritics(text).includes(
normalizeAccentsDiacritics(query)
) : text.includes(query);
}
function smartIncludes(text, query, isNormalizeAccentsDiacritics) {
return excludeSpace(normalize(text, isNormalizeAccentsDiacritics)).includes(
excludeSpace(normalize(query, isNormalizeAccentsDiacritics))
);
}
function smartStartsWith(text, query, isNormalizeAccentsDiacritics) {
return excludeSpace(
excludeEmoji(normalize(text, isNormalizeAccentsDiacritics))
).startsWith(excludeSpace(normalize(query, isNormalizeAccentsDiacritics)));
}
function smartEquals(text, query, isNormalizeAccentsDiacritics) {
return excludeSpace(
excludeEmoji(normalize(text, isNormalizeAccentsDiacritics))
) === normalize(query, isNormalizeAccentsDiacritics);
}
function excludeFormat(text) {
return text.replace(/\[\[[^\]]+\|(.*?)]]/g, "$1").replace(/\[\[([^\]]+)]]/g, "$1").replace(/\[([^\]]+)]\(https?[^)]+\)/g, "$1").replace(/\[([^\]]+)]/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/==([^=]+)==/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/_([^_]+)_/g, "$1").replace(/<[^>]+>([^<]+)<\/[^>]+>/g, "$1");
}
function smartCommaSplit(text) {
return text.split(",").filter((x) => x);
}
function smartLineBreakSplit(text) {
return text.split("\n").filter((x) => x);
}
function smartWhitespaceSplit(text) {
const strs = [];
let str = "";
let hasQuote = false;
for (let i = 0; i < text.length; i++) {
const ch = text[i];
switch (ch) {
case `"`:
hasQuote = !hasQuote;
break;
case " ":
if (hasQuote) {
str += ch;
} else {
strs.push(str);
str = "";
}
break;
default:
str += ch;
}
}
strs.push(str);
return strs.filter((x) => x);
}
function capitalizeFirstLetter(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
function hasCapitalLetter(str) {
return str.toLowerCase() !== str;
}
function microFuzzy(value, query) {
if (value.startsWith(query)) {
return { type: "starts-with", score: 2 ** query.length / value.length };
}
const emojiLessValue = excludeEmoji(value);
if (emojiLessValue.startsWith(query)) {
return { type: "starts-with", score: 2 ** query.length / value.length };
}
if (value.includes(query)) {
return { type: "includes", score: 2 ** query.length / value.length };
}
let i = 0;
let scoreSeed = 0;
let combo = 0;
for (let j = 0; j < emojiLessValue.length; j++) {
if (emojiLessValue[j] === query[i]) {
combo++;
i++;
} else {
if (combo > 0) {
scoreSeed += 2 ** combo;
combo = 0;
}
}
if (i === query.length) {
if (combo > 0) {
scoreSeed += 2 ** combo;
}
return { type: "fuzzy", score: scoreSeed / value.length };
}
}
return { type: "none", score: 0 };
}
function smartMicroFuzzy(text, query, isNormalizeAccentsDiacritics) {
return microFuzzy(
excludeSpace(normalize(text, isNormalizeAccentsDiacritics)),
excludeSpace(normalize(query, isNormalizeAccentsDiacritics))
);
}
function trimLineByEllipsis(text, max) {
return text.length > max * 2 ? `${text.slice(0, max)} ... ${text.slice(text.length - max)}` : text;
}
// src/app-helper.ts
function isFrontMatterLinkCache(x) {
return x.position == null;
}
var AppHelper = class {
constructor(app) {
this.unsafeApp = app;
}
getActiveFile() {
return this.unsafeApp.workspace.getActiveFile();
}
getViewInActiveLeaf() {
return this.unsafeApp.workspace.getActiveViewOfType(import_obsidian.View);
}
getFileViewInActiveLeaf() {
return this.unsafeApp.workspace.getActiveViewOfType(import_obsidian.FileView);
}
getMarkdownViewInActiveLeaf() {
return this.unsafeApp.workspace.getActiveViewOfType(import_obsidian.MarkdownView);
}
getCanvasViewInActiveLeaf() {
return this.getViewInActiveLeaf();
}
getCurrentEditor() {
var _a, _b;
return (_b = (_a = this.getMarkdownViewInActiveLeaf()) == null ? void 0 : _a.editor) != null ? _b : null;
}
getCurrentDirPath() {
var _a, _b, _c;
return (_c = (_b = (_a = this.getActiveFile()) == null ? void 0 : _a.parent) == null ? void 0 : _b.path) != null ? _c : "";
}
getCurrentOffset() {
var _a;
const editor = this.getCurrentEditor();
if (!editor) {
return null;
}
const cursor = (_a = this.getCurrentEditor()) == null ? void 0 : _a.getCursor();
if (!cursor) {
return null;
}
return editor.posToOffset(cursor);
}
getHeadersInActiveFile() {
var _a, _b;
const activeFile = this.getActiveFile();
if (!activeFile) {
return [];
}
return (_b = (_a = this.unsafeApp.metadataCache.getFileCache(activeFile)) == null ? void 0 : _a.headings) != null ? _b : [];
}
getFolders() {
return this.unsafeApp.vault.getAllLoadedFiles().filter((x) => x instanceof import_obsidian.TFolder);
}
getLayout() {
return this.unsafeApp.workspace.getLayout();
}
getLeftSideBarWidth() {
return this.getLayout().left.collapsed ? 0 : this.getLayout().left.width;
}
getRightSideBarWidth() {
return this.getLayout().right.collapsed ? 0 : this.getLayout().right.width;
}
async findExternalLinkUrls(file) {
const content = await this.unsafeApp.vault.read(file);
const matches = Array.from(content.matchAll(/https?:\/\/[^ \n)]+/g));
return matches.map((x) => x[0]);
}
findFirstLinkOffset(file, linkFile) {
var _a, _b, _c;
const fileCache = this.unsafeApp.metadataCache.getFileCache(
file
);
const links = (_a = fileCache == null ? void 0 : fileCache.links) != null ? _a : [];
const frontmatterLinks = (_b = fileCache == null ? void 0 : fileCache.frontmatterLinks) != null ? _b : [];
const embeds = (_c = fileCache == null ? void 0 : fileCache.embeds) != null ? _c : [];
const first = [...links, ...frontmatterLinks, ...embeds].find(
(x) => {
var _a2;
const firstLinkPath = this.isPhantomFile(linkFile) ? this.getPathToBeCreated(x.link) : (_a2 = this.unsafeApp.metadataCache.getFirstLinkpathDest(
(0, import_obsidian.getLinkpath)(x.link),
file.path
)) == null ? void 0 : _a2.path;
return firstLinkPath === linkFile.path;
}
);
if (!first || isFrontMatterLinkCache(first)) {
return 0;
}
return first.position.start.offset;
}
findFirstHeaderOffset(file, header) {
var _a, _b;
const cache = this.unsafeApp.metadataCache.getFileCache(file);
if (!cache) {
return null;
}
const target = (_a = cache.headings) == null ? void 0 : _a.find(
(x) => excludeFormat(x.heading) === excludeFormat(header)
);
return (_b = target == null ? void 0 : target.position.start.offset) != null ? _b : null;
}
getBacklinksByFilePathInActiveFile() {
const f = this.getActiveFile();
if (!f) {
return null;
}
return this.unsafeApp.metadataCache.getBacklinksForFile(f).data;
}
// noinspection FunctionWithMultipleLoopsJS
/**
* Includes phantom files
*/
createBacklinksMap() {
const backLinksMap = {};
const unresolvedLinks = mapValues(
this.unsafeApp.metadataCache.unresolvedLinks,
(innerMap) => mapKeys(innerMap, (x) => this.getPathToBeCreated(x))
);
for (const [filePath, linkMap] of Object.entries(
(0, import_ts_deepmerge.default)(this.unsafeApp.metadataCache.resolvedLinks, unresolvedLinks)
)) {
for (const linkPath of Object.keys(linkMap)) {
if (!backLinksMap[linkPath]) {
backLinksMap[linkPath] = /* @__PURE__ */ new Set();
}
backLinksMap[linkPath].add(filePath);
}
}
return backLinksMap;
}
/**
* @return {"<relative path from root>: UnsafeLinkCache"}
*/
createLinksMap(file) {
var _a, _b, _c;
const cache = this.unsafeApp.metadataCache.getFileCache(
file
);
return mapValues(
groupBy(
[
...(_a = cache == null ? void 0 : cache.embeds) != null ? _a : [],
...(_b = cache == null ? void 0 : cache.links) != null ? _b : [],
...(_c = cache == null ? void 0 : cache.frontmatterLinks) != null ? _c : []
],
(x) => {
var _a2;
return (_a2 = this.linkText2Path(x.link)) != null ? _a2 : this.getPathToBeCreated(x.link);
}
),
(caches) => caches[0]
);
}
getLinksByFilePathInActiveFile() {
var _a, _b, _c;
const file = this.getActiveFile();
if (!file) {
return null;
}
const cache = this.unsafeApp.metadataCache.getFileCache(
file
);
return groupBy(
[
...(_a = cache == null ? void 0 : cache.embeds) != null ? _a : [],
...(_b = cache == null ? void 0 : cache.links) != null ? _b : [],
...(_c = cache == null ? void 0 : cache.frontmatterLinks) != null ? _c : []
],
(x) => {
var _a2;
return (_a2 = this.linkText2Path(x.link)) != null ? _a2 : this.getPathToBeCreated(x.link);
}
);
}
async moveTo(to, editor) {
var _a;
const isToOffset = typeof to === "number";
const activeFile = this.getActiveFile();
const activeLeaf = this.unsafeApp.workspace.activeLeaf;
if (!activeFile || !activeLeaf) {
return;
}
const subView = (_a = this.getMarkdownViewInActiveLeaf()) == null ? void 0 : _a.currentMode;
if (!subView) {
return;
}
const targetEditor = editor != null ? editor : this.getCurrentEditor();
if (!targetEditor) {
return;
}
const line = isToOffset ? targetEditor.offsetToPos(to).line : to.start.line;
targetEditor.setCursor(
targetEditor.offsetToPos(isToOffset ? to : to.start.offset)
);
await activeLeaf.openFile(activeFile, {
eState: {
line
},
active: false
});
}
getFileByPath(path) {
const abstractFile = this.unsafeApp.vault.getAbstractFileByPath(path);
if (!abstractFile) {
return null;
}
return abstractFile;
}
getFilePathsInActiveWindow() {
return this.unsafeApp.workspace.getLeavesOfType("markdown").filter(
(x) => {
var _a;
return x.getContainer() === ((_a = this.unsafeApp.workspace.activeLeaf) == null ? void 0 : _a.getContainer());
}
).map((x) => x.getViewState().state.file);
}
captureState(initialLeaf) {
const currentLeaf = this.unsafeApp.workspace.getLeaf();
const newLeaf = this.unsafeApp.workspace.getLeaf();
const newState = newLeaf.getViewState();
const newEState = newLeaf.getEphemeralState();
const unsafeApp = this.unsafeApp;
return {
leaf: newLeaf,
async restore() {
if (!newLeaf) {
return;
}
if (!initialLeaf || initialLeaf.getViewState().pinned) {
newLeaf.detach();
} else {
await newLeaf.setViewState(
{
...newState,
active: newLeaf === currentLeaf,
popstate: true
},
newEState
);
if (newLeaf !== currentLeaf) {
unsafeApp.workspace.setActiveLeaf(currentLeaf, { focus: true });
}
}
this.leaf = void 0;
}
};
}
getOpenState(leaf, file) {
let type = this.unsafeApp.viewRegistry.getTypeByExtension(file.extension);
if (leaf.view instanceof import_obsidian.FileView && leaf.view.canAcceptExtension(file.extension)) {
type = leaf.view.getViewType();
}
return { type, state: { file: file.path } };
}
findLeaf(file) {
return this.unsafeApp.workspace.getLeavesOfType("markdown").find((x) => x.getViewState().state.file === file.path);
}
async openFile(file, option = {}, captureState) {
var _a, _b, _c;
const opt = {
...{ leafType: "same-tab", inplace: false },
...option
};
const priorLeaf = (option == null ? void 0 : option.preventDuplicateTabs) ? this.findLeaf(file) : void 0;
let leaf;
let background = false;
switch (opt.leafType) {
case "same-tab":
leaf = (_b = (_a = option.leafPriorToSameTab) != null ? _a : captureState == null ? void 0 : captureState.leaf) != null ? _b : this.unsafeApp.workspace.getLeaf();
break;
case "new-tab":
leaf = priorLeaf != null ? priorLeaf : this.unsafeApp.workspace.getLeaf(true);
break;
case "new-tab-background":
leaf = priorLeaf != null ? priorLeaf : this.unsafeApp.workspace.getLeaf(true);
background = true;
break;
case "new-pane-horizontal":
leaf = this.unsafeApp.workspace.getLeaf("split", "horizontal");
break;
case "new-pane-vertical":
leaf = this.unsafeApp.workspace.getLeaf("split", "vertical");
break;
case "new-window":
leaf = this.unsafeApp.workspace.openPopoutLeaf();
break;
case "popup": {
const hoverEditorInstance = this.unsafeApp.plugins.plugins["obsidian-hover-editor"];
leaf = (_c = hoverEditorInstance == null ? void 0 : hoverEditorInstance.spawnPopover()) != null ? _c : this.unsafeApp.workspace.getLeaf(true);
break;
}
default:
throw new ExhaustiveError(opt.leafType);
}
if (opt.inplace && opt.leafType === "same-tab") {
await leaf.setViewState({
...leaf.getViewState(),
active: !background,
popstate: true,
...this.getOpenState(leaf, file)
});
} else {
await leaf.openFile(file, {
...leaf.getViewState(),
active: !background
});
}
if (leaf.view instanceof import_obsidian.MarkdownView) {
const markdownView = leaf.view;
if (opt.offset != null) {
this.moveTo(opt.offset, markdownView.editor);
} else if (opt.line != null) {
const p = { line: opt.line, offset: 0, col: 0 };
this.moveTo({ start: p, end: p }, markdownView.editor);
}
}
}
openFileInDefaultApp(file) {
this.unsafeApp.openWithDefaultApp(file.path);
}
openFolderInDefaultApp(folder) {
this.unsafeApp.openWithDefaultApp(folder.path);
}
openInSystemExplorer(entry) {
this.unsafeApp.showInFolder(entry.path);
}
// FIXME: function name
getStarredFilePaths() {
return this.unsafeApp.internalPlugins.plugins.bookmarks.instance.getBookmarks().map((x) => x.type === "file" ? x.path : void 0).filter((x) => x !== void 0);
}
searchPhantomFiles() {
return uniq(
flatten(
Object.values(this.unsafeApp.metadataCache.unresolvedLinks).map(
Object.keys
)
)
).map((x) => this.createPhantomFile(x));
}
insertStringToActiveFile(str) {
const activeMarkdownView = this.unsafeApp.workspace.getActiveViewOfType(import_obsidian.MarkdownView);
if (!activeMarkdownView) {
return;
}
const editor = activeMarkdownView.editor;
editor.replaceSelection(str);
}
insertLinkToActiveFileBy(file, phantom) {
const activeMarkdownView = this.unsafeApp.workspace.getActiveViewOfType(import_obsidian.MarkdownView);
if (!(activeMarkdownView == null ? void 0 : activeMarkdownView.file)) {
return;
}
let linkText = this.unsafeApp.fileManager.generateMarkdownLink(
file,
activeMarkdownView.file.path
);
if (phantom) {
linkText = linkText.replace(/\[\[.*\/([^\]]+)]]/, "[[$1]]");
}
const editor = activeMarkdownView.editor;
editor.replaceSelection(
// XXX: dirty hack
linkText.endsWith(".excalidraw]]") ? `!${linkText}` : (
// ![[hoge.pdf]] -> [[hoge.pdf]]
linkText.endsWith(".pdf]]") ? linkText.replace("!", "") : linkText
)
);
}
async createMarkdown(linkText) {
const linkPath = this.getPathToBeCreated(linkText);
if (await this.exists(linkPath)) {
return null;
}
const dir = dirname(linkPath);
if (!await this.exists(dir)) {
await this.unsafeApp.vault.createFolder(dir);
}
return this.unsafeApp.vault.create(linkPath, "");
}
exists(normalizedPath) {
return this.unsafeApp.vault.adapter.exists(normalizedPath);
}
isPopWindow() {
return !fish(".modal-bg");
}
removeCommand(commandId) {
this.unsafeApp.commands.removeCommand(commandId);
}
getCommandIds(manifestId) {
return Object.keys(this.unsafeApp.commands.commands).filter(
(x) => x.startsWith(manifestId)
);
}
getPathToBeCreated(linkText) {
var _a, _b, _c;
let linkPath = (0, import_obsidian.getLinkpath)(linkText);
if (extname(linkPath) !== ".md") {
linkPath += ".md";
}
if (linkPath.includes("/")) {
return linkPath;
}
switch (this.unsafeApp.vault.config.newFileLocation) {
case "root":
return `/${linkPath}`;
case "current":
return `${(_c = (_b = (_a = this.getActiveFile()) == null ? void 0 : _a.parent) == null ? void 0 : _b.path) != null ? _c : ""}/${linkPath}`;
case "folder":
return `${this.unsafeApp.vault.config.newFileFolderPath}/${linkPath}`;
default:
return `/${linkPath}`;
}
}
linkText2Path(linkText) {
var _a, _b;
const activeFile = this.getActiveFile();
if (!activeFile) {
return null;
}
return (_b = (_a = this.unsafeApp.metadataCache.getFirstLinkpathDest(
linkText,
activeFile.path
)) == null ? void 0 : _a.path) != null ? _b : null;
}
isPhantomFile(file) {
return file.stat.ctime === 0;
}
isActiveLeafCanvas() {
var _a;
return ((_a = this.getViewInActiveLeaf()) == null ? void 0 : _a.getViewType()) === "canvas";
}
// XXX: not strict
isCacheInitialized() {
return this.unsafeApp.metadataCache.initialized;
}
addFileToCanvas(file, offset = { x: 0, y: 0 }) {
const unsafeView = this.getCanvasViewInActiveLeaf();
const { x, y } = unsafeView.canvas.posCenter();
return unsafeView.canvas.createFileNode({
file,
pos: { x: x + offset.x, y: y + offset.y }
});
}
enableFileExplorer() {
return this.unsafeApp.internalPlugins.getEnabledPluginById("file-explorer");
}
revealInFolder(folder) {
this.unsafeApp.internalPlugins.plugins["file-explorer"].instance.revealInFolder(folder);
}
// TODO: Use another interface instead of TFile
createPhantomFile(linkText) {
const linkPath = this.getPathToBeCreated(linkText);
return {
path: linkPath,
name: basename(linkPath),
vault: this.unsafeApp.vault,
extension: "md",
basename: basename(linkPath, ".md"),
parent: {
name: basename(dirname(linkPath)),
path: dirname(linkPath),
vault: this.unsafeApp.vault,
// XXX: From here, Untrusted properties
children: [],
// @ts-ignore
parent: null,
isRoot: () => true
},
stat: {
mtime: 0,
ctime: 0,
size: 0
}
};
}
};
// src/commands.ts
var import_obsidian12 = require("obsidian");
// src/ui/AnotherQuickSwitcherModal.ts
var import_obsidian4 = require("obsidian");
// src/keys.ts
var import_obsidian2 = require("obsidian");
var MOD = import_obsidian2.Platform.isMacOS ? "Cmd" : "Ctrl";
var ALT = import_obsidian2.Platform.isMacOS ? "Option" : "Alt";
var quickResultSelectionModifier = (userAltInsteadOfModForQuickResultSelection) => userAltInsteadOfModForQuickResultSelection ? ALT : MOD;
function hotkey2String(hotkey) {
if (!hotkey) {
return "";
}
const mods = hotkey.modifiers.join(" ");
return mods ? `${mods} ${hotkey.key}` : hotkey.key;
}
function string2Hotkey(hotKey, hideHotkeyGuide) {
const keys = hotKey.split(" ");
if (keys.length === 1) {
return keys[0] === "" ? null : { modifiers: [], key: keys[0], hideHotkeyGuide };
}
return {
modifiers: keys.slice(0, -1),
key: keys.at(-1),
hideHotkeyGuide
};
}
function createInstructions(hotkeysByCommand) {
return Object.keys(hotkeysByCommand).filter((x) => hotkeysByCommand[x].length > 0).map((x) => createInstruction(x, hotkeysByCommand[x][0])).filter((x) => x !== null);
}
function createInstruction(commandName, hotkey) {
if (!hotkey || hotkey.hideHotkeyGuide) {
return null;
}
const mods = hotkey.modifiers.map((x) => x === "Mod" ? MOD : x === "Alt" ? ALT : x).join(" ");
const key = hotkey.key === "Enter" ? "\u21B5" : hotkey.key === "ArrowUp" ? "\u2191" : hotkey.key === "ArrowDown" ? "\u2193" : hotkey.key === "Escape" ? "ESC" : hotkey.key;
const command = mods ? `[${mods} ${key}]` : `[${key}]`;
return { command, purpose: commandName };
}
function equalsAsHotkey(hotkey, keyDownEvent) {
const hk = {
modifiers: [],
key: normalizeHotkeyEventKey(keyDownEvent.key)
};
if (keyDownEvent.shiftKey) {
hk.modifiers.push("Shift");
}
if (keyDownEvent.altKey) {
hk.modifiers.push("Alt");
}
if (keyDownEvent.ctrlKey) {
hk.modifiers.push(import_obsidian2.Platform.isMacOS ? "Ctrl" : "Mod");
}
if (keyDownEvent.metaKey) {
hk.modifiers.push(import_obsidian2.Platform.isMacOS ? "Mod" : "Meta");
}
return hotkey.key.toLowerCase() === hk.key.toLowerCase() && equalsAsSet(hotkey.modifiers, hk.modifiers);
}
function normalizeHotkeyEventKey(key) {
return key === " " ? "Space" : key;
}
function normalizeKey(hotkey) {
return hotkey === "Space" ? " " : hotkey;
}
// src/utils/types.ts
function isPresent(arg) {
return arg != null;
}
// src/matcher.ts
function matchQuery(item, query, options) {
var _a;
const {
searchByTags,
searchByHeaders,
searchByLinks,
keysOfPropertyToSearch,
isNormalizeAccentsDiacritics
} = options;
if (searchByTags && query.startsWith("#")) {
const tags = item.tags.filter(
(tag) => smartIncludes(tag.slice(1), query.slice(1), isNormalizeAccentsDiacritics)
);
return [
{
type: tags.length > 0 ? "tag" : "not found",
meta: tags,
query
}
];
}
const qs = query.split("/");
const file = qs.pop();
const dirs = qs;
const includeDir = dirs.every(
(dir) => {
var _a2;
return smartIncludes((_a2 = item.file.parent) == null ? void 0 : _a2.path, dir, isNormalizeAccentsDiacritics);
}
);
if (!includeDir) {
return [{ type: "not found", query }];
}
if (file.length === 0) {
return [{ type: "directory", meta: [item.file.path], query }];
}
const results = [];
if (item.tokens.some((t) => smartEquals(t, file, isNormalizeAccentsDiacritics))) {
results.push({ type: "word-perfect", meta: [item.file.name], query });
}
const fuzzyResult = smartMicroFuzzy(
item.file.extension === "md" ? item.file.basename : item.file.name,
// Should calculate the score without .md
query,
isNormalizeAccentsDiacritics
);
switch (fuzzyResult.type) {
case "starts-with":
results.push({ type: "prefix-name", meta: [item.file.name], query });
case "includes":
results.push({ type: "name", meta: [item.file.name], query });
case "fuzzy":
if (options.fuzzyTarget) {
if (fuzzyResult.score > options.minFuzzyScore) {
results.push({
type: "fuzzy-name",
meta: [item.file.name],
query,
score: fuzzyResult.score
});
}
}
}
const prefixNameMatchedAliases = [];
const nameMatchedAliases = [];
const fuzzyNameMatchedAliases = [];
for (const al of item.aliases) {
const r = smartMicroFuzzy(al, file, isNormalizeAccentsDiacritics);
switch (r.type) {
case "starts-with":
prefixNameMatchedAliases.push(al);
case "includes":
nameMatchedAliases.push(al);
case "fuzzy":
if (options.fuzzyTarget) {
if (r.score > options.minFuzzyScore) {
fuzzyNameMatchedAliases.push({
value: al,
score: r.score
});
}
}
}
}
if (prefixNameMatchedAliases.length > 0) {
results.push({
type: "prefix-name",
meta: prefixNameMatchedAliases,
alias: minBy(prefixNameMatchedAliases, (x) => x.length),
query
});
}
if (nameMatchedAliases.length > 0) {
results.push({
type: "name",
meta: nameMatchedAliases,
alias: minBy(nameMatchedAliases, (x) => x.length),
query
});
}
if (options.fuzzyTarget && fuzzyNameMatchedAliases.length > 0) {
const m = minBy(fuzzyNameMatchedAliases, (x) => x.score);
results.push({
type: "fuzzy-name",
meta: fuzzyNameMatchedAliases.map((x) => x.value),
alias: m.value,
score: m.score,
query
});
}
if (smartIncludes((_a = item.file.parent) == null ? void 0 : _a.path, query, isNormalizeAccentsDiacritics)) {
results.push({ type: "directory", meta: [item.file.path], query });
}
if (searchByHeaders) {
const headers = item.headers.filter(
(header) => smartIncludes(header, query, isNormalizeAccentsDiacritics)
);
if (headers.length > 0) {
results.push({
type: "header",
meta: headers,
query
});
}
}
if (searchByLinks) {
const links = item.links.filter(
(link) => smartIncludes(link, query, isNormalizeAccentsDiacritics)
);
if (links.length > 0) {
results.push({
type: "link",
meta: links,
query
});
}
}
if (searchByTags) {
const tags = item.tags.filter(
(tag) => smartIncludes(tag.slice(1), query, isNormalizeAccentsDiacritics)
);
if (tags.length > 0) {
results.push({
type: "tag",
meta: tags,
query
});
}
}
if (keysOfPropertyToSearch.length > 0) {
const values = keysOfPropertyToSearch.map((x) => {
var _a2, _b;
return (_b = (_a2 = item.frontMatter) == null ? void 0 : _a2[x]) == null ? void 0 : _b.toString();
}).filter((x) => x && smartIncludes(x, query, isNormalizeAccentsDiacritics)).filter(isPresent);
if (values.length > 0) {
results.push({
type: "property",
meta: values,
query
});
}
}
return results.length === 0 ? [{ type: "not found", query }] : results;
}
function matchQueryAll(item, queries, options) {
return queries.flatMap((q) => {
var _a;
const [query, negative] = q.startsWith("-") ? [q.slice(1), true] : [q, false];
const matched = matchQuery(item, query, options);
if (((_a = matched[0]) == null ? void 0 : _a.type) === "not found") {
return negative ? [] : matched;
}
return negative ? [{ type: "not found", query }] : matched;
});
}
function stampMatchResults(item, queries, options) {
return {
...item,
matchResults: matchQueryAll(item, queries, options)
};
}
// src/settings.ts
var import_obsidian3 = require("obsidian");
// src/sorters.ts
var sortPriorityList = [
"Header match",
"Last modified",
"Last opened",
"Created earliest",
"Created latest",
"Length",
"Link match",
"Name match",
"Perfect word match",
"Prefix name match",
"Fuzzy name match",
"Star",
"Tag match",
"Property match",
"Alphabetical",
"Alphabetical reverse"
];
function regardAsSortPriority(x) {
return sortPriorityList.includes(x) || x.split(",").every((y) => y.startsWith("#")) || x.split(",").every((y) => y.startsWith("."));
}
function filterNoQueryPriorities(priorities) {
return priorities.filter(
(x) => [
"Last opened",
"Last modified",
"Created earliest",
"Created latest",
"Star",
"Alphabetical",
"Alphabetical reverse"
].includes(x) || x.startsWith("#") || x.startsWith(".")
);
}
function getComparator(priority) {
switch (priority) {
case "Header match":
return priorityToHeader;
case "Last modified":
return priorityToLastModified;
case "Last opened":
return priorityToLastOpened;
case "Created latest":
return priorityToCreatedLatest;
case "Created earliest":
return priorityToCreatedEarliest;
case "Length":
return priorityToLength;
case "Link match":
return priorityToLink;
case "Name match":
return priorityToName;
case "Perfect word match":
return priorityToPerfectWord;
case "Prefix name match":
return priorityToPrefixName;
case "Fuzzy name match":
return priorityToFuzzyScore;
case "Star":
return priorityToStar;
case "Tag match":
return priorityToTag;
case "Property match":
return priorityToProperty;
case "Alphabetical":
return priorityToAlphabetical;
case "Alphabetical reverse":
return priorityToAlphabeticalReverse;
default:
if (priority.startsWith("#")) {
const tags = priority.split(",");
return (a, b) => priorityToTags(a, b, tags);
}
if (priority.startsWith(".")) {
const extensions = priority.split(",").map((x) => x.slice(1));
return (a, b) => priorityToExtensions(a, b, extensions);
}
throw new ExhaustiveError(priority);
}
}
function sort(items, priorities, lastOpenFileIndexByPath) {
const comparators = priorities.map(getComparator);
return items.sort((a, b) => {
let result;
for (const comparator of comparators) {
result = comparator(a, b, lastOpenFileIndexByPath);
if (result !== 0) {
return result;
}
}
return 0;
});
}
function compare(a, b, toOrdered, order = "asc") {
const oA = toOrdered(a);
const oB = toOrdered(b);
if (oA === oB) {
return 0;
}
switch (order) {
case "asc":
if (oA > oB) {
return 1;
}
if (oB > oA) {
return -1;
}
return 0;
case "desc":
if (oA < oB) {
return 1;
}
if (oB < oA) {
return -1;
}
return 0;
}
}
function priorityToPerfectWord(a, b) {
return compare(
a,
b,
(x) => x.matchResults.filter((x2) => x2.type === "word-perfect").map((x2) => x2.query).unique().length,
"desc"
);
}
function priorityToPrefixName(a, b) {
return compare(
a,
b,
(x) => x.matchResults.filter((x2) => x2.type === "prefix-name").map((x2) => x2.query).unique().length,
"desc"
);
}
function priorityToName(a, b) {
return compare(
a,
b,
(x) => x.matchResults.filter((x2) => x2.type === "name").map((x2) => x2.query).unique().length,
"desc"
);
}
function priorityToFuzzyScore(a, b) {
return compare(
a,
b,
(x) => Math.max(...x.matchResults.map((x2) => {
var _a;
return (_a = x2.score) != null ? _a : 0;
})),
"desc"
);
}
function priorityToTag(a, b) {
return compare(
a,
b,
(x) => x.matchResults.filter((x2) => x2.type === "tag").map((x2) => x2.query).unique().length,
"desc"
);
}
function priorityToProperty(a, b) {
return compare(
a,
b,
(x) => x.matchResults.filter((x2) => x2.type === "property").map((x2) => x2.query).unique().length,
"desc"
);
}
function priorityToHeader(a, b) {
return compare(
a,
b,
(x) => x.matchResults.filter((x2) => x2.type === "header").map((x2) => x2.query).unique().length,
"desc"
);
}
function priorityToLink(a, b) {
return compare(
a,
b,
(x) => x.matchResults.filter((x2) => x2.type === "link").map((x2) => x2.query).unique().length,
"desc"
);
}
function priorityToLength(a, b) {
return compare(
a,
b,
(x) => x.matchResults[0].alias ? x.matchResults[0].alias.length : x.file.basename.length,
"asc"
);
}
function priorityToLastOpened(a, b, lastOpenFileIndexByPath) {
return compare(
a,
b,
(x) => {
var _a;
return (_a = lastOpenFileIndexByPath[x.file.path]) != null ? _a : 999999;
},
"asc"
);
}
function priorityToLastModified(a, b) {
return compare(a, b, (x) => x.file.stat.mtime, "desc");
}
function priorityToCreatedLatest(a, b) {
return compare(a, b, (x) => x.file.stat.ctime, "desc");
}
function priorityToCreatedEarliest(a, b) {
return compare(
a,
b,
(x) => x.file.stat.ctime || Number.MAX_SAFE_INTEGER,
"asc"
);
}
function priorityToStar(a, b) {
return compare(a, b, (x) => Number(x.starred), "desc");
}
var toComparedAlphabetical = (item) => {
var _a, _b;
return excludeEmoji((_b = (_a = item.matchResults[0]) == null ? void 0 : _a.alias) != null ? _b : item.file.basename).toLowerCase();
};
function priorityToAlphabetical(a, b) {
return toComparedAlphabetical(a).localeCompare(toComparedAlphabetical(b));
}
function priorityToAlphabeticalReverse(a, b) {
return toComparedAlphabetical(b).localeCompare(toComparedAlphabetical(a));
}
function priorityToTags(a, b, tags) {
return compare(a, b, (x) => intersection([tags, x.tags]).length, "desc");
}
function priorityToExtensions(a, b, extensions) {
return compare(
a,
b,
(x) => Number(extensions.contains(x.file.extension)),
"desc"
);
}
// src/settings.ts
var searchTargetList = [
"file",
"opened file",
"backlink",
"link",
"2-hop-link"
];
var createDefaultHotkeys = () => ({
main: {
up: [{ modifiers: ["Mod"], key: "p" }],
down: [{ modifiers: ["Mod"], key: "n" }],
"clear input": [{ modifiers: ["Mod"], key: "d" }],
"replace input": [{ modifiers: [], key: "Tab" }],
open: [{ modifiers: [], key: "Enter" }],
"open in new tab": [{ modifiers: ["Mod"], key: "Enter" }],
"open in new pane (horizontal)": [{ modifiers: ["Mod"], key: "-" }],
"open in new pane (vertical)": [{ modifiers: ["Mod"], key: "i" }],
"open in new window": [{ modifiers: ["Mod"], key: "o" }],
"open in popup": [],
"open in new tab in background": [{ modifiers: ["Alt"], key: "o" }],
"open all in new tabs": [{ modifiers: ["Mod", "Shift", "Alt"], key: "o" }],
preview: [{ modifiers: ["Mod"], key: "," }],
create: [{ modifiers: ["Shift"], key: "Enter" }],
"create in new tab": [{ modifiers: ["Mod", "Shift"], key: "Enter" }],
"create in new window": [{ modifiers: ["Mod", "Shift"], key: "o" }],
"create in new popup": [],
"open in default app": [],
"show in system explorer": [],
"open in google": [{ modifiers: ["Mod"], key: "g" }],
"open first URL": [{ modifiers: ["Mod"], key: "]" }],
"insert to editor": [{ modifiers: ["Alt"], key: "Enter" }],
"insert to editor in background": [],
"insert all to editor": [{ modifiers: ["Alt", "Shift"], key: "Enter" }],
"show backlinks": [{ modifiers: ["Mod"], key: "h" }],
"show links": [{ modifiers: ["Mod"], key: "l" }],
"show all results": [{ modifiers: ["Shift", "Alt"], key: "a" }],
"navigate forward": [{ modifiers: ["Alt"], key: "ArrowRight" }],
"navigate back": [{ modifiers: ["Alt"], key: "ArrowLeft" }],
dismiss: [{ modifiers: [], key: "Escape" }]
},
folder: {
up: [{ modifiers: ["Mod"], key: "p" }],
down: [{ modifiers: ["Mod"], key: "n" }],
"open in default app": [],
dismiss: [{ modifiers: [], key: "Escape" }]
},
move: {
up: [{ modifiers: ["Mod"], key: "p" }],
down: [{ modifiers: ["Mod"], key: "n" }],
"open in default app": [],
dismiss: [{ modifiers: [], key: "Escape" }]
},
header: {
up: [{ modifiers: ["Mod"], key: "p" }],
down: [{ modifiers: ["Mod"], key: "n" }],
"clear input": [{ modifiers: ["Mod"], key: "d" }],
"move to next hit": [{ modifiers: [], key: "Tab" }],
"move to previous hit": [{ modifiers: ["Shift"], key: "Tab" }],
"toggle auto preview": [{ modifiers: ["Mod"], key: "," }],
"insert all to editor": [{ modifiers: ["Alt", "Shift"], key: "Enter" }],
dismiss: [{ modifiers: [], key: "Escape" }]
},
backlink: {
up: [{ modifiers: ["Mod"], key: "p" }],
down: [{ modifiers: ["Mod"], key: "n" }],
open: [{ modifiers: [], key: "Enter" }],
"open in new tab": [{ modifiers: ["Mod"], key: "Enter" }],
"open in new pane (horizontal)": [{ modifiers: ["Mod"], key: "-" }],
"open in new pane (vertical)": [{ modifiers: ["Mod"], key: "i" }],
"open in new window": [{ modifiers: ["Mod"], key: "o" }],
"open in popup": [],
"open in new tab in background": [{ modifiers: ["Alt"], key: "o" }],
"open all in new tabs": [{ modifiers: ["Mod", "Shift", "Alt"], key: "o" }],
"show all results": [{ modifiers: ["Shift", "Alt"], key: "a" }],
preview: [{ modifiers: ["Mod"], key: "," }],
dismiss: [{ modifiers: [], key: "Escape" }]
},
link: {
up: [{ modifiers: ["Mod"], key: "p" }],
down: [{ modifiers: ["Mod"], key: "n" }],
open: [{ modifiers: [], key: "Enter" }],
"open in new tab": [{ modifiers: ["Mod"], key: "Enter" }],
"open in new pane (horizontal)": [{ modifiers: ["Mod"], key: "-" }],
"open in new pane (vertical)": [{ modifiers: ["Mod"], key: "i" }],
"open in new window": [{ modifiers: ["Mod"], key: "o" }],
"open in popup": [],
"open in new tab in background": [{ modifiers: ["Alt"], key: "o" }],
"open all in new tabs": [{ modifiers: ["Mod", "Shift", "Alt"], key: "o" }],
"show all results": [{ modifiers: ["Shift", "Alt"], key: "a" }],
preview: [{ modifiers: ["Mod"], key: "," }],
dismiss: [{ modifiers: [], key: "Escape" }]
},
"in-file": {
up: [{ modifiers: ["Mod"], key: "p" }],
down: [{ modifiers: ["Mod"], key: "n" }],
"show all results": [{ modifiers: ["Shift", "Alt"], key: "a" }],
"toggle auto preview": [{ modifiers: ["Mod"], key: "," }],
dismiss: [{ modifiers: [], key: "Escape" }]
},
grep: {
search: [{ modifiers: [], key: "Tab" }],
up: [{ modifiers: ["Mod"], key: "p" }],
down: [{ modifiers: ["Mod"], key: "n" }],
"clear input": [{ modifiers: ["Mod"], key: "d" }],
"clear path": [{ modifiers: ["Alt"], key: "d" }],
"set ./ to path": [{ modifiers: ["Alt"], key: "c" }],
open: [{ modifiers: [], key: "Enter" }],
"open in new tab": [{ modifiers: ["Mod"], key: "Enter" }],
"open in new pane (horizontal)": [{ modifiers: ["Mod"], key: "-" }],
"open in new pane (vertical)": [{ modifiers: ["Mod"], key: "i" }],
"open in new window": [{ modifiers: ["Mod"], key: "o" }],
"open in popup": [],
"open in new tab in background": [{ modifiers: ["Alt"], key: "o" }],
"open all in new tabs": [{ modifiers: ["Mod", "Shift", "Alt"], key: "o" }],
preview: [{ modifiers: ["Mod"], key: "," }],
dismiss: [{ modifiers: [], key: "Escape" }]
}
});
var createDefaultExcludeFrontMatterKeys = () => [
"aliases",
"alias",
"tag",
"tags",
"cssclass",
"publish"
];
var createDefaultSearchCommand = () => ({
name: "",
searchBy: {
tag: false,
link: false,
header: false,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "file",
allowFuzzySearchForSearchTarget: false,
minFuzzyMatchScore: 0.5,
targetExtensions: [],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: "",
sortPriorities: [],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: true
});
var createDefaultLinkSearchCommand = () => ({
name: "Link search",
searchBy: {
tag: false,
link: false,
header: false,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "link",
allowFuzzySearchForSearchTarget: false,
minFuzzyMatchScore: 0.5,
targetExtensions: [],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: "",
sortPriorities: [],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: false
});
var createDefaultBacklinkSearchCommand = () => ({
name: "Backlink search",
searchBy: {
tag: false,
link: false,
header: false,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "backlink",
allowFuzzySearchForSearchTarget: false,
minFuzzyMatchScore: 0.5,
targetExtensions: ["md"],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: "",
sortPriorities: ["Last opened", "Last modified"],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: false
});
var createDefault2HopLinkSearchCommand = () => ({
name: "2 hop link search",
searchBy: {
tag: true,
link: false,
header: false,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "2-hop-link",
allowFuzzySearchForSearchTarget: false,
minFuzzyMatchScore: 0.5,
targetExtensions: [],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: "",
sortPriorities: [
"Prefix name match",
"Alphabetical",
".md",
"Last opened",
"Last modified"
],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: false
});
var createPreSettingSearchCommands = () => [
{
name: "Recent search",
searchBy: {
tag: true,
header: false,
link: false,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "file",
allowFuzzySearchForSearchTarget: false,
minFuzzyMatchScore: 0.5,
targetExtensions: [],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: ":e ",
sortPriorities: ["Name match", ".md", "Last opened", "Last modified"],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: true
},
{
name: "File name search",
searchBy: {
tag: false,
link: false,
header: false,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "file",
allowFuzzySearchForSearchTarget: false,
minFuzzyMatchScore: 0.5,
targetExtensions: [],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: ":f ",
sortPriorities: [
"Prefix name match",
"Alphabetical",
".md",
"Last opened",
"Last modified"
],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: false
},
{
name: "File name fuzzy search",
searchBy: {
tag: false,
link: false,
header: false,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "file",
allowFuzzySearchForSearchTarget: true,
minFuzzyMatchScore: 0.5,
targetExtensions: [],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: "",
sortPriorities: [
"Prefix name match",
"Fuzzy name match",
".md",
"Last opened",
"Last modified"
],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: false
},
{
name: "Landmark search",
searchBy: {
tag: true,
link: true,
header: true,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "file",
allowFuzzySearchForSearchTarget: false,
minFuzzyMatchScore: 0.5,
targetExtensions: [],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: ":l ",
sortPriorities: [
"Prefix name match",
"Name match",
"Tag match",
"Header match",
"Link match",
".md",
"Last opened",
"Last modified"
],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: false
},
{
name: "Star search",
searchBy: {
tag: false,
link: false,
header: false,
property: false
},
keysOfPropertyToSearch: [],
searchTarget: "file",
allowFuzzySearchForSearchTarget: false,
minFuzzyMatchScore: 0.5,
targetExtensions: [],
floating: false,
showFrontMatter: false,
excludeFrontMatterKeys: createDefaultExcludeFrontMatterKeys(),
defaultInput: "",
restoreLastInput: false,
commandPrefix: ":s ",
sortPriorities: ["Star", ".md", "Last opened", "Last modified"],
includePrefixPathPatterns: [],
excludePrefixPathPatterns: [],
expand: false
},
createDefaultLinkSearchCommand(),
createDefault2HopLinkSearchCommand()
];
var DEFAULT_SETTINGS = {
searchDelayMilliSeconds: 0,
maxNumberOfSuggestions: 50,
normalizeAccentsAndDiacritics: false,
useSelectionWordsAsDefaultInputQuery: false,
preventDuplicateTabs: false,
// Appearance
showDirectory: true,
showDirectoryAtNewLine: false,
showFullPathOfDirectory: false,
showAliasesOnTop: false,
displayAliaseAsTitle: false,
showExistingFilesOnly: false,
hideGutterIcons: false,
hideHotkeyGuides: false,
// Hot keys in dialog
userAltInsteadOfModForQuickResultSelection: false,
hotkeys: createDefaultHotkeys(),
// Searches
searchCommands: createPreSettingSearchCommands(),
// Header search
autoPreviewInFloatingHeaderSearch: true,
// Backlink search
backlinkExcludePrefixPathPatterns: [],
// In file search
inFileContextLines: 2,
autoPreviewInFloatingInFileSearch: false,
inFileMaxDisplayLengthAroundMatchedWord: 64,
// Grep
ripgrepCommand: "rg",
grepExtensions: ["md"],
maxDisplayLengthAroundMatchedWord: 64,
// Move file to another folder
moveFileExcludePrefixPathPatterns: [],
// debug
showLogAboutPerformanceInConsole: false,
showFuzzyMatchScore: false
};
var AnotherQuickSwitcherSettingTab = class extends import_obsidian3.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.resetLock = true;
this.hotkeyExpandedStatus = {
main: false,
folder: false,
move: false,
header: false,
backlink: false,
link: false,
"in-file": false,
grep: false
};
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl("h2", { text: "Another Quick Switcher - Settings" });
this.addGeneralSettings(containerEl);
this.addAppearanceSettings(containerEl);
this.addHotKeysInDialogSettings(containerEl);
this.addSearchSettings(containerEl);
this.addHeaderSearchSettings(containerEl);
this.addBacklinkSettings(containerEl);
this.addInFileSettings(containerEl);
this.addGrepSettings(containerEl);
this.addMoveSettings(containerEl);
this.addDebugSettings(containerEl);
}
addGeneralSettings(containerEl) {
new import_obsidian3.Setting(containerEl).setName("Search delay milli-seconds").setDesc("If keyboard operation is slow, try increasing the value").addSlider(
(sc) => sc.setLimits(0, 1e3, 10).setValue(this.plugin.settings.searchDelayMilliSeconds).setDynamicTooltip().onChange(async (value) => {
this.plugin.settings.searchDelayMilliSeconds = value;
await this.plugin.saveSettings();
})
);
new import_obsidian3.Setting(containerEl).setName("Max number of suggestions").addSlider(
(sc) => sc.setLimits(1, 255, 1).setValue(this.plugin.settings.maxNumberOfSuggestions).setDynamicTooltip().onChange(async (value) => {
this.plugin.settings.maxNumberOfSuggestions = value;
await this.plugin.saveSettings();
})
);
new import_obsidian3.Setting(containerEl).setName("Normalize accents/diacritics").addToggle((tc) => {
tc.setValue(
this.plugin.settings.normalizeAccentsAndDiacritics
).onChange(async (value) => {
this.plugin.settings.normalizeAccentsAndDiacritics = value;
await this.plugin.saveSettings();
this.display();
});
});
if (this.plugin.settings.normalizeAccentsAndDiacritics) {
containerEl.createEl("div", {
text: "! If enabled, it is about 2 to 5 times slower than disabled",
cls: "another-quick-switcher__settings__warning"
});
}
new import_obsidian3.Setting(containerEl).setName("Use selection words as a default input query").addToggle((tc) => {
tc.setValue(
this.plugin.settings.useSelectionWordsAsDefaultInputQuery
).onChange(async (value) => {
this.plugin.settings.useSelectionWordsAsDefaultInputQuery = value;
await this.plugin.saveSettings();
});
});
new import_obsidian3.Setting(containerEl).setName("Prevent duplicate tabs").setDesc(
"If a file is already opened as a tab, it will not open in a new tab; instead, the existing tab will be activated. This option is enabled for three commands: 'open in new tab', 'open in new tab in background', and 'open all in new tabs'."
).addToggle((tc) => {
tc.setValue(this.plugin.settings.preventDuplicateTabs).onChange(
async (value) => {
this.plugin.settings.preventDuplicateTabs = value;
await this.plugin.saveSettings();
}
);
});
}
addAppearanceSettings(containerEl) {
containerEl.createEl("h3", { text: "\u{1F441}Appearance" });
new import_obsidian3.Setting(containerEl).setName("Show directory").addToggle((tc) => {
tc.setValue(this.plugin.settings.showDirectory).onChange(
async (value) => {
this.plugin.settings.showDirectory = value;
await this.plugin.saveSettings();
this.display();
}
);
});
if (this.plugin.settings.showDirectory) {
new import_obsidian3.Setting(containerEl).setName("Show directory at the new line").setClass("another-quick-switcher__settings__nested").addToggle((tc) => {
tc.setValue(this.plugin.settings.showDirectoryAtNewLine).onChange(
async (value) => {
this.plugin.settings.showDirectoryAtNewLine = value;
await this.plugin.saveSettings();
}
);
});
new import_obsidian3.Setting(containerEl).setName("Show full path of directory").setClass("another-quick-switcher__settings__nested").addToggle((tc) => {
tc.setValue(this.plugin.settings.showFullPathOfDirectory).onChange(
async (value) => {
this.plugin.settings.showFullPathOfDirectory = value;
await this.plugin.saveSettings();
}
);
});
}
new import_obsidian3.Setting(containerEl).setName("Display alias as title on keyword match").setDesc(
"When a keyword matches an alias, display the alias as the title."
).addToggle((tc) => {
tc.setValue(this.plugin.settings.showAliasesOnTop).onChange(
async (value) => {
this.plugin.settings.showAliasesOnTop = value;
await this.plugin.saveSettings();
}
);
});
new import_obsidian3.Setting(containerEl).setName("Display the alias as the title.").addToggle((tc) => {
tc.setValue(this.plugin.settings.displayAliaseAsTitle).onChange(
async (value) => {
this.plugin.settings.displayAliaseAsTitle = value;
await this.plugin.saveSettings();
}
);
});
new import_obsidian3.Setting(containerEl).setName("Show existing files only").addToggle((tc) => {
tc.setValue(this.plugin.settings.showExistingFilesOnly).onChange(
async (value) => {
this.plugin.settings.showExistingFilesOnly = value;
await this.plugin.saveSettings();
}
);
});
new import_obsidian3.Setting(containerEl).setName("Hide gutter icons").addToggle((tc) => {
tc.setValue(this.plugin.settings.hideGutterIcons).onChange(
async (value) => {
this.plugin.settings.hideGutterIcons = value;
await this.plugin.saveSettings();
}
);
});
new import_obsidian3.Setting(containerEl).setName("Hide hotkey guides").addToggle((tc) => {
tc.setValue(this.plugin.settings.hideHotkeyGuides).onChange(
async (value) => {
this.plugin.settings.hideHotkeyGuides = value;
await this.plugin.saveSettings();
}
);
});
}
addHotKeysInDialogSettings(containerEl) {
containerEl.createEl("h3", { text: "\u2328Hot keys in dialog" });
new import_obsidian3.Setting(containerEl).setName(
"Use `alt 1\uFF5E9` instead of `ctrl/cmd 1\uFF5E9` for quick result selection"
).addToggle((tc) => {
tc.setValue(
this.plugin.settings.userAltInsteadOfModForQuickResultSelection
).onChange(async (value) => {
this.plugin.settings.userAltInsteadOfModForQuickResultSelection = value;
await this.plugin.saveSettings();
});
});
const addHotkeyItems = (dialogKey, div) => {
if (!this.hotkeyExpandedStatus[dialogKey]) {
return;
}
const addHotKeyItem = (name, command) => {
new import_obsidian3.Setting(div).setName(name).setClass("another-quick-switcher__settings__dialog-hotkey-item").addText((cb) => {
const dialog = this.plugin.settings.hotkeys[dialogKey];
return cb.setValue(hotkey2String(dialog[command][0])).onChange(async (value) => {
var _a, _b;
const hk = string2Hotkey(
value,
(_b = (_a = dialog[command][0]) == null ? void 0 : _a.hideHotkeyGuide) != null ? _b : false
);
dialog[command] = hk ? [hk] : [];
await this.plugin.saveSettings();
});
}).addToggle((cb) => {
var _a;
const dialog = this.plugin.settings.hotkeys[dialogKey];
return cb.setTooltip("Show hotkey guide if enabled").setValue(!((_a = dialog[command][0]) == null ? void 0 : _a.hideHotkeyGuide)).onChange(async (showHotkeyGuide) => {
dialog[command] = dialog[command][0] ? [
{
...dialog[command][0],
hideHotkeyGuide: !showHotkeyGuide
}
] : [];
await this.plugin.saveSettings();
});
});
};
const keys = Object.keys(this.plugin.settings.hotkeys[dialogKey]);
for (const k of keys) {
addHotKeyItem(k, k);
}
};
const addHotkeysForDialog = (dialogKey, dialogName) => {
const div = createDiv({
cls: "another-quick-switcher__settings__dialog-hotkey"
});
containerEl.append(div);
const li = createEl("li");
li.append(
"You can know the keycode at ",
createEl("a", {
text: "keycode.info",
href: "https://keycode.info/"
}),
". (Press any key and show 'event.key')"
);
li.createEl("ul").createEl("li", {
text: "For the space key, please set the value to 'Space'."
});
const ul = createEl("ul");
ul.createEl("li", {
text: "'Ctrl a' means pressing the Ctrl key and the A key."
});
ul.createEl("li", {
text: "Use 'Mod' instead of 'Ctrl' on Windows or 'Cmd' on macOS."
});
ul.append(li);
const df = document.createDocumentFragment();
df.append(ul);
new import_obsidian3.Setting(div).setHeading().setName(dialogName).setDesc(df).addExtraButton(
(btn) => btn.setIcon(
this.hotkeyExpandedStatus[dialogKey] ? "chevron-up" : "chevron-down"
).setTooltip(
this.hotkeyExpandedStatus[dialogKey] ? "fold" : "unfold"
).onClick(() => {
this.hotkeyExpandedStatus[dialogKey] = !this.hotkeyExpandedStatus[dialogKey];
this.display();
})
);
addHotkeyItems(dialogKey, div);
};
addHotkeysForDialog("main", "Main dialog");
addHotkeysForDialog("folder", "Folder dialog");
addHotkeysForDialog("header", "Header dialog");
addHotkeysForDialog("backlink", "Backlink dialog");
addHotkeysForDialog("link", "Link dialog");
addHotkeysForDialog("in-file", "In File dialog");
addHotkeysForDialog("grep", "Grep dialog");
}
addSearchSettings(containerEl) {
containerEl.createEl("h3", { text: "\u{1F50D} Search commands" });
this.plugin.settings.searchCommands.forEach((_, i) => {
this.addSearchCommandSetting(
containerEl,
this.plugin.settings.searchCommands[i]
);
});
new import_obsidian3.Setting(containerEl).setHeading().addButton((btn) => {
btn.setButtonText("Add").setTooltip("Add a new command").setCta().setClass(
"another-quick-switcher__settings__search-command__add-button"
).onClick(async (_) => {
this.plugin.settings.searchCommands.push(
createDefaultSearchCommand()
);
this.display();
});
}).addButton((btn) => {
btn.setButtonText("Save").setTooltip(
"You must click this button to save settings before closing Obsidian"
).setCta().setClass(
"another-quick-switcher__settings__search-command__save-button"
).onClick(async (_) => {
this.plugin.settings.searchCommands = this.plugin.settings.searchCommands.filter((x) => x.name);
const invalidValues = this.plugin.settings.searchCommands.flatMap((x) => x.sortPriorities).filter((x) => !regardAsSortPriority(x));
if (invalidValues.length > 0) {
new import_obsidian3.Notice(
`
Invalid sort priorities:
${invalidValues.map((x) => `- ${x}`).join("\n")}
`.trim(),
0
);
return;
}
await this.plugin.saveSettings();
this.display();
this.plugin.reloadCommands();
new import_obsidian3.Notice("Save and reload commands");
});
});
new import_obsidian3.Setting(containerEl).setName("Reset all search commands").setClass("another-quick-switcher__settings__danger").setDesc(
"It means your customized commands will be removed. If you reset unintentionally, you can restore the search commands by closing settings and Obsidian immediately, then restart Obsidian."
).addToggle((cb) => {
cb.setValue(this.resetLock).onChange((lock) => {
this.resetLock = lock;
this.display();
});
if (this.resetLock) {
cb.setTooltip(
"Turn off the lock, if you want to reset all search commands"
);
}
}).addButton((btn) => {
btn.setButtonText("Reset").setTooltip("Reset all search commands!!").setDisabled(this.resetLock).onClick(() => {
this.plugin.settings.searchCommands = createPreSettingSearchCommands();
this.display();
});
if (!this.resetLock) {
btn.setCta();
}
});
}
addSearchCommandSetting(containerEl, command) {
const div = createDiv({
cls: "another-quick-switcher__settings__search-command"
});
containerEl.append(div);
new import_obsidian3.Setting(div).setClass("another-quick-switcher__settings__search-command__header").setHeading().addText((tc) => {
const el = tc.setPlaceholder("Command name").setValue(command.name).onChange(async (value) => {
command.name = value;
});
el.inputEl.setAttribute("style", "text-align: left");
return el;
}).addExtraButton((btn) => {
btn.setTooltip("Delete a command (!! it will never be restored !!)").setIcon("trash-2").onClick(() => {
this.plugin.settings.searchCommands.remove(command);
this.display();
});
btn.extraSettingsEl.addClass(
"another-quick-switcher__settings__search-command__header__delete"
);
return btn;
}).addExtraButton((btn) => {
btn.setIcon(command.expand ? "chevron-up" : "chevron-down").setTooltip(command.expand ? "fold" : "unfold").onClick(() => {
command.expand = !command.expand;
this.display();
});
btn.extraSettingsEl.addClass(
"another-quick-switcher__settings__search-command__header__fold-button"
);
return btn;
});
if (!command.expand) {
return;
}
const buttonClass = "another-quick-switcher__settings__search-command__search-by-button";
const buttonEnabledClass = "another-quick-switcher__settings__search-command__search-by-button_enabled";
const buttonDisabledClass = "another-quick-switcher__settings__search-command__search-by-button_disabled";
new import_obsidian3.Setting(div).setName("Search by").setDesc("Click the button to enable/disable the search target").addButton((bc) => {
const coloring = () => {
bc.buttonEl.removeClass(buttonEnabledClass, buttonDisabledClass);
bc.buttonEl.addClass(
command.searchBy.tag ? buttonEnabledClass : buttonDisabledClass
);
};
bc.setButtonText("Tag").setClass(buttonClass).onClick(async () => {
command.searchBy.tag = !command.searchBy.tag;
coloring();
});
coloring();
return bc;
}).addButton((bc) => {
const coloring = () => {
bc.buttonEl.removeClass(buttonEnabledClass, buttonDisabledClass);
bc.buttonEl.addClass(
command.searchBy.header ? buttonEnabledClass : buttonDisabledClass
);
};
bc.setButtonText("Header").setClass(buttonClass).onClick(async () => {
command.searchBy.header = !command.searchBy.header;
coloring();
});
coloring();
return bc;
}).addButton((bc) => {
const coloring = () => {
bc.buttonEl.removeClass(buttonEnabledClass, buttonDisabledClass);
bc.buttonEl.addClass(
command.searchBy.link ? buttonEnabledClass : buttonDisabledClass
);
};
bc.setButtonText("Link").setClass(buttonClass).onClick(async () => {
command.searchBy.link = !command.searchBy.link;
coloring();
});
coloring();
return bc;
}).addButton((bc) => {
const coloring = () => {
bc.buttonEl.removeClass(buttonEnabledClass, buttonDisabledClass);
bc.buttonEl.addClass(
command.searchBy.property ? buttonEnabledClass : buttonDisabledClass
);
};
bc.setButtonText("Property").setClass(buttonClass).onClick(async () => {
command.searchBy.property = !command.searchBy.property;
coloring();
this.display();
});
coloring();
return bc;
});
if (command.searchBy.property) {
new import_obsidian3.Setting(div).setName("Keys of the property to search").setDesc("Multiple entries can be specified, separated by line breaks.").addTextArea((tc) => {
const el = tc.setValue(command.keysOfPropertyToSearch.join("\n")).onChange(async (value) => {
command.keysOfPropertyToSearch = smartLineBreakSplit(value);
});
el.inputEl.className = "another-quick-switcher__settings__keys_of_property_to_search";
return el;
});
}
new import_obsidian3.Setting(div).setName("Search target").addDropdown((dc) => {
dc.addOptions(mirror([...searchTargetList])).setValue(command.searchTarget).onChange(async (value) => {
command.searchTarget = value;
});
});
new import_obsidian3.Setting(div).setName('Allow fuzzy search for "Search target"').addToggle((cb) => {
cb.setValue(command.allowFuzzySearchForSearchTarget).onChange(
async (value) => {
command.allowFuzzySearchForSearchTarget = value;
}
);
});
new import_obsidian3.Setting(div).setName("Min fuzzy match score").setDesc(
"Only show suggestion those score is more than the specific score"
).addSlider(
(sc) => sc.setLimits(0, 10, 0.1).setValue(command.minFuzzyMatchScore).setDynamicTooltip().onChange(async (value) => {
command.minFuzzyMatchScore = value;
})
);
new import_obsidian3.Setting(div).setName("Target extensions").setDesc(
"If set, only files whose extension equals will be suggested. If empty, all files will be suggested. It can set multi extensions using comma."
).addTextArea(
(tc) => tc.setPlaceholder("(ex: md,png,canvas)").setValue(command.targetExtensions.join(",")).onChange(async (value) => {
command.targetExtensions = smartCommaSplit(value);
})
);
new import_obsidian3.Setting(div).setName("Floating").addToggle((cb) => {
cb.setValue(command.floating).onChange(async (value) => {
command.floating = value;
this.display();
});
});
new import_obsidian3.Setting(div).setName("Show front matter").addToggle((cb) => {
cb.setValue(command.showFrontMatter).onChange(async (value) => {
command.showFrontMatter = value;
this.display();
});
});
if (command.showFrontMatter) {
new import_obsidian3.Setting(div).setName("Exclude front matter keys").setDesc("It can set multi patterns by line breaks.").addTextArea((tc) => {
const el = tc.setValue(command.excludeFrontMatterKeys.join("\n")).onChange(async (value) => {
command.excludeFrontMatterKeys = smartLineBreakSplit(value);
});
el.inputEl.className = "another-quick-switcher__settings__exclude_front_matter_keys";
return el;
});
}
new import_obsidian3.Setting(div).setName("Default input").setDesc("Default input strings when it opens the dialog").addText(
(tc) => tc.setValue(command.defaultInput).setPlaceholder("(ex: #todo )").onChange(async (value) => {
command.defaultInput = value;
})
);
new import_obsidian3.Setting(div).setName("Restore last input").setDesc(
"If enabled, this option will restore the last input, shared across all searches where it is enabled."
).addToggle((tc) => {
tc.setValue(command.restoreLastInput).onChange(async (value) => {
command.restoreLastInput = value;
});
});
new import_obsidian3.Setting(div).setName("Command prefix").setDesc(
"For example, if it sets ':r ', a query starts with ':r ' means that search as this command"
).addText(
(tc) => tc.setValue(command.commandPrefix).setPlaceholder("(ex: :r )").onChange(async (value) => {
command.commandPrefix = value;
})
);
const df = document.createDocumentFragment();
df.append(
"Valid sort priorities refer to ",
createEl("a", {
text: "README",
href: "https://github.com/tadashi-aikawa/obsidian-another-quick-switcher#sort-priorities"
})
);
new import_obsidian3.Setting(div).setName("Sort priorities").setDesc(df).addTextArea((tc) => {
const el = tc.setPlaceholder("").setValue(command.sortPriorities.join("\n")).onChange(async (value) => {
const priorities = smartLineBreakSplit(value);
command.sortPriorities = priorities;
});
el.inputEl.addClass(
"another-quick-switcher__settings__search-command__sort-priority"
);
return el;
});
new import_obsidian3.Setting(div).setName("Include prefix path patterns").setDesc(
"If set, only files whose paths start with one of the patterns will be suggested. It can set multi patterns by line breaks. <current_dir> means current directory."
).addTextArea((tc) => {
const el = tc.setPlaceholder("(ex: Notes/Private)").setValue(command.includePrefixPathPatterns.join("\n")).onChange(async (value) => {
command.includePrefixPathPatterns = smartLineBreakSplit(value);
});
el.inputEl.className = "another-quick-switcher__settings__include_path_patterns";
return el;
});
new import_obsidian3.Setting(div).setName("Exclude prefix path patterns").setDesc(
"If set, files whose paths start with one of the patterns will not be suggested. It can set multi patterns by line breaks. <current_dir> means current directory."
).addTextArea((tc) => {
const el = tc.setPlaceholder("(ex: Notes/Private)").setValue(command.excludePrefixPathPatterns.join("\n")).onChange(async (value) => {
command.excludePrefixPathPatterns = smartLineBreakSplit(value);
});
el.inputEl.className = "another-quick-switcher__settings__exclude_path_patterns";
return el;
});
}
addHeaderSearchSettings(containerEl) {
containerEl.createEl("h3", { text: "\u{1F4D2} Header search" });
new import_obsidian3.Setting(containerEl).setName("Auto preview in the floating mode").addToggle((tc) => {
tc.setValue(
this.plugin.settings.autoPreviewInFloatingHeaderSearch
).onChange(async (value) => {
this.plugin.settings.autoPreviewInFloatingHeaderSearch = value;
await this.plugin.saveSettings();
});
});
}
addBacklinkSettings(containerEl) {
containerEl.createEl("h3", { text: "\u{1F50D} Backlink search" });
new import_obsidian3.Setting(containerEl).setName('Exclude prefix path patterns for "Backlink search"').setDesc(
"If set, folders whose paths start with one of the patterns will not be suggested. It can set multi patterns by line breaks"
).addTextArea((tc) => {
const el = tc.setPlaceholder("Prefix match patterns").setValue(
this.plugin.settings.backlinkExcludePrefixPathPatterns.join("\n")
).onChange(async (value) => {
this.plugin.settings.backlinkExcludePrefixPathPatterns = smartLineBreakSplit(value);
await this.plugin.saveSettings();
});
el.inputEl.className = "another-quick-switcher__settings__ignore_path_patterns";
return el;
});
}
addInFileSettings(containerEl) {
containerEl.createEl("h3", { text: "\u{1F50D} In file search" });
new import_obsidian3.Setting(containerEl).setName("Context Lines").setDesc(
"Specifies the number of lines to display before and after the target line. For instance, setting this to '2' would display two lines before and two lines after the target line, providing context to the selected text"
).addSlider(
(sc) => sc.setLimits(0, 10, 1).setValue(this.plugin.settings.inFileContextLines).setDynamicTooltip().onChange(async (value) => {
this.plugin.settings.inFileContextLines = value;
await this.plugin.saveSettings();
})
);
new import_obsidian3.Setting(containerEl).setName("Auto preview in the floating mode").addToggle((tc) => {
tc.setValue(
this.plugin.settings.autoPreviewInFloatingInFileSearch
).onChange(async (value) => {
this.plugin.settings.autoPreviewInFloatingInFileSearch = value;
await this.plugin.saveSettings();
});
});
new import_obsidian3.Setting(containerEl).setName("Max display length around matched word").setDesc(
"Maximum display character count before or after the matched word."
).addSlider(
(sc) => sc.setLimits(1, 255, 1).setValue(
this.plugin.settings.inFileMaxDisplayLengthAroundMatchedWord
).setDynamicTooltip().onChange(async (value) => {
this.plugin.settings.inFileMaxDisplayLengthAroundMatchedWord = value;
await this.plugin.saveSettings();
})
);
}
addGrepSettings(containerEl) {
containerEl.createEl("h3", { text: "\u{1F50D} Grep" });
new import_obsidian3.Setting(containerEl).setName("Ripgrep command").setDesc("A command that can execute ripgrep").addText(
(tc) => tc.setValue(this.plugin.settings.ripgrepCommand).onChange(async (value) => {
this.plugin.settings.ripgrepCommand = value;
await this.plugin.saveSettings();
})
);
new import_obsidian3.Setting(containerEl).setName("Extensions").addText(
(tc) => tc.setPlaceholder("(ex: md,html,css)").setValue(this.plugin.settings.grepExtensions.join(",")).onChange(async (value) => {
this.plugin.settings.grepExtensions = smartCommaSplit(value);
await this.plugin.saveSettings();
})
);
new import_obsidian3.Setting(containerEl).setName("Max display length around matched word").setDesc(
"Maximum display character count before or after the matched word."
).addSlider(
(sc) => sc.setLimits(1, 255, 1).setValue(this.plugin.settings.maxDisplayLengthAroundMatchedWord).setDynamicTooltip().onChange(async (value) => {
this.plugin.settings.maxDisplayLengthAroundMatchedWord = value;
await this.plugin.saveSettings();
})
);
}
addMoveSettings(containerEl) {
containerEl.createEl("h3", { text: "\u{1F4C1} Move file to another folder" });
new import_obsidian3.Setting(containerEl).setName('Exclude prefix path patterns for "Move file to another folder"').setDesc(
"If set, folders whose paths start with one of the patterns will not be suggested. It can set multi patterns by line breaks"
).addTextArea((tc) => {
const el = tc.setPlaceholder("Prefix match patterns").setValue(
this.plugin.settings.moveFileExcludePrefixPathPatterns.join("\n")
).onChange(async (value) => {
this.plugin.settings.moveFileExcludePrefixPathPatterns = smartLineBreakSplit(value);
await this.plugin.saveSettings();
});
el.inputEl.className = "another-quick-switcher__settings__ignore_path_patterns";
return el;
});
}
addDebugSettings(containerEl) {
containerEl.createEl("h3", { text: "Debug" });
new import_obsidian3.Setting(containerEl).setName("Show log about performance in a console").addToggle((tc) => {
tc.setValue(
this.plugin.settings.showLogAboutPerformanceInConsole
).onChange(async (value) => {
this.plugin.settings.showLogAboutPerformanceInConsole = value;
await this.plugin.saveSettings();
});
});
new import_obsidian3.Setting(containerEl).setName("Show fuzzy match score in the dialog").addToggle((tc) => {
tc.setValue(this.plugin.settings.showFuzzyMatchScore).onChange(
async (value) => {
this.plugin.settings.showFuzzyMatchScore = value;
await this.plugin.saveSettings();
}
);
});
}
};
// src/utils/logger.ts
function buildLogMessage(message, msec) {
return `${message}: ${Math.round(msec)}[ms]`;
}
var Logger = class _Logger {
constructor(settings) {
this.settings = settings;
}
static of(settings) {
return new _Logger(settings);
}
showDebugLog(message, startTs) {
if (this.settings.showLogAboutPerformanceInConsole) {
console.log(buildLogMessage(message, performance.now() - startTs));
}
}
};
// src/ui/icons.ts
var FOLDER = `<svg viewBox="0 0 100 100" class="folder" width="17" height="17"><path fill="currentColor" stroke="currentColor" d="M6.1,8c-3.3,0-6,2.7-6,6v73.8c-0.1,0.5-0.1,0.9,0.1,1.4c0.6,2.7,3,4.8,5.9,4.8h78c3,0,5.4-2.2,5.9-5.1 c0-0.1,0.1-0.2,0.1-0.4c0,0,0-0.1,0-0.1l0.1-0.3c0,0,0,0,0-0.1l9.9-53.6l0.1-0.2V34c0-3.3-2.7-6-6-6v-6c0-3.3-2.7-6-6-6H36.1 c0,0,0,0-0.1,0c-0.1,0-0.2-0.2-0.6-0.6c-0.5-0.6-1.1-1.5-1.7-2.5c-0.6-1-1.3-2.1-2.1-3C30.9,9,29.7,8,28.1,8L6.1,8z M6.1,12h22 c-0.1,0,0.1,0,0.6,0.6c0.5,0.6,1.1,1.5,1.7,2.5c0.6,1,1.3,2.1,2.1,3c0.8,0.9,1.9,1.9,3.6,1.9h52c1.1,0,2,0.9,2,2v6h-74 c-3.1,0-5.7,2.5-5.9,5.6h-0.1L10.1,34l-6,32.4V14C4.1,12.9,4.9,12,6.1,12z M16.1,32h78c1.1,0,2,0.9,2,2l-9.8,53.1l-0.1,0.1 c0,0.1,0,0.2-0.1,0.2c0,0.1,0,0.2-0.1,0.2c0,0,0,0.1,0,0.1c0,0,0,0,0,0.1c0,0.1,0,0.2-0.1,0.3c0,0.1,0,0.1,0,0.2 c0,0.1,0,0.2,0,0.2c-0.3,0.8-1,1.4-1.9,1.4h-78c-1.1,0-2-0.9-2-2L14,34.4l0.1-0.2V34C14.1,32.9,14.9,32,16.1,32L16.1,32z"></path></svg>`;
var ALIAS = `<svg viewBox="0 0 100 100" class="forward-arrow" width="16" height="16"><path fill="currentColor" stroke="currentColor" d="m9.9,89.09226c-0.03094,0 -0.05414,0 -0.08508,0c-1.06734,-0.04641 -1.91039,-0.92812 -1.89492,-1.99547c0.00774,-0.48726 1.14469,-48.13101 47.52,-49.44586l0,-13.89094c0,-0.7657 0.44086,-1.4618 1.12922,-1.78664c0.68062,-0.33258 1.5082,-0.23203 2.09601,0.2475l31.68,25.74c0.46406,0.37899 0.73476,0.9436 0.73476,1.53914c0,0.59555 -0.2707,1.16016 -0.72703,1.53914l-31.68,25.74c-0.59555,0.47953 -1.41539,0.57234 -2.10375,0.2475c-0.68836,-0.32485 -1.12922,-1.02094 -1.12922,-1.78664l0,-13.84453c-41.26289,0.75024 -43.49039,24.81961 -43.56773,25.85601c-0.06961,1.04414 -0.93586,1.84078 -1.97226,1.84078z"></path></svg>`;
var TAG = `<svg viewBox="0 0 100 100" class="hashtag" width="17" height="17"><path fill="currentColor" stroke="currentColor" d="M36,18l-1.5,16H20l-0.4,4h14.5l-2.4,26H17.2l-0.4,4h14.5L30,82h4l1.3-14h26L60,82h4l1.3-14h15.5l0.4-4H65.7l2.4-26h15.5 l0.4-4H68.5L70,18h-4l-1.5,16h-26L40,18L36,18z M38.1,38h26l-2.4,26h-26L38.1,38z"></path></svg>`;
var LINK = `<svg viewBox="0 0 100 100" class="links-going-out" width="15" height="15"><path fill="currentColor" stroke="currentColor" d="M76.4,11.7c3.7,3.8,5.6,8.9,5,14.3c-0.5,4-2.4,7.6-5.2,10.5c-2.6,2.6-6.7,6.7-9.2,9.2c-2,2-4.4,3.6-7.1,4.5 c-4.5,1.4-9,1-12.8-0.9l2.9-2.9c1.4,0.5,3,0.8,4.5,0.8c3.6,0,7-1.4,9.5-3.9l9.6-9.6c3.3-3.3,4.7-8.1,3.5-13 c-0.3-1.2-0.8-2.4-1.5-3.5C73,13,68.7,10.6,64,10.6c-3.6,0-7,1.4-9.5,3.9L45,24c-2.5,2.5-3.9,5.9-3.9,9.5c0,1.6,0.3,3.1,0.8,4.5 l-3,3c-1.1-2.3-1.7-4.8-1.7-7.5c0-0.7,0-1.4,0.1-2.1c0.5-3.8,2.2-7.4,5-10.2l9.4-9.4C54.5,9,58.2,7,62.1,6.6 C67.5,6.1,72.6,7.9,76.4,11.7L76.4,11.7z M54.4,34.7c0.3,0.7,0.1,1.6-0.4,2.1L30.9,59.9c-0.5,0.5-1.2,0.7-1.9,0.5 s-1.2-0.7-1.4-1.4s0-1.4,0.5-1.9L51.2,34c0.3-0.4,0.8-0.6,1.3-0.6C53.4,33.5,54.1,34,54.4,34.7z M35.1,44.9l-2.9,2.9 c-1.4-0.5-3-0.8-4.5-0.8c-3.6,0-7,1.4-9.5,3.9l-9.6,9.6c-3.3,3.4-4.7,8.1-3.5,13c0.3,1.2,0.8,2.4,1.5,3.5 c2.6,4.2,6.9,6.6,11.6,6.6c3.6,0,7-1.4,9.5-3.9l9.6-9.6c2.5-2.5,3.9-5.9,3.9-9.5c0-1.6-0.3-3.1-0.8-4.5l2.9-2.9 c1.1,2.3,1.7,4.8,1.7,7.5c0,3-0.8,5.9-2.2,8.5c-0.8,1-1.5,1.9-2.1,2.9c-0.3,0.3-0.5,0.6-0.8,0.8l-9.4,9.4 c-2.9,2.9-6.6,4.8-10.6,5.2c-6.2,0.6-12-1.9-15.8-6.9c-2.4-3.2-3.6-7.2-3.4-11.2c0-0.1,0-0.2,0-0.3c0.3-4.2,2-8.1,5-11.1l9.4-9.4 c2-2,4.4-3.6,7.1-4.5C26.8,42.6,31.3,43,35.1,44.9L35.1,44.9z"></path><path fill="currentColor" stroke="currentColor" d="M99.2,69.3c0-0.2,0-0.2,0-0.4c0-0.2,0-0.2,0-0.4s0-0.2-0.2-0.4c0-0.2,0-0.2-0.2-0.4l0,0l-0.2-0.2l-0.2-0.2L79.2,53 c-0.6-0.4-1.3-0.6-1.9-0.2c-0.8,0.4-1.2,1-1.2,1.7V62c-8.1,0.4-14.6,3.1-19.2,8.1c-8.5,9-7.7,22.5-7.7,23.1c0,0.2,0,0.2,0,0.4 c0,0.2,0,0.2,0,0.4s0.2,0.2,0.2,0.4l0.2,0.2c0.2,0.2,0.2,0.2,0.4,0.2l0.2,0.2c0.2,0,0.4,0,0.6,0.2H51l0,0l0,0c0,0,0,0,0.2,0 s0.2,0,0.4,0s0.2,0,0.4-0.2c0.2,0,0.2-0.2,0.4-0.2s0.2-0.2,0.4-0.2c0,0,0.2-0.2,0.2-0.4c0-0.2,0.2-0.2,0.2-0.4s0-0.2,0-0.4 c0-0.2,0-0.2,0-0.4c0-0.8,0.6-16.6,23.1-17.5v7.3c0,0.8,0.4,1.3,1,1.7c0.6,0.4,1.3,0.2,1.9-0.2l19.2-14l0.2-0.2l0.2-0.2l0,0 c0-0.2,0.2-0.2,0.2-0.4L99.2,69.3L99.2,69.3z"></path></svg>`;
var HEADER = `<svg viewBox="0 0 100 100" class="bullet-list" width="15" height="15"><path fill="currentColor" stroke="currentColor" d="M16.4,16.4c-3.5,0-6.4,2.9-6.4,6.4s2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4S19.9,16.4,16.4,16.4z M16.4,19.6 c1.8,0,3.2,1.4,3.2,3.2c0,1.8-1.4,3.2-3.2,3.2s-3.2-1.4-3.2-3.2C13.2,21,14.6,19.6,16.4,19.6z M29.2,21.2v3.2H90v-3.2H29.2z M16.4,43.6c-3.5,0-6.4,2.9-6.4,6.4s2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4S19.9,43.6,16.4,43.6z M16.4,46.8c1.8,0,3.2,1.4,3.2,3.2 s-1.4,3.2-3.2,3.2s-3.2-1.4-3.2-3.2S14.6,46.8,16.4,46.8z M29.2,48.4v3.2H90v-3.2H29.2z M16.4,70.8c-3.5,0-6.4,2.9-6.4,6.4 c0,3.5,2.9,6.4,6.4,6.4s6.4-2.9,6.4-6.4C22.8,73.7,19.9,70.8,16.4,70.8z M16.4,74c1.8,0,3.2,1.4,3.2,3.2c0,1.8-1.4,3.2-3.2,3.2 s-3.2-1.4-3.2-3.2C13.2,75.4,14.6,74,16.4,74z M29.2,75.6v3.2H90v-3.2H29.2z"></path></svg>`;
var SEARCH = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 22h14a2 2 0 0 0 2-2V7.5L14.5 2H6a2 2 0 0 0-2 2v3"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<path d="M5 17a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"></path>
<path d="m9 18-1.5-1.5"></path>
</svg>`;
var FILTER = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon>
</svg>`;
var FRONT_MATTER = `<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 20 20"><g fill="none"><path d="M10.32 2.013A4 4 0 0 0 6.162 7.13l-3.987 3.986a.6.6 0 0 0-.176.424V14.4a.6.6 0 0 0 .6.6h2.8a.6.6 0 0 0 .6-.6V13h1.9a.6.6 0 0 0 .6-.6v-1.693l.735-.735a5.51 5.51 0 0 1-.569-.846l-.99.991a.6.6 0 0 0-.176.424V12H5.6a.6.6 0 0 0-.6.6V14H3v-2.293l4.32-4.32l-.118-.303a3.001 3.001 0 0 1 1.96-3.965c.33-.423.72-.796 1.157-1.106zM13.5 6.25a.75.75 0 1 0 0-1.5a.75.75 0 0 0 0 1.5zM9 6.5a4.5 4.5 0 1 1 7 3.742v2.05l.783.784a.6.6 0 0 1 0 .848L15.707 15l1.068 1.067a.6.6 0 0 1-.05.893l-2.35 1.88a.6.6 0 0 1-.75 0l-2.4-1.92a.6.6 0 0 1-.225-.468v-6.21A4.496 4.496 0 0 1 9 6.5zM13.5 3a3.5 3.5 0 0 0-1.75 6.532a.5.5 0 0 1 .25.433v6.295l2 1.6l1.751-1.401l-1.034-1.035a.6.6 0 0 1 0-.848l1.076-1.076l-.617-.617a.6.6 0 0 1-.176-.424V9.965a.5.5 0 0 1 .25-.433A3.5 3.5 0 0 0 13.5 3z" fill="currentColor"></path></g></svg>`;
var PREVIEW = `<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 20 20"><g fill="none"><path d="M19 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V5a2 2 0 0 0-2-2zm0 16H5V7h14v12zm-5.5-6c0 .83-.67 1.5-1.5 1.5s-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5s1.5.67 1.5 1.5zM12 9c-2.73 0-5.06 1.66-6 4c.94 2.34 3.27 4 6 4s5.06-1.66 6-4c-.94-2.34-3.27-4-6-4zm0 6.5a2.5 2.5 0 0 1 0-5a2.5 2.5 0 0 1 0 5z" fill="currentColor"></path></g></svg>`;
var SCORE = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="16" viewBox="0 0 20 20"><g fill="none"><path d="M11 6H9V4h2v2zm4-2h-2v2h2V4zM9 14h2v-2H9v2zm10-4V8h-2v2h2zm0 4v-2h-2v2h2zm-6 0h2v-2h-2v2zm6-10h-2v2h2V4zm-6 4V6h-2v2h2zm-6 2V8h2V6H7V4H5v16h2v-8h2v-2H7zm8 2h2v-2h-2v2zm-4-2v2h2v-2h-2zM9 8v2h2V8H9zm4 2h2V8h-2v2zm2-4v2h2V6h-2z" fill="currentColor"></path></g></svg>`;
// src/ui/modal.ts
function setFloatingModal(appHelper) {
var _a;
(_a = activeWindow.activeDocument.querySelector(".modal-bg")) == null ? void 0 : _a.addClass("another-quick-switcher__floating-modal-bg");
const promptEl = activeWindow.activeDocument.querySelector(".prompt");
promptEl == null ? void 0 : promptEl.addClass("another-quick-switcher__floating-prompt");
const fileView = appHelper.getFileViewInActiveLeaf();
if (fileView) {
const windowWidth = activeWindow.innerWidth;
const windowHeight = activeWindow.innerHeight;
const modalEl = activeWindow.activeDocument.querySelector(
".another-quick-switcher__floating-prompt"
);
if (!modalEl) {
console.error("Unexpected error.");
return;
}
const selector = fileView.getState().mode === "preview" ? ".markdown-preview-sizer" : ".cm-sizer";
const editorContentEl = fileView.contentEl.querySelector(selector);
if (!editorContentEl) {
console.error("Unexpected error.");
return;
}
const { width: modalWidth, height: modalHeight } = modalEl.getBoundingClientRect();
const { x: contentX, width: contentWidth } = editorContentEl.getBoundingClientRect();
const { y: leafY } = fileView.containerEl.getBoundingClientRect();
const { y: promptY } = promptEl.getBoundingClientRect();
const contentXEnd = contentX + contentWidth;
const left = windowWidth - contentXEnd - 30 > modalWidth ? contentXEnd - 30 : contentX - modalWidth - 30 > 0 ? contentX - modalWidth : windowWidth - modalWidth - 30;
const top = Math.min(windowHeight - modalHeight - 10, leafY + promptY);
promptEl == null ? void 0 : promptEl.setAttribute("style", `left: ${left}px; top: ${top}px`);
}
}
// src/utils/math.ts
function round(n, decimalPlace) {
const x = 10 ** decimalPlace;
return Math.round(n * x) / x;
}
// src/ui/suggestion-factory.ts
function createItemDiv(item, aliasesDisplayedAsTitle, options) {
var _a, _b;
const itemDiv = createDiv({
cls: [
"another-quick-switcher__item",
item.phantom ? "another-quick-switcher__phantom_item" : "",
item.starred ? "another-quick-switcher__starred_item" : "",
options.hideGutterIcons ? "another-quick-switcher__gutter_hidden" : ""
].filter((x) => x),
attr: {
extension: item.file.extension
}
});
const entryDiv = createDiv({
cls: "another-quick-switcher__item__entry"
});
const shouldShowAliasAsTitle = aliasesDisplayedAsTitle.length > 0 && (options.displayAliaseAsTitle || options.displayAliasAsTitleOnKeywordMatched);
const titleDiv = createDiv({
cls: "another-quick-switcher__item__title",
text: shouldShowAliasAsTitle ? aliasesDisplayedAsTitle.join(" / ") : item.file.basename
});
entryDiv.appendChild(titleDiv);
const isExcalidrawFile = isExcalidraw(item.file);
if (item.file.extension !== "md" || isExcalidrawFile) {
const extDiv = createDiv({
cls: "another-quick-switcher__item__extension",
text: isExcalidrawFile ? "excalidraw" : item.file.extension
});
titleDiv.appendChild(extDiv);
}
if (item.order < 9) {
const hotKeyGuide = createSpan({
cls: "another-quick-switcher__item__hot-key-guide",
text: `${item.order + 1}`
});
entryDiv.appendChild(hotKeyGuide);
}
if (options.showDirectory) {
const directoryDiv = createDiv({
cls: "another-quick-switcher__item__directory"
});
directoryDiv.insertAdjacentHTML("beforeend", FOLDER);
const text = options.showFullPathOfDirectory ? (_a = item.file.parent) == null ? void 0 : _a.path : (_b = item.file.parent) == null ? void 0 : _b.name;
directoryDiv.appendText(` ${text}`);
entryDiv.appendChild(directoryDiv);
if (options.showDirectoryAtNewLine) {
itemDiv.appendChild(entryDiv);
itemDiv.appendChild(directoryDiv);
return itemDiv;
}
}
itemDiv.appendChild(entryDiv);
return itemDiv;
}
function createMetaDiv(args) {
const { frontMatter, options } = args;
const metaDiv = createDiv({
cls: "another-quick-switcher__item__metas"
});
if (options.showFuzzyMatchScore && args.score > 0) {
const scoreDiv = createDiv({
cls: "another-quick-switcher__item__meta"
});
const scoreSpan = createSpan({
cls: "another-quick-switcher__item__meta__score"
});
scoreSpan.insertAdjacentHTML("beforeend", SCORE);
scoreSpan.appendText(String(args.score));
scoreDiv.appendChild(scoreSpan);
metaDiv.appendChild(scoreDiv);
}
if (options.showFrontMatter && Object.keys(frontMatter).length > 0) {
const frontMattersDiv = createDiv({
cls: "another-quick-switcher__item__meta"
});
for (const [key, value] of Object.entries(frontMatter)) {
const frontMatterDiv = createDiv({
cls: "another-quick-switcher__item__meta__front_matter",
title: `${key}: ${value}`
});
frontMatterDiv.insertAdjacentHTML("beforeend", FRONT_MATTER);
frontMatterDiv.createSpan({
cls: "another-quick-switcher__item__meta__front_matter__key",
title: key,
text: key
});
for (const v of [value].flat()) {
frontMatterDiv.createSpan({
cls: "another-quick-switcher__item__meta__front_matter__value",
title: v.toString(),
text: v.toString()
});
}
frontMattersDiv.appendChild(frontMatterDiv);
}
metaDiv.appendChild(frontMattersDiv);
}
return metaDiv;
}
function createDescriptionDiv(args) {
const {
item,
aliases,
tags,
countByLink,
countByHeader,
linkResultsNum,
headerResultsNum,
options
} = args;
const descriptionDiv = createDiv({
cls: "another-quick-switcher__item__descriptions"
});
if (aliases.length > 0) {
const aliasDiv = createDiv({
cls: "another-quick-switcher__item__description"
});
const displayAliases = options.displayAliasAsTitleOnKeywordMatched ? [item.file.basename] : aliases;
for (const x of displayAliases) {
const aliasSpan = createSpan({
cls: "another-quick-switcher__item__description__alias"
});
aliasSpan.insertAdjacentHTML("beforeend", ALIAS);
aliasSpan.appendText(x);
aliasDiv.appendChild(aliasSpan);
}
descriptionDiv.appendChild(aliasDiv);
}
if (tags.length > 0) {
const tagsDiv = createDiv({
cls: "another-quick-switcher__item__description"
});
for (const x of tags) {
const tagsSpan = createSpan({
cls: "another-quick-switcher__item__description__tag"
});
tagsSpan.insertAdjacentHTML("beforeend", TAG);
tagsSpan.appendText(x.replace("#", ""));
tagsDiv.appendChild(tagsSpan);
}
descriptionDiv.appendChild(tagsDiv);
}
if (Object.keys(countByLink).length > 0) {
const linksDiv = createDiv({
cls: "another-quick-switcher__item__description"
});
const linkAndCount = Object.entries(countByLink).map(([link, n]) => ({ link, n })).sort((a, b) => b.n - a.n);
for (const { link, n } of linkAndCount) {
const linkSpan = createSpan({
cls: [
"another-quick-switcher__item__description__link",
n !== linkResultsNum ? "another-quick-switcher__item__description__link__dimmed" : ""
]
});
linkSpan.insertAdjacentHTML("beforeend", LINK);
linkSpan.appendChild(
createSpan({ text: link, attr: { style: "padding-left: 3px" } })
);
linksDiv.appendChild(linkSpan);
}
descriptionDiv.appendChild(linksDiv);
}
if (Object.keys(countByHeader).length > 0) {
const headersDiv = createDiv({
cls: "another-quick-switcher__item__description"
});
const headerAndCount = Object.entries(countByHeader).map(([header, n]) => ({ header, n })).sort((a, b) => b.n - a.n);
for (const { header, n } of headerAndCount) {
const headersSpan = createSpan({
cls: [
"another-quick-switcher__item__description__header",
n !== headerResultsNum ? "another-quick-switcher__item__description__header__dimmed" : ""
]
});
headersSpan.insertAdjacentHTML("beforeend", HEADER);
headersSpan.appendChild(
createSpan({ text: header, attr: { style: "padding-left: 3px" } })
);
headersDiv.appendChild(headersSpan);
}
descriptionDiv.appendChild(headersDiv);
}
return descriptionDiv;
}
function createElements(item, options) {
var _a;
const aliases = uniqFlatMap(
item.matchResults.filter((res) => res.alias),
(x) => {
var _a2;
return (_a2 = x.meta) != null ? _a2 : [];
}
);
const itemDiv = createItemDiv(
item,
options.displayAliaseAsTitle ? item.aliases : aliases,
options
);
const frontMatter = omitBy(
(_a = item.frontMatter) != null ? _a : {},
(key, value) => options.excludeFrontMatterKeys.includes(key) || value == null
);
const maxScore = round(
Math.max(...item.matchResults.map((a) => {
var _a2;
return (_a2 = a.score) != null ? _a2 : 0;
})),
6
);
const metaDiv = Object.keys(frontMatter).length > 0 || maxScore > 0 ? createMetaDiv({
frontMatter,
score: maxScore,
options
}) : void 0;
const tags = uniqFlatMap(
item.matchResults.filter((res) => res.type === "tag"),
(x) => {
var _a2;
return (_a2 = x.meta) != null ? _a2 : [];
}
);
const linkResults = item.matchResults.filter((res) => res.type === "link");
const linkResultsNum = linkResults.length;
const countByLink = count(linkResults.flatMap((xs) => {
var _a2;
return uniq((_a2 = xs.meta) != null ? _a2 : []);
}));
const headerResults = item.matchResults.filter(
(res) => res.type === "header"
);
const headerResultsNum = headerResults.length;
const countByHeader = count(
headerResults.flatMap((xs) => {
var _a2;
return uniq((_a2 = xs.meta) != null ? _a2 : []);
})
);
const descriptionDiv = aliases.length !== 0 || tags.length !== 0 || Object.keys(countByLink).length !== 0 || Object.keys(countByHeader).length !== 0 ? createDescriptionDiv({
item,
aliases,
tags,
countByLink,
countByHeader,
linkResultsNum,
headerResultsNum,
options
}) : void 0;
return {
itemDiv,
metaDiv,
descriptionDiv
};
}
// src/ui/AnotherQuickSwitcherModal.ts
var globalInternalStorage = {
query: ""
};
var AnotherQuickSwitcherModal = class _AnotherQuickSwitcherModal extends import_obsidian4.SuggestModal {
constructor(args) {
var _a;
super(args.app);
this.willSilentClose = false;
this.historyRestoreStatus = "initial";
this.isClosed = new Promise((resolve) => {
this.markClosed = resolve;
});
this.modalEl.addClass("another-quick-switcher__modal-prompt");
this.appHelper = new AppHelper(args.app);
this.settings = args.settings;
this.logger = Logger.of(this.settings);
this.initialCommand = args.command;
this.command = args.command;
this.originFile = args.originFile;
this.floating = args.command.floating;
this.initialInputQuery = args.inputQuery;
this.navigationHistories = args.navigationHistories;
this.currentNavigationHistoryIndex = args.currentNavigationHistoryIndex;
this.stackHistory = args.stackHistory;
this.initialLeaf = args.initialLeaf;
this.stateToRestore = args.initialState;
this.navQueue = (_a = args.navQueue) != null ? _a : Promise.resolve();
this.limit = this.settings.maxNumberOfSuggestions;
this.setHotkeys();
this.phantomItems = this.settings.showExistingFilesOnly ? [] : this.appHelper.searchPhantomFiles().map((x) => ({
file: x,
aliases: [],
tags: [],
headers: [],
links: [],
phantom: true,
starred: false,
matchResults: [],
tokens: x.basename.split(" ")
}));
this.indexingItems();
this.debounceGetSuggestions = (0, import_obsidian4.debounce)(
(query, cb) => {
cb(this._getSuggestions(query));
},
this.settings.searchDelayMilliSeconds,
true
);
}
close() {
if (import_obsidian4.Platform.isMobile) {
this.onClose();
}
super.close();
}
safeClose() {
this.close();
return this.isClosed;
}
silentClose() {
this.willSilentClose = true;
this.close();
}
onOpen() {
var _a, _b;
this.isOpen = true;
this.inputEl.value = this.command.restoreLastInput ? (_a = this.initialInputQuery) != null ? _a : globalInternalStorage.query : (_b = this.initialInputQuery) != null ? _b : "";
this.inputEl.select();
this.updateSuggestions();
if (this.command.floating) {
this.enableFloating();
}
if (this.stackHistory) {
this.navigationHistories.push({
inputQuery: this.inputEl.value,
command: { ...this.command },
originFile: this.originFile
});
}
this.opened = true;
}
onClose() {
super.onClose();
if (this.willSilentClose) {
return;
}
if (this.command.restoreLastInput) {
globalInternalStorage.query = this.inputEl.value;
}
if (this.stateToRestore) {
this.navigate(() => this.stateToRestore.restore());
}
this.navigate(this.markClosed);
}
enableFloating() {
this.floating = true;
if (!import_obsidian4.Platform.isPhone) {
setFloatingModal(this.appHelper);
}
}
indexingItems() {
var _a;
const starredPathMap = keyBy(
this.appHelper.getStarredFilePaths(),
(x) => x
);
const originFilePath = (_a = this.originFile) == null ? void 0 : _a.path;
let start = performance.now();
const fileItems = this.app.vault.getFiles().filter(
(x) => x.path !== originFilePath && this.app.metadataCache.getFileCache(x)
).map((x) => {
var _a2, _b, _c, _d, _e, _f;
const cache = this.app.metadataCache.getFileCache(x);
return {
file: x,
aliases: (_a2 = (0, import_obsidian4.parseFrontMatterAliases)(cache.frontmatter)) != null ? _a2 : [],
tags: this.command.searchBy.tag ? uniq([
...((_b = cache.tags) != null ? _b : []).map((x2) => x2.tag),
...(_c = (0, import_obsidian4.parseFrontMatterTags)(cache.frontmatter)) != null ? _c : []
]) : [],
headers: this.command.searchBy.header ? ((_d = cache.headings) != null ? _d : []).map((x2) => excludeFormat(x2.heading)) : [],
links: this.command.searchBy.link ? uniq(
[
...(_e = cache.links) != null ? _e : [],
...(_f = cache.frontmatterLinks) != null ? _f : []
].map((x2) => {
var _a3;
return (_a3 = x2.displayText) != null ? _a3 : "";
})
) : [],
frontMatter: (this.command.showFrontMatter || this.command.searchBy.property) && cache.frontmatter ? omitBy(cache.frontmatter, (key, _) => key === "position") : void 0,
phantom: false,
starred: x.path in starredPathMap,
matchResults: [],
tokens: x.basename.split(" ")
};
});
this.logger.showDebugLog("Indexing file items: ", start);
this.originItems = [...fileItems, ...this.phantomItems];
start = performance.now();
this.ignoredItems = this.prefilterItems(this.command);
this.logger.showDebugLog("Prefilter items: ", start);
}
prefilterItems(command) {
const filterItems = (includePatterns, excludePatterns) => {
let items = this.originItems;
if (command.targetExtensions.length > 0) {
items = items.filter(
(x) => command.targetExtensions.includes(x.file.extension)
);
}
switch (command.searchTarget) {
case "file":
break;
case "opened file": {
const paths = this.appHelper.getFilePathsInActiveWindow();
items = items.filter((x) => paths.includes(x.file.path));
break;
}
case "backlink": {
const backlinksMap = this.appHelper.createBacklinksMap();
items = items.filter(
(x) => {
var _a, _b, _c;
return (_c = backlinksMap[(_b = (_a = this.originFile) == null ? void 0 : _a.path) != null ? _b : ""]) == null ? void 0 : _c.has(x.file.path);
}
);
break;
}
case "link": {
const originFileLinkMap = this.originFile ? this.appHelper.createLinksMap(this.originFile) : {};
items = items.filter((x) => originFileLinkMap[x.file.path]).sort(
sorter((x) => {
const c = originFileLinkMap[x.file.path];
return isFrontMatterLinkCache(c) ? -1 : c.position.start.offset;
})
);
break;
}
case "2-hop-link": {
const backlinksMap2 = this.appHelper.createBacklinksMap();
const originFileLinkMap2 = this.originFile ? this.appHelper.createLinksMap(this.originFile) : {};
const linkPaths = items.filter((x) => originFileLinkMap2[x.file.path]).map((x) => x.file.path);
const backlinkPaths = linkPaths.flatMap(
(x) => Array.from(backlinksMap2[x])
);
const filteredPaths = uniq([...linkPaths, ...backlinkPaths]);
items = items.filter((x) => filteredPaths.includes(x.file.path)).sort(
sorter((x) => {
const c = originFileLinkMap2[x.file.path];
return !c || isFrontMatterLinkCache(c) ? 65535 : c.position.start.offset;
})
);
break;
}
}
if (includePatterns.length > 0) {
items = includeItems(items, includePatterns, (x) => x.file.path);
}
if (excludePatterns.length > 0) {
items = excludeItems(items, excludePatterns, (x) => x.file.path);
}
return items;
};
return filterItems(
command.includePrefixPathPatterns.map(
(p) => p.replace(/<current_dir>/g, this.appHelper.getCurrentDirPath())
),
command.excludePrefixPathPatterns.map(
(p) => p.replace(/<current_dir>/g, this.appHelper.getCurrentDirPath())
)
);
}
getSuggestions(query) {
if (!query || query === this.command.defaultInput || !this.opened) {
return this._getSuggestions(query);
}
return new Promise((resolve) => {
this.debounceGetSuggestions(query, (items) => {
resolve(items);
});
});
}
_getSuggestions(query) {
var _a;
const start = performance.now();
const lastOpenFileIndexByPath = {};
this.app.workspace.getLastOpenFiles().forEach((v, i) => {
lastOpenFileIndexByPath[v] = i;
});
const commandByPrefix = this.settings.searchCommands.filter((x) => x.commandPrefix).find((x) => query.startsWith(x.commandPrefix));
if ((commandByPrefix || this.initialCommand !== this.command) && commandByPrefix !== this.command) {
this.command = commandByPrefix != null ? commandByPrefix : this.initialCommand;
this.indexingItems();
}
this.searchQuery = query.startsWith(this.command.commandPrefix) ? query.replace(this.command.commandPrefix, "") : query;
this.searchQuery = this.searchQuery.replace(
/<cd>/g,
this.appHelper.getCurrentDirPath()
);
if (this.command.defaultInput) {
this.searchQuery = `${this.command.defaultInput}${this.searchQuery}`;
}
this.renderInputComponent();
const qs = smartWhitespaceSplit(this.searchQuery);
if (this.command.searchTarget === "backlink" && !((_a = this.originFile) == null ? void 0 : _a.path)) {
return [];
}
const isQueryEmpty = !this.searchQuery.trim();
const matchedSuggestions = isQueryEmpty ? this.ignoredItems : this.ignoredItems.map(
(x) => stampMatchResults(x, qs, {
isNormalizeAccentsDiacritics: this.settings.normalizeAccentsAndDiacritics,
searchByHeaders: this.command.searchBy.header,
searchByLinks: this.command.searchBy.link,
searchByTags: this.command.searchBy.tag,
keysOfPropertyToSearch: this.command.searchBy.property ? this.command.keysOfPropertyToSearch : [],
fuzzyTarget: this.command.allowFuzzySearchForSearchTarget,
minFuzzyScore: this.command.minFuzzyMatchScore
})
).filter((x) => x.matchResults.every((x2) => x2.type !== "not found"));
const items = sort(
matchedSuggestions,
isQueryEmpty ? filterNoQueryPriorities(this.command.sortPriorities) : this.command.sortPriorities,
lastOpenFileIndexByPath
);
this.logger.showDebugLog(
`Get suggestions: ${this.searchQuery} (${this.command.name})`,
start
);
this.countInputEl = createDiv({
text: `${Math.min(items.length, this.limit)} / ${items.length}`,
cls: "another-quick-switcher__status__count-input"
});
this.inputEl.before(this.countInputEl);
return items.slice(0, this.limit).map((x, order) => ({ ...x, order }));
}
renderInputComponent() {
var _a, _b, _c, _d;
(_a = this.navigationHistoryEl) == null ? void 0 : _a.remove();
(_b = this.searchCommandEl) == null ? void 0 : _b.remove();
(_c = this.defaultInputEl) == null ? void 0 : _c.remove();
(_d = this.countInputEl) == null ? void 0 : _d.remove();
this.navigationHistoryEl = createDiv({
cls: "another-quick-switcher__custom-search__navigation-history-header"
});
const backHistoryLength = this.currentNavigationHistoryIndex;
if (backHistoryLength > 0) {
this.navigationHistoryEl.appendText(`${backHistoryLength} < `);
}
this.navigationHistoryEl.appendText(
this.originFile ? this.originFile.basename : "No file"
);
const forwardHistoryLength = this.navigationHistories.length - this.currentNavigationHistoryIndex - 1;
if (forwardHistoryLength > 0) {
this.navigationHistoryEl.appendText(` > ${forwardHistoryLength}`);
}
this.inputEl.before(this.navigationHistoryEl);
this.searchCommandEl = createDiv({
cls: "another-quick-switcher__status__search-command"
});
this.searchCommandEl.insertAdjacentHTML("beforeend", SEARCH);
this.searchCommandEl.createSpan({
text: this.command.name,
cls: "another-quick-switcher__status__search-command-name"
});
this.searchCommandEl.createSpan({
cls: "another-quick-switcher__status__search-command-separator"
});
if (this.command.searchBy.tag) {
this.searchCommandEl.insertAdjacentHTML("beforeend", TAG);
}
if (this.command.searchBy.header) {
this.searchCommandEl.insertAdjacentHTML("beforeend", HEADER);
}
if (this.command.searchBy.link) {
this.searchCommandEl.insertAdjacentHTML("beforeend", LINK);
}
const promptInputContainer = this.modalEl.find(".prompt-input-container");
if (promptInputContainer) {
promptInputContainer.setAttr("style", "display: initial");
}
this.inputEl.before(this.searchCommandEl);
if (this.command.defaultInput) {
this.defaultInputEl = createDiv({
text: this.searchQuery,
cls: "another-quick-switcher__status__default-input"
});
this.defaultInputEl.insertAdjacentHTML("afterbegin", FILTER);
this.resultContainerEl.before(this.defaultInputEl);
}
}
renderSuggestion(item, el) {
const { itemDiv, metaDiv, descriptionDiv } = createElements(item, {
showFrontMatter: this.command.showFrontMatter,
excludeFrontMatterKeys: this.command.excludeFrontMatterKeys,
showDirectory: this.settings.showDirectory,
showDirectoryAtNewLine: this.settings.showDirectoryAtNewLine,
showFullPathOfDirectory: this.settings.showFullPathOfDirectory,
displayAliasAsTitleOnKeywordMatched: this.settings.showAliasesOnTop,
displayAliaseAsTitle: this.settings.displayAliaseAsTitle,
hideGutterIcons: this.settings.hideGutterIcons,
showFuzzyMatchScore: this.settings.showFuzzyMatchScore
});
if (metaDiv == null ? void 0 : metaDiv.hasChildNodes()) {
itemDiv.appendChild(metaDiv);
}
if (descriptionDiv == null ? void 0 : descriptionDiv.hasChildNodes()) {
itemDiv.appendChild(descriptionDiv);
}
el.appendChild(itemDiv);
}
onNoSuggestion() {
super.onNoSuggestion();
const div = createDiv({
cls: "another-quick-switcher__command_buttons"
});
const createButton = createEl("button", {
text: "Create",
cls: "another-quick-switcher__command_button"
});
createButton.addEventListener(
"click",
() => this.handleCreateNewMarkdown(this.searchQuery, "same-tab")
);
div.appendChild(createButton);
const searchInGoogleButton = createEl("button", {
text: "Search in google",
cls: "another-quick-switcher__command_button"
});
searchInGoogleButton.addEventListener("click", () => {
activeWindow.open(`https://www.google.com/search?q=${this.searchQuery}`);
this.close();
});
div.appendChild(searchInGoogleButton);
this.resultContainerEl.appendChild(div);
}
navigate(cb) {
this.navQueue = this.navQueue.then(cb);
}
async chooseCurrentSuggestion(leafType, option = {}) {
var _a, _b, _c, _d, _e, _f;
const item = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem];
if (!item) {
return null;
}
let fileToOpened = item.file;
if (item.phantom) {
fileToOpened = await this.app.vault.create(item.file.path, "");
}
let offset;
let leafPriorToSameTab;
switch (this.command.searchTarget) {
case "file":
if (((_b = item.matchResults[0]) == null ? void 0 : _b.type) === "header") {
const firstHeader = item.matchResults[0].meta[0];
offset = (_c = this.appHelper.findFirstHeaderOffset(item.file, firstHeader)) != null ? _c : void 0;
}
break;
case "opened file":
if (((_d = item.matchResults[0]) == null ? void 0 : _d.type) === "header") {
const firstHeader = item.matchResults[0].meta[0];
offset = (_e = this.appHelper.findFirstHeaderOffset(item.file, firstHeader)) != null ? _e : void 0;
}
this.appHelper.getFilePathsInActiveWindow;
leafPriorToSameTab = this.appHelper.findLeaf(fileToOpened);
break;
case "backlink":
offset = this.appHelper.findFirstLinkOffset(
item.file,
this.originFile
);
break;
case "link":
break;
case "2-hop-link":
break;
default:
throw new ExhaustiveError(this.command.searchTarget);
}
if (!option.keepOpen) {
this.close();
this.navigate(() => this.isClosed);
} else if (leafType === "same-tab") {
(_f = this.stateToRestore) != null ? _f : this.stateToRestore = this.appHelper.captureState(this.initialLeaf);
}
this.navigate(
() => this.appHelper.openFile(
fileToOpened,
{
leafType,
offset,
inplace: option.keepOpen,
preventDuplicateTabs: this.settings.preventDuplicateTabs,
leafPriorToSameTab
},
this.stateToRestore
)
);
return fileToOpened;
}
async onChooseSuggestion() {
await this.chooseCurrentSuggestion("same-tab");
}
async handleCreateNewMarkdown(searchQuery, leafType) {
if (!searchQuery) {
return true;
}
const file = await this.appHelper.createMarkdown(this.searchQuery);
if (!file) {
new import_obsidian4.Notice("This file already exists.");
return true;
}
this.close();
this.navigate(() => this.isClosed);
this.navigate(() => this.appHelper.openFile(file, { leafType }));
return false;
}
registerKeys(key, handler) {
var _a;
for (const x of (_a = this.settings.hotkeys.main[key]) != null ? _a : []) {
this.scope.register(
x.modifiers,
normalizeKey(capitalizeFirstLetter(x.key)),
(evt) => {
if (!evt.isComposing) {
evt.preventDefault();
handler();
return false;
}
}
);
}
}
setHotkeys() {
this.scope.unregister(this.scope.keys.find((x) => x.key === "Enter"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Escape"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Home"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "End"));
const openNthMod = quickResultSelectionModifier(
this.settings.userAltInsteadOfModForQuickResultSelection
);
if (!this.settings.hideHotkeyGuides) {
this.setInstructions([
{ command: "[\u2191]", purpose: "up" },
{ command: "[\u2193]", purpose: "down" },
{ command: `[${openNthMod} 1~9]`, purpose: "open Nth" },
...createInstructions(this.settings.hotkeys.main)
]);
}
this.registerKeys("up", () => {
document.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowUp" }));
});
this.registerKeys("down", () => {
document.dispatchEvent(
new KeyboardEvent("keydown", { key: "ArrowDown" })
);
});
this.registerKeys("clear input", () => {
this.inputEl.value = "";
this.inputEl.dispatchEvent(new Event("input"));
});
this.registerKeys("replace input", () => {
if (this.chooser.values) {
this.inputEl.value = this.chooser.values[this.chooser.selectedItem].file.basename;
this.inputEl.dispatchEvent(new Event("input"));
}
});
this.registerKeys("open", async () => {
await this.chooseCurrentSuggestion("same-tab");
});
this.registerKeys("open in new tab", async () => {
await this.chooseCurrentSuggestion("new-tab");
});
this.registerKeys("open in new pane (horizontal)", async () => {
await this.chooseCurrentSuggestion("new-pane-horizontal");
});
this.registerKeys("open in new pane (vertical)", async () => {
await this.chooseCurrentSuggestion("new-pane-vertical");
});
this.registerKeys("open in new window", async () => {
await this.chooseCurrentSuggestion("new-window");
});
this.registerKeys("open in popup", async () => {
await this.chooseCurrentSuggestion("popup");
});
this.registerKeys("open in new tab in background", async () => {
await this.chooseCurrentSuggestion("new-tab-background", {
keepOpen: true
});
});
this.registerKeys("open all in new tabs", () => {
this.close();
if (this.chooser.values == null) {
return;
}
const items = this.chooser.values.slice().reverse();
for (const x of items) {
this.appHelper.openFile(x.file, {
leafType: "new-tab-background",
preventDuplicateTabs: this.settings.preventDuplicateTabs
});
}
});
this.registerKeys("preview", () => {
if (!this.floating) {
this.enableFloating();
}
this.chooseCurrentSuggestion("same-tab", {
keepOpen: true
});
});
this.registerKeys("create", async () => {
await this.handleCreateNewMarkdown(this.searchQuery, "same-tab");
});
this.registerKeys("create in new tab", async () => {
await this.handleCreateNewMarkdown(this.searchQuery, "new-tab");
});
this.registerKeys("create in new window", async () => {
await this.handleCreateNewMarkdown(this.searchQuery, "new-window");
});
this.registerKeys("create in new popup", async () => {
await this.handleCreateNewMarkdown(this.searchQuery, "popup");
});
this.registerKeys("open in default app", () => {
var _a, _b;
const file = (_b = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem]) == null ? void 0 : _b.file;
if (!file) {
return;
}
this.appHelper.openFileInDefaultApp(file);
this.close();
});
this.registerKeys("show in system explorer", () => {
var _a, _b;
const file = (_b = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem]) == null ? void 0 : _b.file;
if (!file) {
return;
}
this.appHelper.openInSystemExplorer(file);
this.close();
});
this.registerKeys("open in google", () => {
activeWindow.open(`https://www.google.com/search?q=${this.searchQuery}`);
this.close();
});
this.registerKeys("open first URL", async () => {
var _a, _b;
const fileToOpened = (_b = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem]) == null ? void 0 : _b.file;
if (!fileToOpened) {
return;
}
this.close();
await this.isClosed;
const urls = await this.appHelper.findExternalLinkUrls(fileToOpened);
if (urls.length > 0) {
activeWindow.open(urls[0]);
} else {
this.appHelper.openFile(fileToOpened, {
leafType: "same-tab"
});
}
});
this.registerKeys("insert to editor", async () => {
var _a, _b, _c, _d, _e;
const file = (_b = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem]) == null ? void 0 : _b.file;
if (!file) {
return;
}
await this.safeClose();
if (this.appHelper.isActiveLeafCanvas()) {
this.appHelper.addFileToCanvas(file);
} else {
this.appHelper.insertLinkToActiveFileBy(
file,
(_e = (_d = (_c = this.chooser.values) == null ? void 0 : _c[this.chooser.selectedItem]) == null ? void 0 : _d.phantom) != null ? _e : false
);
}
});
this.registerKeys("insert to editor in background", async () => {
var _a, _b, _c, _d, _e;
const file = (_b = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem]) == null ? void 0 : _b.file;
if (!file) {
return;
}
this.historyRestoreStatus = "doing";
if (this.stateToRestore) {
await this.stateToRestore.restore();
this.stateToRestore = void 0;
}
if (this.appHelper.isActiveLeafCanvas()) {
this.appHelper.addFileToCanvas(file);
} else {
this.appHelper.insertLinkToActiveFileBy(
file,
(_e = (_d = (_c = this.chooser.values) == null ? void 0 : _c[this.chooser.selectedItem]) == null ? void 0 : _d.phantom) != null ? _e : false
);
this.appHelper.insertStringToActiveFile("\n");
}
});
this.registerKeys("insert all to editor", async () => {
var _a;
await this.safeClose();
let offsetX = 0;
for (const x of (_a = this.chooser.values) != null ? _a : []) {
if (this.appHelper.isActiveLeafCanvas()) {
const cv = this.appHelper.addFileToCanvas(x.file, {
x: offsetX,
y: 0
});
offsetX += cv.width + 30;
} else {
this.appHelper.insertLinkToActiveFileBy(x.file, x.phantom);
this.appHelper.insertStringToActiveFile("\n");
}
}
});
const navigateLinks = (command) => {
var _a, _b;
const file = (_b = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem]) == null ? void 0 : _b.file;
if (!file) {
return;
}
this.silentClose();
const modal = new _AnotherQuickSwitcherModal({
app: this.app,
settings: this.settings,
command: {
...command,
floating: this.floating
},
originFile: file,
inputQuery: "",
navigationHistories: [
...this.navigationHistories.slice(
0,
this.currentNavigationHistoryIndex
),
{
inputQuery: this.inputEl.value,
command: { ...this.command },
originFile: this.originFile
}
],
currentNavigationHistoryIndex: this.currentNavigationHistoryIndex + 1,
stackHistory: true,
initialLeaf: this.initialLeaf,
initialState: this.stateToRestore,
navQueue: this.navQueue
});
modal.open();
};
this.registerKeys("show links", () => {
navigateLinks(createDefaultLinkSearchCommand());
});
this.registerKeys("show backlinks", () => {
navigateLinks(createDefaultBacklinkSearchCommand());
});
this.registerKeys("show all results", () => {
this.limit = Number.MAX_SAFE_INTEGER;
this.inputEl.dispatchEvent(new Event("input"));
});
const navigate = (index) => {
const history = this.navigationHistories[index];
if (!history) {
return;
}
this.silentClose();
const modal = new _AnotherQuickSwitcherModal({
app: this.app,
settings: this.settings,
command: {
...history.command,
floating: this.floating
},
originFile: history.originFile,
inputQuery: history.inputQuery,
navigationHistories: this.navigationHistories,
currentNavigationHistoryIndex: index,
stackHistory: false,
initialState: this.stateToRestore,
initialLeaf: this.initialLeaf,
navQueue: this.navQueue
});
modal.open();
};
this.registerKeys("navigate back", () => {
navigate(this.currentNavigationHistoryIndex - 1);
});
this.registerKeys("navigate forward", () => {
navigate(this.currentNavigationHistoryIndex + 1);
});
const modifierKey = this.settings.userAltInsteadOfModForQuickResultSelection ? "Alt" : "Mod";
for (const n of [1, 2, 3, 4, 5, 6, 7, 8, 9]) {
this.scope.register([modifierKey], String(n), (evt) => {
this.chooser.setSelectedItem(n - 1, evt);
this.chooseCurrentSuggestion("same-tab");
return false;
});
}
this.registerKeys("dismiss", async () => {
this.close();
});
}
};
// src/ui/BacklinkModal.ts
var import_obsidian5 = require("obsidian");
var BacklinkModal = class extends import_obsidian5.SuggestModal {
constructor(app, settings, initialLeaf) {
super(app);
this.lastOpenFileIndexByPath = {};
this.suggestions = [];
this.isClosed = new Promise((resolve) => {
this.markClosed = resolve;
});
this.navQueue = Promise.resolve();
this.modalEl.addClass("another-quick-switcher__modal-prompt");
this.vaultRootPath = normalizePath(
this.app.vault.adapter.basePath
);
this.appHelper = new AppHelper(app);
this.settings = settings;
this.logger = Logger.of(this.settings);
this.initialLeaf = initialLeaf;
this.originFileBaseName = this.appHelper.getActiveFile().basename;
this.originFileBaseNameRegExp = new RegExp(this.originFileBaseName, "g");
this.limit = 255;
this.app.workspace.getLastOpenFiles().forEach((v, i) => {
this.lastOpenFileIndexByPath[v] = i;
});
this.setHotkeys();
this.debounceGetSuggestions = (0, import_obsidian5.debounce)(
(query, cb) => {
cb(this._getSuggestions(query));
},
this.settings.searchDelayMilliSeconds,
true
);
}
async init() {
await this.indexingItems();
}
onOpen() {
super.onOpen();
if (!import_obsidian5.Platform.isPhone) {
setFloatingModal(this.appHelper);
}
this.opened = true;
}
close() {
if (import_obsidian5.Platform.isMobile) {
this.onClose();
}
super.close();
}
onClose() {
super.onClose();
if (this.stateToRestore) {
this.navigate(() => this.stateToRestore.restore());
}
this.navigate(this.markClosed);
}
async indexingItems() {
const start = performance.now();
const ignoredItems = [];
const backlinks = this.appHelper.getBacklinksByFilePathInActiveFile();
if (!backlinks) {
return;
}
for (const [path, caches] of Object.entries(backlinks)) {
const file = this.appHelper.getFileByPath(path);
if (this.settings.backlinkExcludePrefixPathPatterns.some(
(p) => file.path.startsWith(p)
)) {
continue;
}
const content = await this.app.vault.cachedRead(file);
for (const cache of caches) {
ignoredItems.push(
isFrontMatterLinkCache(cache) ? {
file,
line: `<${cache.key}: in properties>`,
lineNumber: 1,
offset: 0
} : {
file,
line: content.split("\n").at(cache.position.start.line),
lineNumber: cache.position.start.line + 1,
offset: cache.position.start.offset
}
);
}
}
this.ignoredItems = uniqBy(
ignoredItems,
(item) => `${item.file.path}/${item.lineNumber}`
);
this.logger.showDebugLog("Indexing backlinks", start);
}
getSuggestions(query) {
if (!query || !this.opened) {
return this._getSuggestions(query);
}
return new Promise((resolve) => {
this.debounceGetSuggestions(query, (items) => {
resolve(items);
});
});
}
_getSuggestions(query) {
var _a;
const start = performance.now();
const isQueryEmpty = query.trim() === "";
const queries = query.trim().split(" ");
const matchedSuggestions = isQueryEmpty ? this.ignoredItems : this.ignoredItems.filter(
(x) => queries.every(
(q) => smartIncludes(
x.file.path,
q,
this.settings.normalizeAccentsAndDiacritics
) || smartIncludes(
x.line,
q,
this.settings.normalizeAccentsAndDiacritics
)
)
);
this.logger.showDebugLog(`Get suggestions: ${query}`, start);
(_a = this.countInputEl) == null ? void 0 : _a.remove();
this.countInputEl = createDiv({
text: `${Math.min(matchedSuggestions.length, this.limit)} / ${matchedSuggestions.length}`,
cls: "another-quick-switcher__backlink__status__count-input"
});
this.inputEl.before(this.countInputEl);
this.suggestions = matchedSuggestions.sort(
(a, b) => compare(
a,
b,
(x) => {
var _a2;
return (_a2 = this.lastOpenFileIndexByPath[x.file.path]) != null ? _a2 : 999999;
},
"asc"
)
).slice(0, this.limit).map((x, order) => ({ ...x, order }));
return this.suggestions;
}
renderSuggestion(item, el) {
var _a, _b, _c;
const previousPath = (_a = this.suggestions[item.order - 1]) == null ? void 0 : _a.file.path;
const sameFileWithPrevious = previousPath === item.file.path;
const itemDiv = createDiv({
cls: "another-quick-switcher__item"
});
const entryDiv = createDiv({
cls: "another-quick-switcher__item__entry"
});
if (!sameFileWithPrevious) {
const titleDiv = createDiv({
cls: [
"another-quick-switcher__item__title",
"another-quick-switcher__backlink__item__title_entry"
],
text: item.file.basename,
attr: {
extension: item.file.extension
}
});
const isExcalidrawFile = isExcalidraw(item.file);
if (item.file.extension !== "md" || isExcalidrawFile) {
const extDiv = createDiv({
cls: "another-quick-switcher__item__extension",
text: isExcalidrawFile ? "excalidraw" : item.file.extension
});
titleDiv.appendChild(extDiv);
}
entryDiv.appendChild(titleDiv);
itemDiv.appendChild(entryDiv);
if (this.settings.showDirectory) {
const directoryDiv = createDiv({
cls: "another-quick-switcher__item__directory"
});
directoryDiv.insertAdjacentHTML("beforeend", FOLDER);
const text = this.settings.showFullPathOfDirectory ? (_b = item.file.parent) == null ? void 0 : _b.path : (_c = item.file.parent) == null ? void 0 : _c.name;
directoryDiv.appendText(` ${text}`);
entryDiv.appendChild(directoryDiv);
if (this.settings.showDirectoryAtNewLine) {
itemDiv.appendChild(directoryDiv);
}
}
}
const descriptionsDiv = createDiv({
cls: "another-quick-switcher__item__descriptions"
});
const descriptionDiv = createDiv({
cls: "another-quick-switcher__backlink__item__description"
});
let restLine = item.line;
let offset = 0;
const indices = Array.from(
restLine.matchAll(this.originFileBaseNameRegExp)
).map((x) => x.index);
for (const index of indices) {
const before = restLine.slice(0, index - offset);
descriptionDiv.createSpan({
text: trimLineByEllipsis(
before,
this.settings.maxDisplayLengthAroundMatchedWord
)
});
descriptionDiv.createSpan({
text: this.originFileBaseName,
cls: "another-quick-switcher__hit_word"
});
offset = index - offset + this.originFileBaseName.length;
restLine = restLine.slice(offset);
}
descriptionDiv.createSpan({
text: trimLineByEllipsis(
restLine,
this.settings.maxDisplayLengthAroundMatchedWord
)
});
if (item.order < 9) {
const hotKeyGuide = createSpan({
cls: "another-quick-switcher__backlink__item__hot-key-guide",
text: `${item.order + 1}`
});
descriptionsDiv.appendChild(hotKeyGuide);
}
descriptionsDiv.appendChild(descriptionDiv);
itemDiv.appendChild(descriptionsDiv);
el.appendChild(itemDiv);
}
navigate(cb) {
this.navQueue = this.navQueue.then(cb);
}
async chooseCurrentSuggestion(leaf, option = {}) {
var _a, _b;
const item = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem];
if (!item) {
return null;
}
if (!option.keepOpen) {
this.close();
this.navigate(() => this.isClosed);
} else if (leaf === "same-tab") {
(_b = this.stateToRestore) != null ? _b : this.stateToRestore = this.appHelper.captureState(this.initialLeaf);
}
this.navigate(
() => this.appHelper.openFile(
item.file,
{
leafType: leaf,
line: item.lineNumber - 1,
inplace: option.keepOpen,
preventDuplicateTabs: this.settings.preventDuplicateTabs
},
this.stateToRestore
)
);
return item.file;
}
async onChooseSuggestion() {
await this.chooseCurrentSuggestion("same-tab");
}
registerKeys(key, handler) {
const hotkeys = this.settings.hotkeys.backlink[key];
for (const x of hotkeys) {
this.scope.register(
x.modifiers,
normalizeKey(capitalizeFirstLetter(x.key)),
(evt) => {
if (!evt.isComposing) {
evt.preventDefault();
handler();
return false;
}
}
);
}
}
setHotkeys() {
this.scope.unregister(this.scope.keys.find((x) => x.key === "Enter"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Escape"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Home"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "End"));
const openNthMod = quickResultSelectionModifier(
this.settings.userAltInsteadOfModForQuickResultSelection
);
if (!this.settings.hideHotkeyGuides) {
this.setInstructions([
{ command: "[\u21B5]", purpose: "open" },
{ command: "[\u2191]", purpose: "up" },
{ command: "[\u2193]", purpose: "down" },
{ command: `[${openNthMod} 1~9]`, purpose: "open Nth" },
...createInstructions(this.settings.hotkeys.backlink)
]);
}
this.registerKeys("up", () => {
document.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowUp" }));
});
this.registerKeys("down", () => {
document.dispatchEvent(
new KeyboardEvent("keydown", { key: "ArrowDown" })
);
});
this.registerKeys("open", async () => {
await this.chooseCurrentSuggestion("same-tab");
});
this.registerKeys("open in new tab", async () => {
await this.chooseCurrentSuggestion("new-tab");
});
this.registerKeys("open in new pane (horizontal)", async () => {
await this.chooseCurrentSuggestion("new-pane-horizontal");
});
this.registerKeys("open in new pane (vertical)", async () => {
await this.chooseCurrentSuggestion("new-pane-vertical");
});
this.registerKeys("open in new window", async () => {
await this.chooseCurrentSuggestion("new-window");
});
this.registerKeys("open in popup", async () => {
await this.chooseCurrentSuggestion("popup");
});
this.registerKeys("open in new tab in background", async () => {
await this.chooseCurrentSuggestion("new-tab-background", {
keepOpen: true
});
});
this.registerKeys("open all in new tabs", () => {
this.close();
if (this.chooser.values == null) {
return;
}
const items = this.chooser.values.slice().reverse();
for (const x of items) {
this.appHelper.openFile(x.file, {
leafType: "new-tab-background",
preventDuplicateTabs: this.settings.preventDuplicateTabs
});
}
});
this.registerKeys("show all results", () => {
this.limit = Number.MAX_SAFE_INTEGER;
this.inputEl.dispatchEvent(new Event("input"));
});
this.registerKeys("preview", async () => {
await this.chooseCurrentSuggestion("same-tab", {
keepOpen: true
});
});
const modifierKey = this.settings.userAltInsteadOfModForQuickResultSelection ? "Alt" : "Mod";
for (const n of [1, 2, 3, 4, 5, 6, 7, 8, 9]) {
this.scope.register([modifierKey], String(n), (evt) => {
this.chooser.setSelectedItem(n - 1, evt);
this.chooser.useSelectedItem({});
return false;
});
}
this.registerKeys("dismiss", async () => {
this.close();
});
}
};
// src/ui/FolderModal.ts
var import_obsidian6 = require("obsidian");
function matchQuery2(item, query, matcher, isNormalizeAccentsDiacritics) {
const qs = query.split("/");
const folder = qs.pop();
return qs.every(
(dir) => {
var _a;
return smartIncludes(
(_a = item.folder.parent) == null ? void 0 : _a.path,
dir,
isNormalizeAccentsDiacritics
);
}
) && matcher(item, folder);
}
function matchQueryAll2(item, queries, matcher, isNormalizeAccentsDiacritics) {
return queries.every(
(q) => matchQuery2(item, q, matcher, isNormalizeAccentsDiacritics)
);
}
function stampMatchType(item, queries, isNormalizeAccentsDiacritics) {
if (matchQueryAll2(
item,
queries,
(item2, query) => smartStartsWith(item2.folder.name, query, isNormalizeAccentsDiacritics),
isNormalizeAccentsDiacritics
)) {
return { ...item, matchType: "prefix-name" };
}
if (matchQueryAll2(
item,
queries,
(item2, query) => smartIncludes(item2.folder.name, query, isNormalizeAccentsDiacritics),
isNormalizeAccentsDiacritics
)) {
return { ...item, matchType: "name" };
}
if (matchQueryAll2(
item,
queries,
(item2, query) => smartIncludes(item2.folder.path, query, isNormalizeAccentsDiacritics),
isNormalizeAccentsDiacritics
)) {
return { ...item, matchType: "directory" };
}
return item;
}
var FolderModal = class extends import_obsidian6.SuggestModal {
constructor(app, settings) {
super(app);
this.modalEl.addClass("another-quick-switcher__modal-prompt");
this.appHelper = new AppHelper(app);
this.settings = settings;
this.setHotkeys();
this.originItems = this.appHelper.getFolders().filter((x) => !x.isRoot()).map((x) => ({
folder: x
}));
this.filteredItems = this.originItems;
}
getSuggestions(query) {
const qs = query.split(" ").filter((x) => x);
return this.filteredItems.map(
(x) => stampMatchType(x, qs, this.settings.normalizeAccentsAndDiacritics)
).filter((x) => x.matchType).sort(sorter((x) => x.matchType === "directory" ? 1 : 0)).sort(
sorter(
(x) => x.matchType === "prefix-name" ? 1e3 - x.folder.name.length : 0,
"desc"
)
).slice(0, 10);
}
renderSuggestion(item, el) {
var _a;
const itemDiv = createDiv({
cls: [
"another-quick-switcher__item",
"another-quick-switcher__directory_item"
]
});
const entryDiv = createDiv({
cls: "another-quick-switcher__item__entry"
});
const folderDiv = createDiv({
cls: "another-quick-switcher__item__title",
text: item.folder.name
});
entryDiv.appendChild(folderDiv);
const directoryDiv = createDiv({
cls: "another-quick-switcher__item__directory"
});
directoryDiv.insertAdjacentHTML("beforeend", FOLDER);
directoryDiv.appendText(` ${(_a = item.folder.parent) == null ? void 0 : _a.name}`);
entryDiv.appendChild(directoryDiv);
itemDiv.appendChild(entryDiv);
el.appendChild(itemDiv);
}
async onChooseSuggestion(item) {
if (!this.appHelper.enableFileExplorer()) {
new import_obsidian6.Notice("File explorer (core plugin) is not enabled.");
return;
}
this.appHelper.revealInFolder(item.folder);
}
registerKeys(key, handler) {
var _a;
for (const x of (_a = this.settings.hotkeys.folder[key]) != null ? _a : []) {
this.scope.register(x.modifiers, x.key.toUpperCase(), (evt) => {
evt.preventDefault();
handler();
return false;
});
}
}
setHotkeys() {
this.scope.unregister(this.scope.keys.find((x) => x.key === "Escape"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Home"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "End"));
if (!this.settings.hideHotkeyGuides) {
this.setInstructions([
{ command: "[\u21B5]", purpose: "reveal in file tree" },
{ command: "[\u2191]", purpose: "up" },
{ command: "[\u2193]", purpose: "down" },
...createInstructions(this.settings.hotkeys.folder)
]);
}
this.registerKeys("up", () => {
document.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowUp" }));
});
this.registerKeys("down", () => {
document.dispatchEvent(
new KeyboardEvent("keydown", { key: "ArrowDown" })
);
});
this.registerKeys("open in default app", () => {
var _a, _b;
const folder = (_b = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem]) == null ? void 0 : _b.folder;
if (!folder) {
return;
}
this.appHelper.openFolderInDefaultApp(folder);
this.close();
});
this.registerKeys("dismiss", async () => {
this.close();
});
}
};
// src/ui/GrepModal.ts
var import_obsidian7 = require("obsidian");
// src/utils/ripgrep.ts
var import_child_process = require("child_process");
async function existsRg(cmd) {
return new Promise((resolve, _) => {
(0, import_child_process.execFile)(cmd, ["--version"], (error, _stdout, _stderr) => {
if (error) {
console.dir(error);
}
resolve(!error);
});
});
}
async function rg(cmd, ...args) {
return new Promise((resolve, _) => {
(0, import_child_process.execFile)(
cmd,
["--json", ...args],
{ maxBuffer: 100 * 1024 * 1024 },
(_2, stdout, _stderr) => {
const results = stdout.split("\n").filter((x) => x).map((x) => JSON.parse(x)).filter((x) => x.type === "match");
resolve(results);
}
);
});
}
// src/ui/GrepModal.ts
var globalInternalStorage2 = {
items: [],
basePath: void 0,
selected: void 0
};
var GrepModal = class extends import_obsidian7.SuggestModal {
constructor(app, settings, initialLeaf) {
super(app);
this.isClosed = new Promise((resolve) => {
this.markClosed = resolve;
});
this.navQueue = Promise.resolve();
this.modalEl.addClass("another-quick-switcher__modal-prompt");
this.suggestions = globalInternalStorage2.items;
this.vaultRootPath = normalizePath(
this.app.vault.adapter.basePath
);
this.appHelper = new AppHelper(app);
this.settings = settings;
this.logger = Logger.of(this.settings);
this.initialLeaf = initialLeaf;
this.limit = 255;
const searchCmd = this.settings.hotkeys.grep.search.at(0);
if (searchCmd) {
const inst = createInstruction("_", {
key: searchCmd.key,
modifiers: searchCmd.modifiers
});
this.setPlaceholder(`Search around the vault by ${inst == null ? void 0 : inst.command} key`);
} else {
this.setPlaceholder(
`Please set a key about "search" in the "Grep dialog" setting`
);
}
this.setHotkeys();
}
onOpen() {
var _a;
super.onOpen();
setFloatingModal(this.appHelper);
this.basePath = (_a = globalInternalStorage2.basePath) != null ? _a : "";
window.setTimeout(() => {
var _a2;
const selected = globalInternalStorage2.selected;
if (selected != null) {
this.chooser.setSelectedItem(selected);
(_a2 = this.chooser.suggestions.at(selected)) == null ? void 0 : _a2.scrollIntoView({
behavior: "auto",
block: "center",
inline: "center"
});
}
this.basePathInputEl = createEl("input", {
value: this.basePath,
placeholder: "path from vault root (./ means current directory. ../ means parent directory)",
cls: "another-quick-switcher__grep__path-input",
type: "text"
});
this.basePathInputEl.setAttrs({
autocomplete: "on",
list: "directories"
});
const basePathInputList = createEl("datalist");
basePathInputList.setAttrs({ id: "directories" });
const folders = this.appHelper.getFolders().filter((x) => !x.isRoot());
for (const x of folders) {
basePathInputList.appendChild(createEl("option", { value: x.path }));
}
this.basePathInputElChangeEventListener = (evt) => {
this.basePath = evt.target.value;
};
this.basePathInputElKeydownEventListener = (evt) => {
if (!evt.key) {
evt.preventDefault();
return;
}
const hotkey = this.settings.hotkeys.grep.search[0];
if (!hotkey) {
return;
}
const keyEvent = evt;
if (equalsAsHotkey(hotkey, keyEvent)) {
evt.preventDefault();
this.basePath = evt.target.value;
this.currentQuery = this.clonedInputEl.value;
this.inputEl.value = this.currentQuery;
this.inputEl.dispatchEvent(new Event("input"));
}
};
this.basePathInputEl.addEventListener(
"change",
this.basePathInputElChangeEventListener
);
this.basePathInputEl.addEventListener(
"keydown",
this.basePathInputElKeydownEventListener
);
const wrapper = createDiv({
cls: "another-quick-switcher__grep__path-input__wrapper"
});
wrapper.appendChild(this.basePathInputEl);
wrapper.appendChild(basePathInputList);
const promptInputContainerEl = activeWindow.activeDocument.querySelector(
".prompt-input-container"
);
promptInputContainerEl == null ? void 0 : promptInputContainerEl.after(wrapper);
wrapper.insertAdjacentHTML("afterbegin", FOLDER);
}, 0);
}
onClose() {
super.onClose();
globalInternalStorage2.items = this.suggestions;
globalInternalStorage2.basePath = this.basePath;
globalInternalStorage2.selected = this.chooser.selectedItem;
this.clonedInputEl.removeEventListener(
"keydown",
this.clonedInputElKeydownEventListener
);
this.basePathInputEl.removeEventListener(
"change",
this.basePathInputElChangeEventListener
);
this.basePathInputEl.removeEventListener(
"keydown",
this.basePathInputElKeydownEventListener
);
if (this.stateToRestore) {
this.navigate(() => this.stateToRestore.restore());
}
this.navigate(this.markClosed);
}
async searchSuggestions(query) {
var _a;
const start = performance.now();
(_a = this.countInputEl) == null ? void 0 : _a.remove();
this.countInputEl = createDiv({
text: "searching...",
cls: "another-quick-switcher__grep__count-input"
});
this.clonedInputEl.before(this.countInputEl);
const absolutePathFromRoot = normalizeRelativePath(
this.basePath,
this.appHelper.getCurrentDirPath()
);
const rgResults = await rg(
this.settings.ripgrepCommand,
...[
...this.settings.grepExtensions.flatMap((x) => ["-t", x]),
hasCapitalLetter(query) ? "" : "-i",
"--",
query,
`${this.vaultRootPath}/${absolutePathFromRoot}`
].filter((x) => x)
);
const items = rgResults.map((x) => {
return {
order: -1,
file: this.appHelper.getFileByPath(
normalizePath(x.data.path.text).replace(
`${this.vaultRootPath}/`,
""
)
),
line: x.data.lines.text,
lineNumber: x.data.line_number,
offset: x.data.absolute_offset,
submatches: x.data.submatches
};
}).filter((x) => x.file != null).sort(sorter((x) => x.file.stat.mtime, "desc")).map((x, order) => ({ ...x, order }));
this.logger.showDebugLog("getSuggestions: ", start);
return items;
}
async getSuggestions(query) {
var _a;
if (query) {
this.suggestions = await this.searchSuggestions(query);
(_a = this.countInputEl) == null ? void 0 : _a.remove();
this.countInputEl = createDiv({
text: `${Math.min(this.suggestions.length, this.limit)} / ${this.suggestions.length}`,
cls: "another-quick-switcher__grep__count-input"
});
this.clonedInputEl.before(this.countInputEl);
}
return this.suggestions;
}
renderSuggestion(item, el) {
var _a, _b, _c;
const previousPath = (_a = this.suggestions[item.order - 1]) == null ? void 0 : _a.file.path;
const sameFileWithPrevious = previousPath === item.file.path;
const itemDiv = createDiv({
cls: "another-quick-switcher__item"
});
const entryDiv = createDiv({
cls: "another-quick-switcher__item__entry"
});
if (!sameFileWithPrevious) {
const titleDiv = createDiv({
cls: [
"another-quick-switcher__item__title",
"another-quick-switcher__grep__item__title_entry"
],
text: item.file.basename,
attr: {
extension: item.file.extension
}
});
const isExcalidrawFile = isExcalidraw(item.file);
if (item.file.extension !== "md" || isExcalidrawFile) {
const extDiv = createDiv({
cls: "another-quick-switcher__item__extension",
text: isExcalidrawFile ? "excalidraw" : item.file.extension
});
titleDiv.appendChild(extDiv);
}
entryDiv.appendChild(titleDiv);
itemDiv.appendChild(entryDiv);
if (this.settings.showDirectory) {
const directoryDiv = createDiv({
cls: "another-quick-switcher__item__directory"
});
directoryDiv.insertAdjacentHTML("beforeend", FOLDER);
const text = this.settings.showFullPathOfDirectory ? (_b = item.file.parent) == null ? void 0 : _b.path : (_c = item.file.parent) == null ? void 0 : _c.name;
directoryDiv.appendText(` ${text}`);
entryDiv.appendChild(directoryDiv);
if (this.settings.showDirectoryAtNewLine) {
itemDiv.appendChild(directoryDiv);
}
}
}
const descriptionsDiv = createDiv({
cls: "another-quick-switcher__item__descriptions"
});
const descriptionDiv = createDiv({
cls: "another-quick-switcher__grep__item__description"
});
let restLine = item.line;
for (const x of item.submatches) {
const i = restLine.indexOf(x.match.text);
const before = restLine.slice(0, i);
descriptionDiv.createSpan({
text: trimLineByEllipsis(
before,
this.settings.maxDisplayLengthAroundMatchedWord
)
});
descriptionDiv.createSpan({
text: x.match.text,
cls: "another-quick-switcher__hit_word"
});
restLine = restLine.slice(i + x.match.text.length);
}
descriptionDiv.createSpan({
text: trimLineByEllipsis(
restLine,
this.settings.maxDisplayLengthAroundMatchedWord
)
});
if (item.order < 9) {
const hotKeyGuide = createSpan({
cls: "another-quick-switcher__grep__item__hot-key-guide",
text: `${item.order + 1}`
});
descriptionsDiv.appendChild(hotKeyGuide);
}
descriptionsDiv.appendChild(descriptionDiv);
itemDiv.appendChild(descriptionsDiv);
el.appendChild(itemDiv);
}
navigate(cb) {
this.navQueue = this.navQueue.then(cb);
}
async chooseCurrentSuggestion(leaf, option = {}) {
var _a, _b;
const item = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem];
if (!item) {
return null;
}
if (!option.keepOpen) {
this.close();
this.navigate(() => this.isClosed);
} else if (leaf === "same-tab") {
(_b = this.stateToRestore) != null ? _b : this.stateToRestore = this.appHelper.captureState(this.initialLeaf);
}
this.navigate(
() => this.appHelper.openFile(
item.file,
{
leafType: leaf,
line: item.lineNumber - 1,
inplace: option.keepOpen,
preventDuplicateTabs: this.settings.preventDuplicateTabs
},
this.stateToRestore
)
);
return item.file;
}
async onChooseSuggestion() {
await this.chooseCurrentSuggestion("same-tab");
}
registerKeys(key, handler) {
const hotkeys = this.settings.hotkeys.grep[key];
for (const x of hotkeys) {
this.scope.register(
x.modifiers,
normalizeKey(capitalizeFirstLetter(x.key)),
(evt) => {
if (!evt.isComposing) {
evt.preventDefault();
handler();
return false;
}
}
);
}
}
setHotkeys() {
var _a;
this.scope.unregister(this.scope.keys.find((x) => x.key === "Enter"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Escape"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Home"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "End"));
const openNthMod = quickResultSelectionModifier(
this.settings.userAltInsteadOfModForQuickResultSelection
);
if (!this.settings.hideHotkeyGuides) {
this.setInstructions([
{ command: "[\u21B5]", purpose: "open" },
{ command: "[\u2191]", purpose: "up" },
{ command: "[\u2193]", purpose: "down" },
{ command: `[${openNthMod} 1~9]`, purpose: "open Nth" },
...createInstructions(this.settings.hotkeys.grep)
]);
}
this.clonedInputEl = this.inputEl.cloneNode(true);
(_a = this.inputEl.parentNode) == null ? void 0 : _a.replaceChild(this.clonedInputEl, this.inputEl);
this.clonedInputElKeydownEventListener = (evt) => {
const keyEvent = evt;
const hotkey = this.settings.hotkeys.grep.search[0];
if (!hotkey) {
return;
}
if (equalsAsHotkey(hotkey, keyEvent)) {
evt.preventDefault();
this.currentQuery = this.clonedInputEl.value;
this.inputEl.value = this.currentQuery;
this.inputEl.dispatchEvent(new Event("input"));
}
};
this.clonedInputEl.addEventListener(
"keydown",
this.clonedInputElKeydownEventListener
);
this.registerKeys("up", () => {
document.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowUp" }));
});
this.registerKeys("down", () => {
document.dispatchEvent(
new KeyboardEvent("keydown", { key: "ArrowDown" })
);
});
this.registerKeys("clear input", () => {
this.clonedInputEl.value = "";
this.clonedInputEl.dispatchEvent(new InputEvent("input"));
this.clonedInputEl.focus();
});
this.registerKeys("clear path", () => {
this.basePathInputEl.value = "";
this.basePathInputEl.dispatchEvent(new InputEvent("change"));
});
this.registerKeys("set ./ to path", () => {
this.basePathInputEl.value = "./";
this.basePathInputEl.dispatchEvent(new InputEvent("change"));
});
this.registerKeys("open", async () => {
await this.chooseCurrentSuggestion("same-tab");
});
this.registerKeys("open in new tab", async () => {
await this.chooseCurrentSuggestion("new-tab");
});
this.registerKeys("open in new pane (horizontal)", async () => {
await this.chooseCurrentSuggestion("new-pane-horizontal");
});
this.registerKeys("open in new pane (vertical)", async () => {
await this.chooseCurrentSuggestion("new-pane-vertical");
});
this.registerKeys("open in new window", async () => {
await this.chooseCurrentSuggestion("new-window");
});
this.registerKeys("open in popup", async () => {
await this.chooseCurrentSuggestion("popup");
});
this.registerKeys("open in new tab in background", async () => {
await this.chooseCurrentSuggestion("new-tab-background", {
keepOpen: true
});
});
this.registerKeys("open all in new tabs", () => {
this.close();
if (this.chooser.values == null) {
return;
}
const items = this.chooser.values.slice().reverse();
for (const x of items) {
this.appHelper.openFile(x.file, {
leafType: "new-tab-background",
preventDuplicateTabs: this.settings.preventDuplicateTabs
});
}
});
this.registerKeys("preview", async () => {
await this.chooseCurrentSuggestion("same-tab", {
keepOpen: true
});
});
const modifierKey = this.settings.userAltInsteadOfModForQuickResultSelection ? "Alt" : "Mod";
for (const n of [1, 2, 3, 4, 5, 6, 7, 8, 9]) {
this.scope.register([modifierKey], String(n), (evt) => {
this.chooser.setSelectedItem(n - 1, evt);
this.chooser.useSelectedItem({});
return false;
});
}
this.registerKeys("dismiss", async () => {
this.close();
});
}
};
// src/ui/HeaderModal.ts
var import_obsidian8 = require("obsidian");
var HeaderModal = class extends import_obsidian8.SuggestModal {
constructor(app, settings, floating) {
super(app);
this.hitItems = [];
/** !Not work correctly in all cases */
this.unsafeSelectedIndex = 0;
this.modalEl.addClass("another-quick-switcher__modal-prompt");
this.limit = 1e3;
this.appHelper = new AppHelper(app);
this.settings = settings;
this.floating = floating;
this.autoPreview = settings.autoPreviewInFloatingHeaderSearch && floating;
this.items = this.appHelper.getHeadersInActiveFile().map((x, i) => ({
value: excludeFormat(x.heading),
level: x.level,
position: x.position,
hit: false,
index: i
}));
this.inputEl.addEventListener("input", (evt) => {
var _a, _b;
const unsafeEvt = evt;
if (this.hitItems.length === 0) {
this.select(this.unsafeSelectedIndex, unsafeEvt);
return;
}
const nextIndex = (_b = (_a = this.hitItems.find((x) => x.index >= this.unsafeSelectedIndex)) == null ? void 0 : _a.index) != null ? _b : this.hitItems[0].index;
this.select(nextIndex, unsafeEvt);
});
this.setHotkeys();
}
select(index, evt, suppressAutoPreview) {
var _a;
this.chooser.setSelectedItem(index, evt);
(_a = this.chooser.suggestions.at(index)) == null ? void 0 : _a.scrollIntoView({
behavior: "auto",
block: "center",
inline: "center"
});
this.unsafeSelectedIndex = index;
const item = this.items.at(this.unsafeSelectedIndex);
if (this.autoPreview && item && !suppressAutoPreview) {
this.appHelper.moveTo(item.position);
}
}
getNextSelectIndex() {
return this.unsafeSelectedIndex + 1 > this.items.length - 1 ? 0 : this.unsafeSelectedIndex + 1;
}
getPreviousSelectIndex() {
return this.unsafeSelectedIndex - 1 < 0 ? this.items.length - 1 : this.unsafeSelectedIndex - 1;
}
onOpen() {
super.onOpen();
if (this.floating) {
this.enableFloating();
this.refreshPreviewIcon();
}
const markdownView = this.appHelper.getMarkdownViewInActiveLeaf();
if (!markdownView || this.items.length === 0) {
return;
}
const mode = markdownView.getMode();
const offset = mode === "source" ? this.appHelper.getCurrentOffset() : markdownView.editor.posToOffset({
ch: 0,
line: markdownView.previewMode.getScroll()
});
if (!offset) {
return;
}
const firstOverIndex = this.items.findIndex(
(x) => x.position.start.offset > offset
);
if (firstOverIndex === -1) {
this.select(this.items.last().index, void 0, true);
} else if (firstOverIndex === 0) {
this.select(0, void 0, true);
} else {
this.select(firstOverIndex - 1, void 0, true);
}
}
refreshPreviewIcon() {
var _a, _b;
(_a = this.previewIcon) == null ? void 0 : _a.remove();
if (this.autoPreview) {
this.previewIcon = this.inputEl.insertAdjacentElement(
"afterend",
createDiv({ cls: "another-quick-switcher__header__auto-preview-icon" })
);
(_b = this.previewIcon) == null ? void 0 : _b.insertAdjacentHTML("beforeend", PREVIEW);
}
}
enableFloating() {
this.floating = true;
if (!import_obsidian8.Platform.isPhone) {
setFloatingModal(this.appHelper);
}
}
getSuggestions(query) {
const qs = smartWhitespaceSplit(query);
const suggestions = this.items.map((x) => {
const hit = qs.length > 0 && qs.every(
(q) => smartIncludes(
x.value,
q,
this.settings.normalizeAccentsAndDiacritics
)
);
return { ...x, hit };
});
this.hitItems = suggestions.filter((x) => x.hit);
return suggestions;
}
renderSuggestion(item, el) {
const itemDiv = createDiv({
cls: "another-quick-switcher__item"
});
const entryDiv = createDiv({
cls: "another-quick-switcher__item__entry"
});
const headerDiv = createDiv({
cls: [
"another-quick-switcher__item__title",
"another-quick-switcher__item__title__header",
item.hit ? "another-quick-switcher__item__title__header_hit" : "another-quick-switcher__item__title__header_no_hit",
`another-quick-switcher__item__title__header${item.level}`
],
text: item.value
});
entryDiv.appendChild(headerDiv);
if (item.hit) {
const i = this.hitItems.findIndex((x) => x.index === item.index);
if (i !== -1) {
entryDiv.createSpan({
cls: "another-quick-switcher__item__title__header_hit__counter",
text: `${i + 1} / ${this.hitItems.length}`
});
}
}
itemDiv.appendChild(entryDiv);
el.appendChild(itemDiv);
}
async onChooseSuggestion(item) {
this.appHelper.moveTo(item.position);
}
registerKeys(key, handler) {
var _a;
for (const x of (_a = this.settings.hotkeys.header[key]) != null ? _a : []) {
this.scope.register(
x.modifiers,
normalizeKey(capitalizeFirstLetter(x.key)),
(evt) => {
if (!evt.isComposing) {
evt.preventDefault();
handler(evt);
return false;
}
}
);
}
}
setHotkeys() {
this.scope.unregister(this.scope.keys.find((x) => x.key === "Escape"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Home"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "End"));
if (!this.settings.hideHotkeyGuides) {
this.setInstructions([
{ command: "[\u21B5]", purpose: "move to header" },
{ command: "[\u2191]", purpose: "up" },
{ command: "[\u2193]", purpose: "down" },
...createInstructions(this.settings.hotkeys.header)
]);
}
const navigateNext = (evt) => {
this.select(this.getNextSelectIndex(), evt);
};
const navigatePrevious = (evt) => {
this.select(this.getPreviousSelectIndex(), evt);
};
const moveToNextHit = (evt) => {
var _a, _b;
if (this.hitItems.length === 1) {
return;
}
if (this.hitItems.length === 0) {
navigateNext(evt);
return;
}
const nextIndex = (_b = (_a = this.hitItems.find((x) => x.index > this.unsafeSelectedIndex)) == null ? void 0 : _a.index) != null ? _b : this.hitItems[0].index;
this.select(nextIndex, evt);
};
const moveToPreviousHit = (evt) => {
if (this.hitItems.length === 1) {
return;
}
if (this.hitItems.length === 0) {
navigatePrevious(evt);
return;
}
const currentIndex = this.hitItems.findIndex(
(x) => x.index >= this.unsafeSelectedIndex
);
const previousIndex = currentIndex === 0 ? this.hitItems.length - 1 : currentIndex - 1;
this.select(this.hitItems[previousIndex].index, evt);
};
for (const x of this.scope.keys.filter(
(x2) => ["ArrowDown", "ArrowUp"].includes(x2.key)
)) {
this.scope.unregister(x);
}
this.scope.register([], "ArrowUp", (evt) => {
evt.preventDefault();
navigatePrevious(evt);
return false;
});
this.scope.register([], "ArrowDown", (evt) => {
evt.preventDefault();
navigateNext(evt);
return false;
});
this.registerKeys("up", (evt) => {
navigatePrevious(evt);
});
this.registerKeys("down", (evt) => {
navigateNext(evt);
});
this.registerKeys("clear input", () => {
this.inputEl.value = "";
this.inputEl.dispatchEvent(new InputEvent("input"));
});
this.registerKeys("move to next hit", (evt) => {
moveToNextHit(evt);
});
this.registerKeys("move to previous hit", (evt) => {
moveToPreviousHit(evt);
});
this.registerKeys("toggle auto preview", () => {
this.autoPreview = !this.autoPreview;
this.refreshPreviewIcon();
if (this.autoPreview && !this.floating) {
this.enableFloating();
}
});
this.registerKeys("insert all to editor", async () => {
this.close();
const headers = this.chooser.values;
if (!headers) {
return;
}
const minLevel = minBy(headers, (x) => x.level).level;
for (const x of headers) {
this.appHelper.insertStringToActiveFile(
`${" ".repeat((x.level - minLevel) * 4)}- ${x.value}
`
);
}
});
this.registerKeys("dismiss", async () => {
this.close();
});
}
};
// src/ui/InFileModal.ts
var import_obsidian9 = require("obsidian");
var globalInternalStorage3 = {
query: "",
selected: null
};
var InFileModal = class extends import_obsidian9.SuggestModal {
constructor(app, settings, initialLeaf) {
super(app);
/** !Not work correctly in all cases */
this.unsafeSelectedIndex = 0;
this.suggestions = [];
this.modalEl.addClass("another-quick-switcher__modal-prompt");
this.appHelper = new AppHelper(app);
this.settings = settings;
this.logger = Logger.of(this.settings);
this.initialLeaf = initialLeaf;
this.floating = this.settings.autoPreviewInFloatingInFileSearch;
this.autoPreview = settings.autoPreviewInFloatingInFileSearch;
this.limit = 255;
this.setHotkeys();
this.setPlaceholder("Type anything then shows the results");
}
close() {
if (import_obsidian9.Platform.isMobile) {
this.onClose();
}
super.close();
}
async init() {
await this.indexingItems();
}
onOpen() {
var _a;
this.isOpen = true;
this.inputEl.value = globalInternalStorage3.query;
this.inputEl.select();
this.updateSuggestions();
if (this.floating) {
this.enableFloating();
this.refreshPreviewIcon();
}
if (globalInternalStorage3.selected != null && this.chooser.suggestions.length > 0) {
const selected = Math.min(
globalInternalStorage3.selected,
this.chooser.suggestions.length - 1
);
this.select(selected);
(_a = this.chooser.suggestions.at(selected)) == null ? void 0 : _a.scrollIntoView({
behavior: "auto",
block: "center",
inline: "center"
});
}
this.inputEl.addEventListener("input", (evt) => {
const unsafeEvt = evt;
if (this.suggestions.length === 0) {
return;
}
this.select(
Math.min(this.unsafeSelectedIndex, this.suggestions.length - 1),
unsafeEvt
);
});
this.opened = true;
}
onClose() {
super.onClose();
globalInternalStorage3.query = this.inputEl.value;
globalInternalStorage3.selected = this.chooser.values != null ? this.chooser.selectedItem : null;
}
select(index, evt) {
this.chooser.setSelectedItem(index, evt);
this.unsafeSelectedIndex = index;
if (this.autoPreview) {
const p = {
line: this.chooser.values[index].lineNumber - 1,
offset: 0,
col: 0
};
this.appHelper.moveTo({
start: p,
end: p
});
}
}
getNextSelectIndex() {
return this.chooser.selectedItem + 1 > this.chooser.suggestions.length - 1 ? 0 : this.chooser.selectedItem + 1;
}
getPreviousSelectIndex() {
return this.chooser.selectedItem - 1 < 0 ? this.chooser.suggestions.length - 1 : this.chooser.selectedItem - 1;
}
refreshPreviewIcon() {
var _a, _b;
(_a = this.previewIcon) == null ? void 0 : _a.remove();
if (this.autoPreview) {
this.previewIcon = this.inputEl.insertAdjacentElement(
"afterend",
createDiv({
cls: "another-quick-switcher__in-file__auto-preview-icon"
})
);
(_b = this.previewIcon) == null ? void 0 : _b.insertAdjacentHTML("beforeend", PREVIEW);
}
}
enableFloating() {
this.floating = true;
if (!import_obsidian9.Platform.isPhone) {
setFloatingModal(this.appHelper);
}
}
async indexingItems() {
const lines = this.appHelper.getCurrentEditor().getValue().split("\n");
this.ignoredItems = lines.map((line, i) => ({
lineBefore: range(this.settings.inFileContextLines).reverse().map((x) => lines[i - x - 1]).filter(isPresent),
line,
lineAfter: range(this.settings.inFileContextLines).map((x) => lines[i + x + 1]).filter(isPresent),
lineNumber: i + 1
}));
}
getSuggestions(query) {
var _a;
const start = performance.now();
const isQueryEmpty = query.trim() === "";
const queries = query.trim().split(" ");
this.currentQueriesRegExp = new RegExp(
queries.map(escapeRegExp).join("|"),
"gi"
);
const matchedSuggestions = isQueryEmpty ? [] : this.ignoredItems.filter(
(x) => queries.every(
(q) => capitalIncludes(
x.line,
q,
this.settings.normalizeAccentsAndDiacritics
)
)
);
this.logger.showDebugLog(`Get suggestions: ${query}`, start);
(_a = this.countInputEl) == null ? void 0 : _a.remove();
this.countInputEl = createDiv({
text: `${Math.min(matchedSuggestions.length, this.limit)} / ${matchedSuggestions.length}`,
cls: "another-quick-switcher__in-file__status__count-input"
});
this.inputEl.before(this.countInputEl);
this.suggestions = matchedSuggestions.slice(0, this.limit).map((x, order) => ({ ...x, order }));
return this.suggestions;
}
renderSuggestion(item, el) {
const itemDiv = createDiv({
cls: [
"another-quick-switcher__item",
"another-quick-switcher__in-file__item"
]
});
const descriptionsDiv = createDiv({
cls: "another-quick-switcher__item__descriptions"
});
const descriptionDiv = createDiv({
cls: "another-quick-switcher__in-file__item__description"
});
item.lineBefore.forEach((line, i) => {
const lineDiv = descriptionDiv.createDiv({
cls: "another-quick-switcher__in-file__line"
});
lineDiv.createSpan({
text: String(item.lineNumber - item.lineBefore.length + i),
cls: "another-quick-switcher__in-file__line-number"
});
lineDiv.createSpan({
text: trimLineByEllipsis(
line,
this.settings.inFileMaxDisplayLengthAroundMatchedWord
)
});
});
const activeLineDiv = descriptionDiv.createDiv({
cls: [
"another-quick-switcher__in-file__line",
"another-quick-switcher__in-file__active-line"
]
});
activeLineDiv.createSpan({
text: item.lineNumber.toString(),
cls: "another-quick-switcher__in-file__line-number"
});
const activeLineBlockDiv = activeLineDiv.createDiv();
let restLine = item.line;
let offset = 0;
const indexAndText = Array.from(
restLine.matchAll(this.currentQueriesRegExp)
).map((x) => ({ index: x.index, text: x[0] }));
for (const { index, text } of indexAndText) {
const before = restLine.slice(0, index - offset);
activeLineBlockDiv.createSpan({
text: trimLineByEllipsis(
before,
this.settings.inFileMaxDisplayLengthAroundMatchedWord
)
});
activeLineBlockDiv.createSpan({
text,
cls: "another-quick-switcher__hit_word"
});
offset += before.length + text.length;
restLine = item.line.slice(offset);
}
activeLineBlockDiv.createSpan({
text: trimLineByEllipsis(
restLine,
this.settings.inFileMaxDisplayLengthAroundMatchedWord
)
});
item.lineAfter.forEach((line, i) => {
const lineDiv = descriptionDiv.createDiv({
cls: "another-quick-switcher__in-file__line"
});
lineDiv.createSpan({
text: String(item.lineNumber + i + 1),
cls: "another-quick-switcher__in-file__line-number"
});
lineDiv.createSpan({
text: trimLineByEllipsis(
line,
this.settings.inFileMaxDisplayLengthAroundMatchedWord
)
});
});
if (item.order < 9) {
const hotKeyGuide = createSpan({
cls: "another-quick-switcher__in-file__item__hot-key-guide",
text: `${item.order + 1}`
});
descriptionsDiv.appendChild(hotKeyGuide);
}
descriptionsDiv.appendChild(descriptionDiv);
itemDiv.appendChild(descriptionsDiv);
el.appendChild(itemDiv);
}
async onChooseSuggestion(item) {
this.appHelper.moveTo(
this.appHelper.getCurrentEditor().posToOffset({ line: item.lineNumber - 1, ch: 0 })
);
}
registerKeys(key, handler) {
var _a;
for (const x of (_a = this.settings.hotkeys["in-file"][key]) != null ? _a : []) {
this.scope.register(
x.modifiers,
normalizeKey(capitalizeFirstLetter(x.key)),
(evt) => {
if (!evt.isComposing) {
evt.preventDefault();
handler(evt);
return false;
}
}
);
}
}
setHotkeys() {
this.scope.unregister(this.scope.keys.find((x) => x.key === "Escape"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Home"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "End"));
const openNthMod = quickResultSelectionModifier(
this.settings.userAltInsteadOfModForQuickResultSelection
);
if (!this.settings.hideHotkeyGuides) {
this.setInstructions([
{ command: "[\u21B5]", purpose: "open" },
{ command: "[\u2191]", purpose: "up" },
{ command: "[\u2193]", purpose: "down" },
{ command: `[${openNthMod} 1~9]`, purpose: "open Nth" },
...createInstructions(this.settings.hotkeys["in-file"])
]);
}
const navigateNext = (evt) => {
this.select(this.getNextSelectIndex(), evt);
};
const navigatePrevious = (evt) => {
this.select(this.getPreviousSelectIndex(), evt);
};
const keyHandlers = this.scope.keys.filter(
(x) => ["ArrowDown", "ArrowUp"].includes(x.key)
);
for (const x of keyHandlers) {
this.scope.unregister(x);
}
this.scope.register([], "ArrowUp", (evt) => {
evt.preventDefault();
navigatePrevious(evt);
return false;
});
this.scope.register([], "ArrowDown", (evt) => {
evt.preventDefault();
navigateNext(evt);
return false;
});
this.registerKeys("up", (evt) => {
navigatePrevious(evt);
});
this.registerKeys("down", (evt) => {
navigateNext(evt);
});
this.registerKeys("show all results", () => {
this.limit = Number.MAX_SAFE_INTEGER;
this.inputEl.dispatchEvent(new Event("input"));
});
const modifierKey = this.settings.userAltInsteadOfModForQuickResultSelection ? "Alt" : "Mod";
for (const n of [1, 2, 3, 4, 5, 6, 7, 8, 9]) {
this.scope.register([modifierKey], String(n), (evt) => {
this.chooser.setSelectedItem(n - 1, evt);
this.chooser.useSelectedItem({});
return false;
});
}
this.registerKeys("toggle auto preview", () => {
this.autoPreview = !this.autoPreview;
this.refreshPreviewIcon();
if (this.autoPreview) {
this.select(this.unsafeSelectedIndex);
if (!this.floating) {
this.enableFloating();
}
}
});
this.registerKeys("dismiss", async () => {
this.close();
});
}
};
// src/ui/LinkModal.ts
var import_obsidian10 = require("obsidian");
var LinkModal = class extends import_obsidian10.SuggestModal {
constructor(app, settings, initialLeaf) {
super(app);
this.lastOpenFileIndexByPath = {};
this.suggestions = [];
this.isClosed = new Promise((resolve) => {
this.markClosed = resolve;
});
this.navQueue = Promise.resolve();
this.modalEl.addClass("another-quick-switcher__modal-prompt");
this.vaultRootPath = normalizePath(
this.app.vault.adapter.basePath
);
this.appHelper = new AppHelper(app);
this.settings = settings;
this.logger = Logger.of(this.settings);
this.initialLeaf = initialLeaf;
this.limit = 255;
this.app.workspace.getLastOpenFiles().forEach((v, i) => {
this.lastOpenFileIndexByPath[v] = i;
});
this.setHotkeys();
this.debounceGetSuggestions = (0, import_obsidian10.debounce)(
(query, cb) => {
cb(this._getSuggestions(query));
},
this.settings.searchDelayMilliSeconds,
true
);
}
async init() {
await this.indexingItems();
}
onOpen() {
super.onOpen();
if (!import_obsidian10.Platform.isPhone) {
setFloatingModal(this.appHelper);
}
this.opened = true;
}
onClose() {
super.onClose();
if (this.stateToRestore) {
this.navigate(() => this.stateToRestore.restore());
}
this.navigate(this.markClosed);
}
async indexingItems() {
const ignoredItems = [];
const links = this.appHelper.getLinksByFilePathInActiveFile();
if (!links) {
return;
}
for (const [path, caches] of Object.entries(links)) {
const file = this.appHelper.getFileByPath(path);
const content = this.appHelper.getCurrentEditor().getValue();
for (const cache of caches) {
if (!isFrontMatterLinkCache(cache)) {
ignoredItems.push({
file,
displayLink: cache.displayText,
line: content.split("\n").at(cache.position.start.line),
lineNumber: cache.position.start.line + 1,
offset: cache.position.start.offset
});
}
}
}
this.ignoredItems = ignoredItems;
}
getSuggestions(query) {
if (!query || !this.opened) {
return this._getSuggestions(query);
}
return new Promise((resolve) => {
this.debounceGetSuggestions(query, (items) => {
resolve(items);
});
});
}
_getSuggestions(query) {
var _a;
const start = performance.now();
const isQueryEmpty = query.trim() === "";
const queries = query.trim().split(" ");
const matchedSuggestions = isQueryEmpty ? this.ignoredItems : this.ignoredItems.filter(
(x) => queries.every(
(q) => x.file && smartIncludes(
x.file.path,
q,
this.settings.normalizeAccentsAndDiacritics
) || smartIncludes(
x.line,
q,
this.settings.normalizeAccentsAndDiacritics
)
)
);
this.logger.showDebugLog(`Get suggestions: ${query}`, start);
(_a = this.countInputEl) == null ? void 0 : _a.remove();
this.countInputEl = createDiv({
text: `${Math.min(matchedSuggestions.length, this.limit)} / ${matchedSuggestions.length}`,
cls: "another-quick-switcher__link__status__count-input"
});
this.inputEl.before(this.countInputEl);
this.suggestions = matchedSuggestions.slice(0, this.limit).map((x, order) => ({ ...x, order }));
return this.suggestions;
}
renderSuggestion(item, el) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
const previousPath = (_d = (_b = (_a = this.suggestions[item.order - 1]) == null ? void 0 : _a.file) == null ? void 0 : _b.path) != null ? _d : (_c = this.suggestions[item.order - 1]) == null ? void 0 : _c.displayLink;
const sameFileWithPrevious = previousPath === ((_f = (_e = item.file) == null ? void 0 : _e.path) != null ? _f : item.displayLink);
const itemDiv = createDiv({
cls: "another-quick-switcher__item"
});
const entryDiv = createDiv({
cls: "another-quick-switcher__item__entry"
});
if (!sameFileWithPrevious) {
const extension = (_h = (_g = item.file) == null ? void 0 : _g.extension) != null ? _h : "md";
const titleDiv = createDiv({
cls: [
"another-quick-switcher__item__title",
"another-quick-switcher__link__item__title_entry"
],
text: (_j = (_i = item.file) == null ? void 0 : _i.basename) != null ? _j : item.displayLink,
attr: {
extension
}
});
const isExcalidrawFile = isExcalidraw(item.file);
if (extension !== "md" || isExcalidrawFile) {
const extDiv = createDiv({
cls: "another-quick-switcher__item__extension",
text: isExcalidrawFile ? "excalidraw" : extension
});
titleDiv.appendChild(extDiv);
}
entryDiv.appendChild(titleDiv);
itemDiv.appendChild(entryDiv);
if (this.settings.showDirectory) {
const directoryDiv = createDiv({
cls: "another-quick-switcher__item__directory"
});
directoryDiv.insertAdjacentHTML("beforeend", FOLDER);
const text = this.settings.showFullPathOfDirectory ? (_l = (_k = item.file) == null ? void 0 : _k.parent) == null ? void 0 : _l.path : (_n = (_m = item.file) == null ? void 0 : _m.parent) == null ? void 0 : _n.name;
directoryDiv.appendText(` ${text}`);
entryDiv.appendChild(directoryDiv);
if (this.settings.showDirectoryAtNewLine) {
itemDiv.appendChild(directoryDiv);
}
}
}
const descriptionsDiv = createDiv({
cls: "another-quick-switcher__item__descriptions"
});
const descriptionDiv = createDiv({
cls: "another-quick-switcher__link__item__description"
});
descriptionDiv.createSpan({
text: item.line
});
if (item.order < 9) {
const hotKeyGuide = createSpan({
cls: "another-quick-switcher__link__item__hot-key-guide",
text: `${item.order + 1}`
});
descriptionsDiv.appendChild(hotKeyGuide);
}
descriptionsDiv.appendChild(descriptionDiv);
itemDiv.appendChild(descriptionsDiv);
el.appendChild(itemDiv);
}
navigate(cb) {
this.navQueue = this.navQueue.then(cb);
}
async chooseCurrentSuggestion(leaf, option = {}) {
var _a, _b;
const item = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem];
if (!item) {
return null;
}
if (!option.keepOpen) {
this.close();
this.navigate(() => this.isClosed);
} else if (leaf === "same-tab") {
(_b = this.stateToRestore) != null ? _b : this.stateToRestore = this.appHelper.captureState(this.initialLeaf);
}
this.navigate(
() => this.appHelper.openFile(
this.appHelper.getActiveFile(),
{
leafType: leaf,
line: item.lineNumber - 1,
inplace: option.keepOpen,
preventDuplicateTabs: this.settings.preventDuplicateTabs
},
this.stateToRestore
)
);
return this.appHelper.getActiveFile();
}
async onChooseSuggestion() {
await this.chooseCurrentSuggestion("same-tab");
}
registerKeys(key, handler) {
var _a;
for (const x of (_a = this.settings.hotkeys.link[key]) != null ? _a : []) {
this.scope.register(
x.modifiers,
normalizeKey(capitalizeFirstLetter(x.key)),
(evt) => {
if (!evt.isComposing) {
evt.preventDefault();
handler();
return false;
}
}
);
}
}
setHotkeys() {
this.scope.unregister(this.scope.keys.find((x) => x.key === "Enter"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Escape"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Home"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "End"));
const openNthMod = quickResultSelectionModifier(
this.settings.userAltInsteadOfModForQuickResultSelection
);
if (!this.settings.hideHotkeyGuides) {
this.setInstructions([
{ command: "[\u21B5]", purpose: "open" },
{ command: "[\u2191]", purpose: "up" },
{ command: "[\u2193]", purpose: "down" },
{ command: `[${openNthMod} 1~9]`, purpose: "open Nth" },
...createInstructions(this.settings.hotkeys.link)
]);
}
this.registerKeys("up", () => {
document.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowUp" }));
});
this.registerKeys("down", () => {
document.dispatchEvent(
new KeyboardEvent("keydown", { key: "ArrowDown" })
);
});
this.registerKeys("open", async () => {
await this.chooseCurrentSuggestion("same-tab");
});
this.registerKeys("open in new tab", async () => {
await this.chooseCurrentSuggestion("new-tab");
});
this.registerKeys("open in new pane (horizontal)", async () => {
await this.chooseCurrentSuggestion("new-pane-horizontal");
});
this.registerKeys("open in new pane (vertical)", async () => {
await this.chooseCurrentSuggestion("new-pane-vertical");
});
this.registerKeys("open in new window", async () => {
await this.chooseCurrentSuggestion("new-window");
});
this.registerKeys("open in popup", async () => {
await this.chooseCurrentSuggestion("popup");
});
this.registerKeys("open in new tab in background", async () => {
await this.chooseCurrentSuggestion("new-tab-background", {
keepOpen: true
});
});
this.registerKeys("open all in new tabs", () => {
this.close();
if (this.chooser.values == null) {
return;
}
const files = this.chooser.values.slice().reverse().map((x) => x.file).filter(isPresent);
for (const x of files) {
this.appHelper.openFile(x, {
leafType: "new-tab-background",
preventDuplicateTabs: this.settings.preventDuplicateTabs
});
}
});
this.registerKeys("show all results", () => {
this.limit = Number.MAX_SAFE_INTEGER;
this.inputEl.dispatchEvent(new Event("input"));
});
this.registerKeys("preview", async () => {
await this.chooseCurrentSuggestion("same-tab", {
keepOpen: true
});
});
const modifierKey = this.settings.userAltInsteadOfModForQuickResultSelection ? "Alt" : "Mod";
for (const n of [1, 2, 3, 4, 5, 6, 7, 8, 9]) {
this.scope.register([modifierKey], String(n), (evt) => {
this.chooser.setSelectedItem(n - 1, evt);
this.chooser.useSelectedItem({});
return false;
});
}
this.registerKeys("dismiss", async () => {
this.close();
});
}
};
// src/ui/MoveModal.ts
var import_obsidian11 = require("obsidian");
function matchQuery3(item, query, matcher, isNormalizeAccentsDiacritics) {
const qs = query.split("/");
const folder = qs.pop();
return qs.every(
(dir) => {
var _a;
return smartIncludes(
(_a = item.folder.parent) == null ? void 0 : _a.path,
dir,
isNormalizeAccentsDiacritics
);
}
) && matcher(item, folder);
}
function matchQueryAll3(item, queries, matcher, isNormalizeAccentsDiacritics) {
return queries.every(
(q) => matchQuery3(item, q, matcher, isNormalizeAccentsDiacritics)
);
}
function stampMatchType2(item, queries, isNormalizeAccentsDiacritics) {
if (matchQueryAll3(
item,
queries,
(item2, query) => smartStartsWith(item2.folder.name, query, isNormalizeAccentsDiacritics),
isNormalizeAccentsDiacritics
)) {
return { ...item, matchType: "prefix-name" };
}
if (matchQueryAll3(
item,
queries,
(item2, query) => smartIncludes(item2.folder.name, query, isNormalizeAccentsDiacritics),
isNormalizeAccentsDiacritics
)) {
return { ...item, matchType: "name" };
}
if (matchQueryAll3(
item,
queries,
(item2, query) => smartIncludes(item2.folder.path, query, isNormalizeAccentsDiacritics),
isNormalizeAccentsDiacritics
)) {
return { ...item, matchType: "directory" };
}
return item;
}
var MoveModal = class extends import_obsidian11.SuggestModal {
constructor(app, settings) {
super(app);
this.modalEl.addClass("another-quick-switcher__modal-prompt");
this.appHelper = new AppHelper(app);
this.settings = settings;
this.setHotkeys();
this.originItems = this.appHelper.getFolders().filter((x) => !x.isRoot()).map((x) => ({
folder: x
}));
this.filteredItems = excludeItems(
this.originItems,
this.settings.moveFileExcludePrefixPathPatterns,
(x) => x.folder.path
);
}
getSuggestions(query) {
const qs = query.split(" ").filter((x) => x);
return this.filteredItems.map(
(x) => stampMatchType2(x, qs, this.settings.normalizeAccentsAndDiacritics)
).filter((x) => x.matchType).sort(sorter((x) => x.matchType === "directory" ? 1 : 0)).sort(
sorter(
(x) => x.matchType === "prefix-name" ? 1e3 - x.folder.name.length : 0,
"desc"
)
).slice(0, 10);
}
renderSuggestion(item, el) {
var _a;
const itemDiv = createDiv({
cls: [
"another-quick-switcher__item",
"another-quick-switcher__directory_item"
]
});
const entryDiv = createDiv({
cls: "another-quick-switcher__item__entry"
});
const folderDiv = createDiv({
cls: "another-quick-switcher__item__title",
text: item.folder.name
});
entryDiv.appendChild(folderDiv);
const directoryDiv = createDiv({
cls: "another-quick-switcher__item__directory"
});
directoryDiv.insertAdjacentHTML("beforeend", FOLDER);
directoryDiv.appendText(` ${(_a = item.folder.parent) == null ? void 0 : _a.name}`);
entryDiv.appendChild(directoryDiv);
itemDiv.appendChild(entryDiv);
el.appendChild(itemDiv);
}
async onChooseSuggestion(item) {
const activeFile = this.app.workspace.getActiveFile();
if (!activeFile) {
return;
}
await this.app.fileManager.renameFile(
activeFile,
`${item.folder.path}/${activeFile.name}`
);
}
registerKeys(key, handler) {
var _a;
for (const x of (_a = this.settings.hotkeys.move[key]) != null ? _a : []) {
this.scope.register(x.modifiers, x.key.toUpperCase(), (evt) => {
evt.preventDefault();
handler();
return false;
});
}
}
setHotkeys() {
this.scope.unregister(this.scope.keys.find((x) => x.key === "Escape"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "Home"));
this.scope.unregister(this.scope.keys.find((x) => x.key === "End"));
if (!this.settings.hideHotkeyGuides) {
this.setInstructions([
{ command: "[\u21B5]", purpose: "move to" },
{ command: "[\u2191]", purpose: "up" },
{ command: "[\u2193]", purpose: "down" },
...createInstructions(this.settings.hotkeys.move)
]);
}
this.registerKeys("up", () => {
document.dispatchEvent(new KeyboardEvent("keydown", { key: "ArrowUp" }));
});
this.registerKeys("down", () => {
document.dispatchEvent(
new KeyboardEvent("keydown", { key: "ArrowDown" })
);
});
this.registerKeys("open in default app", () => {
var _a, _b;
const folder = (_b = (_a = this.chooser.values) == null ? void 0 : _a[this.chooser.selectedItem]) == null ? void 0 : _b.folder;
if (!folder) {
return;
}
this.appHelper.openFolderInDefaultApp(folder);
this.close();
});
this.registerKeys("dismiss", async () => {
this.close();
});
}
};
// src/commands.ts
var SEARCH_COMMAND_PREFIX = "search-command";
function showSearchDialog(app, settings, command) {
var _a, _b, _c, _d, _e;
const activeFileLeaf = (_b = (_a = app.workspace.getActiveViewOfType(import_obsidian12.FileView)) == null ? void 0 : _a.leaf) != null ? _b : null;
const editor = (_d = (_c = app.workspace.getActiveViewOfType(import_obsidian12.MarkdownView)) == null ? void 0 : _c.editor) != null ? _d : null;
const modal = new AnotherQuickSwitcherModal({
app,
settings,
command,
originFile: app.workspace.getActiveFile(),
inputQuery: settings.useSelectionWordsAsDefaultInputQuery ? (_e = editor == null ? void 0 : editor.getSelection()) != null ? _e : null : null,
navigationHistories: [],
currentNavigationHistoryIndex: 0,
stackHistory: true,
initialLeaf: activeFileLeaf
});
modal.open();
}
function showFolderDialog(app, settings) {
const modal = new FolderModal(app, settings);
modal.open();
}
function showMoveDialog(app, settings) {
if (!app.workspace.getActiveFile()) {
return;
}
const modal = new MoveModal(app, settings);
modal.open();
}
async function showGrepDialog(app, settings) {
var _a, _b;
if (!import_obsidian12.Platform.isDesktop) {
new import_obsidian12.Notice("Grep is not supported on mobile.");
return;
}
if (!await existsRg(settings.ripgrepCommand)) {
new import_obsidian12.Notice(
`"${settings.ripgrepCommand}" was not working as a ripgrep command. If you have not installed ripgrep yet, please install it.`
);
return;
}
const activeFileLeaf = (_b = (_a = app.workspace.getActiveViewOfType(import_obsidian12.FileView)) == null ? void 0 : _a.leaf) != null ? _b : null;
const modal = new GrepModal(app, settings, activeFileLeaf);
modal.open();
}
async function showBacklinkDialog(app, settings) {
var _a, _b;
if (!app.workspace.getActiveFile()) {
return;
}
const activeFileLeaf = (_b = (_a = app.workspace.getActiveViewOfType(import_obsidian12.FileView)) == null ? void 0 : _a.leaf) != null ? _b : null;
const modal = new BacklinkModal(app, settings, activeFileLeaf);
await modal.init();
modal.open();
}
async function showLinkDialog(app, settings) {
var _a, _b;
if (!app.workspace.getActiveFile()) {
return;
}
const activeFileLeaf = (_b = (_a = app.workspace.getActiveViewOfType(import_obsidian12.FileView)) == null ? void 0 : _a.leaf) != null ? _b : null;
const modal = new LinkModal(app, settings, activeFileLeaf);
await modal.init();
modal.open();
}
async function showInFileDialog(app, settings) {
var _a, _b;
if (!app.workspace.getActiveFile()) {
return;
}
const activeFileLeaf = (_b = (_a = app.workspace.getActiveViewOfType(import_obsidian12.FileView)) == null ? void 0 : _a.leaf) != null ? _b : null;
const modal = new InFileModal(app, settings, activeFileLeaf);
await modal.init();
modal.open();
}
function showHeaderDialog(app, settings, floating) {
if (!app.workspace.getActiveFile()) {
return;
}
const modal = new HeaderModal(app, settings, floating);
modal.open();
}
function createCommands(app, settings) {
return [
{
id: "header-search-in-file",
name: "Header search in file",
checkCallback: (checking) => {
if (checking) {
return Boolean(app.workspace.getActiveFile());
}
showHeaderDialog(app, settings, false);
}
},
{
id: "header-floating-search-in-file",
name: "Header floating search in file",
checkCallback: (checking) => {
if (checking) {
return Boolean(app.workspace.getActiveFile());
}
showHeaderDialog(app, settings, true);
}
},
{
id: "folder",
name: "Reveal a folder in the file tree",
hotkeys: [],
callback: () => {
showFolderDialog(app, settings);
}
},
{
id: "move",
name: "Move file to another folder",
hotkeys: [{ modifiers: ["Mod", "Shift"], key: "m" }],
checkCallback: (checking) => {
if (checking) {
return Boolean(app.workspace.getActiveFile());
}
showMoveDialog(app, settings);
}
},
{
id: "grep",
name: "Grep",
hotkeys: [],
checkCallback: (checking) => {
if (checking) {
return import_obsidian12.Platform.isDesktop;
}
showGrepDialog(app, settings);
}
},
{
id: "backlink",
name: "Backlink search",
hotkeys: [],
checkCallback: (checking) => {
if (checking) {
return Boolean(app.workspace.getActiveFile());
}
showBacklinkDialog(app, settings);
}
},
{
id: "link",
name: "Link search",
hotkeys: [],
checkCallback: (checking) => {
if (checking) {
return Boolean(app.workspace.getActiveFile());
}
showLinkDialog(app, settings);
}
},
{
id: "in-file-search",
name: "In file search",
hotkeys: [],
checkCallback: (checking) => {
if (checking) {
return Boolean(app.workspace.getActiveFile());
}
showInFileDialog(app, settings);
}
},
...settings.searchCommands.map((command) => {
return {
id: `${SEARCH_COMMAND_PREFIX}_${command.name.replace(/ /g, "-").toLowerCase()}`,
name: command.name,
hotkeys: [],
callback: () => {
showSearchDialog(app, settings, command);
}
};
})
];
}
// src/main.ts
var AnotherQuickSwitcher = class extends import_obsidian13.Plugin {
async onload() {
this.appHelper = new AppHelper(this.app);
await this.loadSettings();
this.addSettingTab(new AnotherQuickSwitcherSettingTab(this.app, this));
if (this.appHelper.isCacheInitialized()) {
this.reloadCommands();
} else {
const cacheResolvedRef = this.app.metadataCache.on(
"resolved",
async () => {
this.reloadCommands();
this.app.metadataCache.offref(cacheResolvedRef);
}
);
}
}
reloadCommands() {
const commandIds = this.appHelper.getCommandIds(this.manifest.id);
for (const x of commandIds) {
this.appHelper.removeCommand(x);
}
const commands = createCommands(this.app, this.settings);
for (const x of commands) {
this.addCommand(x);
}
}
async loadSettings() {
const currentSettings = await this.loadData();
this.settings = import_ts_deepmerge2.default.withOptions(
{ mergeArrays: false },
DEFAULT_SETTINGS,
currentSettings != null ? currentSettings : {}
);
this.settings.searchCommands.forEach((_, i) => {
this.settings.searchCommands[i] = import_ts_deepmerge2.default.withOptions(
{ mergeArrays: false },
createDefaultSearchCommand(),
{
...this.settings.searchCommands[i]
}
);
if (this.settings.searchCommands[i].searchTarget === "markdown") {
this.settings.searchCommands[i].searchTarget = "file";
}
});
const defaultHotkeys = createDefaultHotkeys();
const defaultDialogKeys = Object.keys(defaultHotkeys);
for (const dialogKey of defaultDialogKeys) {
const dialogKeys = Object.keys(this.settings.hotkeys[dialogKey]);
for (const k of dialogKeys) {
if (!(k in defaultHotkeys[dialogKey])) {
delete this.settings.hotkeys[dialogKey][k];
}
}
}
}
async saveSettings() {
await this.saveData(this.settings);
}
};