Skip to content

Commit

Permalink
Resolve #4118 Sub- and superscript auto-completion
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Yu committed Dec 30, 2023
1 parent 5ed7957 commit d5fbdd8
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 2 deletions.
57 changes: 57 additions & 0 deletions src/completion/completer/subsuperscript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as vscode from 'vscode'
import type * as Ast from '@unified-latex/unified-latex-types'
import { lw } from '../../lw'
import type { CompletionArgs, CompletionItem, CompletionProvider, FileCache } from '../../types'

import { argContentToStr } from '../../utils/parser'

export const provider: CompletionProvider = { from }
export const subsuperscript = {
parse,
}

function from(result: RegExpMatchArray, _: CompletionArgs) {
const isSub = result[0].startsWith('_')
let suggestions: CompletionItem[] = []
lw.cache.getIncludedTeX().forEach(cachedFile => {
suggestions = [...suggestions, ...((isSub ? lw.cache.get(cachedFile)?.elements.subscripts : lw.cache.get(cachedFile)?.elements.superscripts) ?? [])]
})
return suggestions
}


function parse(cache: FileCache) {
if (cache.ast !== undefined) {
const scripts = parseAst(cache.ast, cache.content.split('\n'), {sub: [], super: []})
cache.elements.subscripts = scripts.sub
cache.elements.superscripts = scripts.super
}
}

function parseAst(node: Ast.Node, lines: string[], scripts: {sub: CompletionItem[], super: CompletionItem[]}): {sub: CompletionItem[], super: CompletionItem[]} {
const entries = {sub: scripts.sub.map(entry => entry.label), super: scripts.super.map(entry => entry.label)}
if (node.type === 'macro' && ['^', '_'].includes(node.content)) {
const content = argContentToStr(node.args?.[0]?.content || [])

if (content !== '' && node.position !== undefined &&
!(node.content === '^' ? entries.super : entries.sub).includes(content)) {

(node.content === '^' ? entries.super : entries.sub).push(content)

;(node.content === '^' ? scripts.super : scripts.sub).push({
label: content,
kind: vscode.CompletionItemKind.Constant,
// One row before, four rows after
documentation: lines.slice(node.position.start.line - 2, node.position.end.line + 4).join('\n')
})
}
}

if ('content' in node && typeof node.content !== 'string') {
for (const subNode of node.content) {
parseAst(subNode, lines, scripts)
}
}

return scripts
}
2 changes: 2 additions & 0 deletions src/completion/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { citation } from './completer/citation'
import { environment } from './completer/environment'
import { macro } from './completer/macro'
import { subsuperscript } from './completer/subsuperscript'
import { reference } from './completer/reference'
import { usepackage } from './completer/package'
import { input } from './completer/input'
Expand All @@ -13,6 +14,7 @@ export const completion = {
citation,
environment,
macro,
subsuperscript,
reference,
usepackage,
input,
Expand Down
7 changes: 6 additions & 1 deletion src/completion/latex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { CompletionArgs, CompletionProvider, ReferenceDocType } from '../ty
import { citation, provider as citationProvider } from './completer/citation'
import { provider as environmentProvider } from './completer/environment'
import { provider as macroProvider } from './completer/macro'
import { provider as subsuperProvider } from './completer/subsuperscript'
import { provider as argumentProvider } from './completer/argument'
import { provider as classProvider } from './completer/class'
import { provider as referenceProvider } from './completer/reference'
Expand Down Expand Up @@ -36,7 +37,7 @@ export class Provider implements vscode.CompletionItemProvider {
provide(args: CompletionArgs): vscode.CompletionItem[] {
// Note that the order of the following array affects the result.
// 'command' must be at the last because it matches any commands.
for (const type of ['citation', 'reference', 'environment', 'package', 'documentclass', 'input', 'subimport', 'import', 'includeonly', 'glossary', 'argument', 'command']) {
for (const type of ['citation', 'reference', 'environment', 'package', 'documentclass', 'input', 'subimport', 'import', 'includeonly', 'glossary', 'argument', 'command', 'subsuper']) {
const suggestions = this.completion(type, args)
if (suggestions.length > 0) {
if (type === 'citation') {
Expand Down Expand Up @@ -149,6 +150,10 @@ export class Provider implements vscode.CompletionItemProvider {
reg = /\\(gls(?:pl|text|first|fmt(?:text|short|long)|plural|firstplural|name|symbol|desc|disp|user(?:i|ii|iii|iv|v|vi))?|Acr(?:long|full|short)?(?:pl)?|ac[slf]?p?)(?:\[[^[\]]*\])?{([^}]*)$/i
provider = glossaryProvider
break
case 'subsuper':
reg = /(?:\^|_){([^}]*)$/
provider = subsuperProvider
break
default:
// This shouldn't be possible, so mark as error case in log.
logger.log(`Error - trying to complete unknown type ${type}`)
Expand Down
1 change: 1 addition & 0 deletions src/core/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ function updateElements(fileCache: FileCache) {
lw.completion.glossary.parse(fileCache)
lw.completion.environment.parse(fileCache)
lw.completion.macro.parse(fileCache)
lw.completion.subsuperscript.parse(fileCache)
lw.completion.input.parseGraphicsPath(fileCache)
updateBibfiles(fileCache)
const elapsed = performance.now() - start
Expand Down
6 changes: 5 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ export type FileCache = {
/** command items */
command?: CmdEnvSuggestion[],
/** \usepackage{}, a dictionary whose key is package name and value is the options */
package?: {[packageName: string]: string[]}
package?: {[packageName: string]: string[]},
/** _{} */
subscripts?: CompletionItem[],
/** ^{} */
superscripts?: CompletionItem[]
},
/** The sub-files of the LaTeX file. They should be tex or plain files */
children: {
Expand Down

0 comments on commit d5fbdd8

Please sign in to comment.