2023-10-28 17:37:02 +00:00
|
|
|
import {Plugin, TFile, TFolder} from "obsidian"
|
2023-10-28 16:05:49 +00:00
|
|
|
|
|
|
|
|
2023-11-17 13:46:34 +00:00
|
|
|
export interface FileIndex {
|
2023-10-28 17:37:02 +00:00
|
|
|
basenames: {[basename: string]: string},
|
|
|
|
paths: string[],
|
2023-10-28 16:05:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-11-17 13:46:34 +00:00
|
|
|
export default class FileIndexPlugin extends Plugin {
|
|
|
|
static FILE_IGNORE_PATH = "file-index-ignore.json"
|
2023-10-29 00:55:41 +00:00
|
|
|
|
|
|
|
ignoreRegExps: RegExp[] = []
|
|
|
|
|
|
|
|
async reloadIgnoreRegExps() {
|
2023-11-17 13:46:34 +00:00
|
|
|
const ignoreFile = this.app.vault.getAbstractFileByPath(FileIndexPlugin.FILE_IGNORE_PATH)
|
2023-10-29 00:55:41 +00:00
|
|
|
|
|
|
|
if(ignoreFile === null) {
|
2023-11-17 13:46:34 +00:00
|
|
|
console.debug("[FileIndexPlugin] Ignore file does not exist, not ignoring anything:", FileIndexPlugin.FILE_IGNORE_PATH)
|
2023-10-29 00:55:41 +00:00
|
|
|
this.ignoreRegExps = []
|
|
|
|
}
|
|
|
|
else if(ignoreFile instanceof TFolder) {
|
2023-11-17 13:46:34 +00:00
|
|
|
console.debug("[FileIndexPlugin] Ignore file is actually a folder, not ignoring anything:", FileIndexPlugin.FILE_IGNORE_PATH)
|
2023-10-29 00:55:41 +00:00
|
|
|
this.ignoreRegExps = []
|
|
|
|
}
|
|
|
|
else if(ignoreFile instanceof TFile) {
|
|
|
|
const ignoreJSON = await this.app.vault.cachedRead(ignoreFile)
|
|
|
|
const ignoreContents: string[] = JSON.parse(ignoreJSON)
|
|
|
|
this.ignoreRegExps = ignoreContents.map((re) => new RegExp(re))
|
2023-11-17 13:46:34 +00:00
|
|
|
console.debug("[FileIndexPlugin] Determined ignore list to be:", this.ignoreRegExps)
|
2023-10-29 00:55:41 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-11-17 13:46:34 +00:00
|
|
|
console.error("[FileIndexPlugin] Ignore file is of an unknown type, not doing anything:", FileIndexPlugin.FILE_IGNORE_PATH)
|
2023-10-29 00:55:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async reloadIgnoreRegExpsIfIgnoreFileChanged(file: TFile) {
|
2023-11-17 13:46:34 +00:00
|
|
|
if(file.path === FileIndexPlugin.FILE_IGNORE_PATH) {
|
2023-10-29 00:55:41 +00:00
|
|
|
await this.reloadIgnoreRegExps()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-17 13:46:34 +00:00
|
|
|
static FILE_INDEX_PATH = "file-index.json"
|
2023-10-28 16:05:49 +00:00
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
async recreateFileIndex() {
|
|
|
|
const files = this.app.vault.getFiles()
|
2023-10-28 16:05:49 +00:00
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
const basenames: {[basename: string]: string} = {}
|
|
|
|
const paths = []
|
2023-10-28 16:05:49 +00:00
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
for(const file of files) {
|
2023-10-29 00:55:41 +00:00
|
|
|
let ignored = false
|
|
|
|
for(const regexp of this.ignoreRegExps) {
|
|
|
|
if(file.path.match(regexp)) {
|
|
|
|
ignored = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ignored) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
paths.push(file.path)
|
2023-11-06 13:34:01 +00:00
|
|
|
|
2023-11-17 13:55:11 +00:00
|
|
|
let basename
|
|
|
|
if(file.extension === "md") {
|
|
|
|
basename = file.basename.toLocaleLowerCase()
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
basename = file.basename.toLocaleLowerCase() + "." + file.extension.toLocaleLowerCase()
|
|
|
|
}
|
|
|
|
|
2023-11-06 13:49:28 +00:00
|
|
|
if(basenames.hasOwnProperty(basename)) {
|
2023-11-17 13:46:34 +00:00
|
|
|
console.warn("[FileIndexPlugin] Multiple files with the same basename detected:", basenames[basename], file.path)
|
2023-11-06 13:49:28 +00:00
|
|
|
}
|
2023-11-06 13:34:01 +00:00
|
|
|
basenames[basename] = file.path
|
2023-10-28 17:37:02 +00:00
|
|
|
}
|
2023-10-28 16:05:49 +00:00
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
paths.sort()
|
2023-10-28 16:05:49 +00:00
|
|
|
|
2023-11-17 13:46:34 +00:00
|
|
|
const index: FileIndex = {basenames, paths}
|
|
|
|
console.debug("[FileIndexPlugin] Determined index to be:", index)
|
2023-10-29 00:55:41 +00:00
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
const indexContents = JSON.stringify(index, null, "\t")
|
2023-10-28 16:05:49 +00:00
|
|
|
|
2023-11-17 13:46:34 +00:00
|
|
|
const indexFile = this.app.vault.getAbstractFileByPath(FileIndexPlugin.FILE_INDEX_PATH)
|
2023-10-29 00:55:41 +00:00
|
|
|
if(indexFile === null) {
|
2023-11-17 13:46:34 +00:00
|
|
|
console.debug("[FileIndexPlugin] File index does not exist, creating it right now at:", FileIndexPlugin.FILE_INDEX_PATH)
|
|
|
|
await this.app.vault.create(FileIndexPlugin.FILE_INDEX_PATH, indexContents)
|
2023-10-29 00:55:41 +00:00
|
|
|
}
|
|
|
|
else if(indexFile instanceof TFolder) {
|
2023-11-17 13:46:34 +00:00
|
|
|
console.debug("[FileIndexPlugin] Cannot create file index, as there's a folder at:", FileIndexPlugin.FILE_INDEX_PATH)
|
2023-10-28 17:37:02 +00:00
|
|
|
}
|
|
|
|
else if(indexFile instanceof TFile) {
|
2023-11-17 13:46:34 +00:00
|
|
|
console.debug("[FileIndexPlugin] File index already exists, overwriting contents of:", FileIndexPlugin.FILE_INDEX_PATH)
|
2023-10-28 17:37:02 +00:00
|
|
|
await this.app.vault.modify(indexFile, indexContents)
|
|
|
|
}
|
|
|
|
else {
|
2023-11-17 13:46:34 +00:00
|
|
|
console.error("[FileIndexPlugin] File index is of an unknown type, not doing anything:", FileIndexPlugin.FILE_INDEX_PATH)
|
2023-10-28 17:37:02 +00:00
|
|
|
}
|
2023-10-28 16:05:49 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 00:55:41 +00:00
|
|
|
#reloadIgnoreRegExpsIfIgnoreFileChangedBinding = this.reloadIgnoreRegExpsIfIgnoreFileChanged.bind(this)
|
|
|
|
#recreateFileIndexBinding = this.recreateFileIndex.bind(this)
|
2023-10-28 16:05:49 +00:00
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
async onload() {
|
2023-10-29 00:55:41 +00:00
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
this.addCommand({
|
2023-11-17 13:46:34 +00:00
|
|
|
id: 'recreate',
|
2023-10-28 17:37:02 +00:00
|
|
|
name: 'Force file index recreation',
|
|
|
|
callback: this.recreateFileIndex.bind(this)
|
|
|
|
})
|
2023-10-28 16:05:49 +00:00
|
|
|
|
2023-10-29 00:55:41 +00:00
|
|
|
this.app.workspace.onLayoutReady(async () => {
|
|
|
|
await this.reloadIgnoreRegExps()
|
|
|
|
await this.recreateFileIndex()
|
|
|
|
|
|
|
|
this.registerEvent(
|
|
|
|
this.app.vault.on("create", this.#reloadIgnoreRegExpsIfIgnoreFileChangedBinding)
|
|
|
|
)
|
|
|
|
this.registerEvent(
|
|
|
|
this.app.vault.on("delete", this.#reloadIgnoreRegExpsIfIgnoreFileChangedBinding)
|
|
|
|
)
|
|
|
|
this.registerEvent(
|
|
|
|
this.app.vault.on("rename", this.#reloadIgnoreRegExpsIfIgnoreFileChangedBinding)
|
|
|
|
)
|
|
|
|
|
|
|
|
this.registerEvent(
|
|
|
|
this.app.vault.on("create", this.#recreateFileIndexBinding)
|
|
|
|
)
|
|
|
|
this.registerEvent(
|
|
|
|
this.app.vault.on("delete", this.#recreateFileIndexBinding)
|
|
|
|
)
|
|
|
|
this.registerEvent(
|
|
|
|
this.app.vault.on("rename", this.#recreateFileIndexBinding)
|
|
|
|
)
|
|
|
|
})
|
2023-10-28 16:05:49 +00:00
|
|
|
}
|
|
|
|
|
2023-10-28 17:37:02 +00:00
|
|
|
onunload() {
|
2023-10-29 00:55:41 +00:00
|
|
|
|
2023-10-28 16:05:49 +00:00
|
|
|
}
|
|
|
|
}
|