Skip to content

Commit

Permalink
Finish modularizing completer
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Yu committed Dec 18, 2023
1 parent 2afcc6b commit e3db44c
Show file tree
Hide file tree
Showing 26 changed files with 808 additions and 816 deletions.
2 changes: 1 addition & 1 deletion src/compile/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ async function afterSuccessfulBuilt(lastStep: Step, skipped: boolean) {
return
}
lw.viewer.refresh(lw.file.getPdfPath(lastStep.rootFile))
lw.completer.reference.setNumbersFromAuxFile(lastStep.rootFile)
lw.completion.reference.setNumbersFromAuxFile(lastStep.rootFile)
await lw.cache.loadFlsFile(lastStep.rootFile ?? '')
const configuration = vscode.workspace.getConfiguration('latex-workshop', vscode.Uri.file(lastStep.rootFile))
// If the PDF viewer is internal, we call SyncTeX in src/components/viewer.ts.
Expand Down
2 changes: 1 addition & 1 deletion src/completion/bibtex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const logger = lw.log('Intelli', 'Bib')
type DataBibtexJsonType = typeof import('../../data/bibtex-entries.json')
type DataBibtexOptionalJsonType = typeof import('../../data/bibtex-optional-entries.json')

export class BibtexCompleter implements vscode.CompletionItemProvider {
export class BibProvider implements vscode.CompletionItemProvider {
private scope: vscode.ConfigurationScope | undefined = undefined
private readonly entryItems: vscode.CompletionItem[] = []
private readonly optFieldItems = Object.create(null) as { [key: string]: vscode.CompletionItem[] }
Expand Down
10 changes: 5 additions & 5 deletions src/completion/completer/argument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function from(result: RegExpMatchArray, args: CompletionArgs) {
return provideClassOptions(args.line)
}
const index = getArgumentIndex(result[2])
const packages = lw.completer.package.getPackagesIncluded(args.langId)
const packages = lw.completion.usepackage.getAll(args.langId)
let candidate: CmdEnvSuggestion | undefined
let environment: string | undefined
if (result[1] === 'begin') {
Expand Down Expand Up @@ -66,8 +66,8 @@ function providePackageOptions(line: string): vscode.CompletionItem[] {
if (!match) {
return []
}
lw.completer.loadPackageData(match[1])
const suggestions = lw.completer.package.getPackageOptions(match[1])
lw.completion.usepackage.load(match[1])
const suggestions = lw.completion.usepackage.getOpts(match[1])
.map(option => {
const item = new vscode.CompletionItem(option, vscode.CompletionItemKind.Constant)
item.insertText = new vscode.SnippetString(option)
Expand All @@ -86,8 +86,8 @@ function provideClassOptions(line: string): vscode.CompletionItem[] {
return []
}
const isDefaultClass = ['article', 'report', 'book'].includes(match[1])
lw.completer.loadPackageData(isDefaultClass ? 'latex-document' : `class-${match[1]}`)
const suggestions = lw.completer.package.getPackageOptions(isDefaultClass ? 'latex-document' : `class-${match[1]}`)
lw.completion.usepackage.load(isDefaultClass ? 'latex-document' : `class-${match[1]}`)
const suggestions = lw.completion.usepackage.getOpts(isDefaultClass ? 'latex-document' : `class-${match[1]}`)
.map(option => {
const item = new vscode.CompletionItem(option, vscode.CompletionItemKind.Constant)
item.insertText = new vscode.SnippetString(option)
Expand Down
125 changes: 62 additions & 63 deletions src/completion/completer/atsuggestion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,80 @@ import * as vscode from 'vscode'
import * as fs from 'fs'
import { lw } from '../../lw'
import type { CompletionProvider, CompletionArgs } from '../../types'
import {escapeRegExp} from '../../utils/utils'
import { escapeRegExp } from '../../utils/utils'

export const provider: CompletionProvider = { from }
export const atSuggestion = {
initialize
}

const data = {
triggerCharacter: '',
escapedTriggerCharacter: '',
suggestions: [] as vscode.CompletionItem[]
}

interface AtSuggestionItemEntry {
prefix: string,
body: string,
description: string
}

type DataAtSuggestionJsonType = typeof import('../../../data/at-suggestions.json')

export class AtSuggestion implements CompletionProvider {
private readonly triggerCharacter: string
private readonly escapedTriggerCharacter: string
private readonly suggestions: vscode.CompletionItem[] = []

constructor(triggerCharacter: string) {
this.triggerCharacter = triggerCharacter
this.escapedTriggerCharacter = escapeRegExp(this.triggerCharacter)

const allSuggestions: {[key: string]: AtSuggestionItemEntry} = JSON.parse(fs.readFileSync(`${lw.extensionRoot}/data/at-suggestions.json`).toString()) as DataAtSuggestionJsonType
this.initialize(allSuggestions)
lw.onConfigChange('intellisense.atSuggestion.user', () => {
this.initialize(allSuggestions)
})
lw.onConfigChange(['intellisense.atSuggestion.user'], initialize)
// AtSuggestion is not initialized here, but in AtSuggestionCompleter
function initialize(triggerCharacter?: string) {
if (triggerCharacter) {
data.triggerCharacter = triggerCharacter
data.escapedTriggerCharacter = escapeRegExp(data.triggerCharacter)
}
const userSnippets = vscode.workspace.getConfiguration('latex-workshop').get('intellisense.atSuggestion.user') as {[key: string]: string}
data.suggestions.length = 0
Object.entries(userSnippets).forEach(([prefix, body]) => {
if (body === '') {
return
}
const completionItem = new vscode.CompletionItem(prefix.replace('@', data.triggerCharacter), vscode.CompletionItemKind.Function)
completionItem.insertText = new vscode.SnippetString(body)
completionItem.documentation = 'User defined @suggestion'
completionItem.detail = 'User defined @suggestion'
data.suggestions.push(completionItem)
})

private initialize(suggestions: {[key: string]: AtSuggestionItemEntry}) {
const userSnippets = vscode.workspace.getConfiguration('latex-workshop').get('intellisense.atSuggestion.user') as {[key: string]: string}
this.suggestions.length = 0
Object.entries(userSnippets).forEach(([prefix, body]) => {
if (body === '') {
return
}
const completionItem = new vscode.CompletionItem(prefix.replace('@', this.triggerCharacter), vscode.CompletionItemKind.Function)
completionItem.insertText = new vscode.SnippetString(body)
completionItem.documentation = 'User defined @suggestion'
completionItem.detail = 'User defined @suggestion'
this.suggestions.push(completionItem)
})

Object.values(suggestions).forEach(item => {
if (item.prefix in userSnippets) {
return
}
const completionItem = new vscode.CompletionItem(item.prefix.replace('@', this.triggerCharacter), vscode.CompletionItemKind.Function)
completionItem.insertText = new vscode.SnippetString(item.body)
completionItem.documentation = new vscode.MarkdownString(item.description)
completionItem.detail = item.description
this.suggestions.push(completionItem)
})
}
const suggestions: {[key: string]: AtSuggestionItemEntry} = JSON.parse(fs.readFileSync(`${lw.extensionRoot}/data/at-suggestions.json`).toString()) as typeof import('../../../data/at-suggestions.json')
Object.values(suggestions).forEach(item => {
if (item.prefix in userSnippets) {
return
}
const completionItem = new vscode.CompletionItem(item.prefix.replace('@', data.triggerCharacter), vscode.CompletionItemKind.Function)
completionItem.insertText = new vscode.SnippetString(item.body)
completionItem.documentation = new vscode.MarkdownString(item.description)
completionItem.detail = item.description
data.suggestions.push(completionItem)
})
}

from(result: RegExpMatchArray, args: CompletionArgs) {
const suggestions = this.provide(args.line, args.position)
// Manually filter suggestions when there are several consecutive trigger characters
const reg = new RegExp(this.escapedTriggerCharacter + '{2,}$')
if (result[0].match(reg)) {
const filteredSuggestions = suggestions.filter(item => item.label === result[0])
if (filteredSuggestions.length > 0) {
return filteredSuggestions.map(item => {
item.range = new vscode.Range(args.position.translate(undefined, -item.label.toString().length), args.position)
return item
})
}
function from(result: RegExpMatchArray, args: CompletionArgs) {
const suggestions = provide(args.line, args.position)
// Manually filter suggestions when there are several consecutive trigger characters
const reg = new RegExp(data.escapedTriggerCharacter + '{2,}$')
if (result[0].match(reg)) {
const filteredSuggestions = suggestions.filter(item => item.label === result[0])
if (filteredSuggestions.length > 0) {
return filteredSuggestions.map(item => {
item.range = new vscode.Range(args.position.translate(undefined, -item.label.toString().length), args.position)
return item
})
}
return suggestions
}
return suggestions
}

private provide(line: string, position: vscode.Position): vscode.CompletionItem[] {
let range: vscode.Range | undefined = undefined
const startPos = line.lastIndexOf(this.triggerCharacter, position.character - 1)
if (startPos >= 0) {
range = new vscode.Range(position.line, startPos, position.line, position.character)
}
this.suggestions.forEach(suggestion => {suggestion.range = range})
return this.suggestions
function provide(line: string, position: vscode.Position): vscode.CompletionItem[] {
let range: vscode.Range | undefined = undefined
const startPos = line.lastIndexOf(data.triggerCharacter, position.character - 1)
if (startPos >= 0) {
range = new vscode.Range(position.line, startPos, position.line, position.character)
}
data.suggestions.forEach(suggestion => {suggestion.range = range})
return data.suggestions
}
33 changes: 33 additions & 0 deletions src/completion/completer/class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as vscode from 'vscode'
import * as fs from 'fs'
import { lw } from '../../lw'
import type { CompletionProvider } from '../../types'

export const provider: CompletionProvider = { from }

const data = {
suggestions: [] as vscode.CompletionItem[]
}

type ClassItemEntry = {
command: string,
detail: string,
documentation: string
}

function initialize(classes: {[key: string]: ClassItemEntry}) {
Object.values(classes).forEach(item => {
const cl = new vscode.CompletionItem(item.command, vscode.CompletionItemKind.Module)
cl.detail = item.detail
cl.documentation = new vscode.MarkdownString(`[${item.documentation}](${item.documentation})`)
data.suggestions.push(cl)
})
}

function from(): vscode.CompletionItem[] {
if (data.suggestions.length === 0) {
const allClasses: {[key: string]: ClassItemEntry} = JSON.parse(fs.readFileSync(`${lw.extensionRoot}/data/classnames.json`).toString()) as typeof import('../../../data/classnames.json')
initialize(allClasses)
}
return data.suggestions
}
37 changes: 0 additions & 37 deletions src/completion/completer/documentclass.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/completion/completer/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function provide(langId: string, line: string, position: vscode.Position): Compl
// Insert package environments
const configuration = vscode.workspace.getConfiguration('latex-workshop')
if (configuration.get('intellisense.package.enabled')) {
const packages = lw.completer.package.getPackagesIncluded(langId)
const packages = lw.completion.usepackage.getAll(langId)
Object.entries(packages).forEach(([packageName, options]) => {
getEnvFromPkg(packageName, snippetType).forEach(env => {
if (env.option && options && !options.includes(env.option)) {
Expand Down Expand Up @@ -241,7 +241,7 @@ function getEnvFromPkg(packageName: string, type: EnvSnippetType): CmdEnvSuggest
return entry
}

lw.completer.loadPackageData(packageName)
lw.completion.usepackage.load(packageName)
// No package command defined
const pkgEnvs = data.packageEnvs.get(packageName)
if (!pkgEnvs || pkgEnvs.length === 0) {
Expand Down
Loading

0 comments on commit e3db44c

Please sign in to comment.