Skip to content

Commit

Permalink
Modularize env and cmd
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Yu committed Dec 13, 2023
1 parent 338699e commit 0c7aeea
Show file tree
Hide file tree
Showing 26 changed files with 1,154 additions and 1,165 deletions.
221 changes: 110 additions & 111 deletions src/completion/completer/argument.ts
Original file line number Diff line number Diff line change
@@ -1,135 +1,134 @@
import * as vscode from 'vscode'
import { lw } from '../../lw'
import type { IProvider, IProviderArgs } from '../latex'
import { EnvSnippetType } from '../../types'
import type { CompletionArgs, CompletionProvider } from '../../types'
import { CmdEnvSuggestion, filterArgumentHint } from './completerutils'
import { EnvSnippetType } from './environment'

export class Argument implements IProvider {
export const provider: CompletionProvider = { from }

provideFrom(result: RegExpMatchArray, args: IProviderArgs) {
if (result[1] === 'usepackage') {
return this.providePackageOptions(args.line)
}
if (result[1] === 'documentclass') {
return this.provideClassOptions(args.line)
}
const index = this.getArgumentIndex(result[2])
const packages = lw.completer.package.getPackagesIncluded(args.langId)
let candidate: CmdEnvSuggestion | undefined
let environment: string | undefined
if (result[1] === 'begin') {
environment = result[2].match(/{(.*?)}/)?.[1]
}
for (const packageName of Object.keys(packages)) {
if (environment) {
const environments = lw.completer.environment.getEnvFromPkg(packageName, EnvSnippetType.AsCommand) || []
for (const env of environments) {
if (environment !== env.signature.name) {
continue
}
if (index !== env.keyvalpos + 1) { // Start from one.
continue
}
candidate = env
function from(result: RegExpMatchArray, args: CompletionArgs) {
if (result[1] === 'usepackage') {
return providePackageOptions(args.line)
}
if (result[1] === 'documentclass') {
return provideClassOptions(args.line)
}
const index = getArgumentIndex(result[2])
const packages = lw.completer.package.getPackagesIncluded(args.langId)
let candidate: CmdEnvSuggestion | undefined
let environment: string | undefined
if (result[1] === 'begin') {
environment = result[2].match(/{(.*?)}/)?.[1]
}
for (const packageName of Object.keys(packages)) {
if (environment) {
const environments = lw.completion.environment.getEnvFromPkg(packageName, EnvSnippetType.AsCommand) || []
for (const env of environments) {
if (environment !== env.signature.name) {
continue
}
} else {
const commands = lw.completer.command.getPackageCmds(packageName)
for (const command of commands) {
if (result[1] !== command.signature.name) {
continue
}
if (index !== command.keyvalpos) {
continue
}
candidate = command
break
if (index !== env.keyvalpos + 1) { // Start from one.
continue
}
candidate = env
}
if (candidate !== undefined) {
} else {
const commands = lw.completion.macro.getPackageCmds(packageName)
for (const command of commands) {
if (result[1] !== command.signature.name) {
continue
}
if (index !== command.keyvalpos) {
continue
}
candidate = command
break
}
}
const suggestions = candidate?.keyvals?.map(option => {
const item = new vscode.CompletionItem(option, vscode.CompletionItemKind.Constant)
item.insertText = new vscode.SnippetString(option)
return item
}) || []

filterArgumentHint(suggestions)

return suggestions
if (candidate !== undefined) {
break
}
}
const suggestions = candidate?.keyvals?.map(option => {
const item = new vscode.CompletionItem(option, vscode.CompletionItemKind.Constant)
item.insertText = new vscode.SnippetString(option)
return item
}) || []

private providePackageOptions(line: string): vscode.CompletionItem[] {
const regex = /\\usepackage.*{(.*?)}/
const match = line.match(regex)
if (!match) {
return []
}
lw.completer.loadPackageData(match[1])
const suggestions = lw.completer.package.getPackageOptions(match[1])
.map(option => {
const item = new vscode.CompletionItem(option, vscode.CompletionItemKind.Constant)
item.insertText = new vscode.SnippetString(option)
return item
})
filterArgumentHint(suggestions)

filterArgumentHint(suggestions)
return suggestions
}

return suggestions
function providePackageOptions(line: string): vscode.CompletionItem[] {
const regex = /\\usepackage.*{(.*?)}/
const match = line.match(regex)
if (!match) {
return []
}
lw.completer.loadPackageData(match[1])
const suggestions = lw.completer.package.getPackageOptions(match[1])
.map(option => {
const item = new vscode.CompletionItem(option, vscode.CompletionItemKind.Constant)
item.insertText = new vscode.SnippetString(option)
return item
})

private provideClassOptions(line: string): vscode.CompletionItem[] {
const regex = /\\documentclass.*{(.*?)}/s
const match = line.match(regex)
if (!match) {
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]}`)
.map(option => {
const item = new vscode.CompletionItem(option, vscode.CompletionItemKind.Constant)
item.insertText = new vscode.SnippetString(option)
return item
})
filterArgumentHint(suggestions)

filterArgumentHint(suggestions)
return suggestions
}

return suggestions
function provideClassOptions(line: string): vscode.CompletionItem[] {
const regex = /\\documentclass.*{(.*?)}/s
const match = line.match(regex)
if (!match) {
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]}`)
.map(option => {
const item = new vscode.CompletionItem(option, vscode.CompletionItemKind.Constant)
item.insertText = new vscode.SnippetString(option)
return item
})

private getArgumentIndex(argstr: string) {
let argumentIndex = 0
let curlyLevel = argstr[0] === '{' ? 1 : 0
let squareLevel = argstr[0] === '[' ? 1 : 0
for (let index = 1; index < argstr.length; index++) {
if (argstr[index-1] === '\\') {
continue
}
switch (argstr[index]) {
case '{':
curlyLevel++
break
case '[':
squareLevel++
break
case '}':
curlyLevel--
if (curlyLevel === 0 && squareLevel === 0) {
argumentIndex++
}
break
case ']':
squareLevel--
if (curlyLevel === 0 && squareLevel === 0) {
argumentIndex++
}
break
default:
break
}
filterArgumentHint(suggestions)

return suggestions
}

function getArgumentIndex(argstr: string) {
let argumentIndex = 0
let curlyLevel = argstr[0] === '{' ? 1 : 0
let squareLevel = argstr[0] === '[' ? 1 : 0
for (let index = 1; index < argstr.length; index++) {
if (argstr[index-1] === '\\') {
continue
}
switch (argstr[index]) {
case '{':
curlyLevel++
break
case '[':
squareLevel++
break
case '}':
curlyLevel--
if (curlyLevel === 0 && squareLevel === 0) {
argumentIndex++
}
break
case ']':
squareLevel--
if (curlyLevel === 0 && squareLevel === 0) {
argumentIndex++
}
break
default:
break
}
return argumentIndex
}
return argumentIndex
}
6 changes: 3 additions & 3 deletions src/completion/completer/atsuggestion.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as vscode from 'vscode'
import * as fs from 'fs'
import { lw } from '../../lw'
import type {IProvider, IProviderArgs} from '../latex'
import type { CompletionProvider, CompletionArgs } from '../../types'
import {escapeRegExp} from '../../utils/utils'

interface AtSuggestionItemEntry {
Expand All @@ -12,7 +12,7 @@ interface AtSuggestionItemEntry {

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

export class AtSuggestion implements IProvider {
export class AtSuggestion implements CompletionProvider {
private readonly triggerCharacter: string
private readonly escapedTriggerCharacter: string
private readonly suggestions: vscode.CompletionItem[] = []
Expand Down Expand Up @@ -54,7 +54,7 @@ export class AtSuggestion implements IProvider {
})
}

provideFrom(result: RegExpMatchArray, args: IProviderArgs) {
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,}$')
Expand Down
Loading

0 comments on commit 0c7aeea

Please sign in to comment.