1+ import * as vscode from 'vscode' ;
2+
3+ export class LedgerAccountCompletion implements vscode . CompletionItemProvider {
4+ accounts : string [ ] = [ ] ;
5+
6+ constructor ( ) {
7+ const defaultAccountsFile = vscode . Uri . joinPath ( vscode . extensions . getExtension ( 'parsa2820.ledger-cli' ) ! . extensionUri , 'examples' , 'accounts.ledger' ) . fsPath ;
8+ const accountFiles = vscode . workspace . getConfiguration ( 'ledger' ) . get < string [ ] > ( 'accountFiles' , [ ] ) ;
9+ if ( accountFiles . length === 0 ) {
10+ accountFiles . push ( defaultAccountsFile ) ;
11+ }
12+ accountFiles . forEach ( file => {
13+ this . loadAccountFile ( file ) . then ( accounts => {
14+ this . accounts . push ( ...accounts ) ;
15+ } ) ;
16+ } ) ;
17+ }
18+
19+ provideCompletionItems ( document : vscode . TextDocument , position : vscode . Position , token : vscode . CancellationToken , context : vscode . CompletionContext ) : vscode . ProviderResult < vscode . CompletionList < vscode . CompletionItem > | vscode . CompletionItem [ ] > {
20+ return this . accounts . map ( account => new vscode . CompletionItem ( account , vscode . CompletionItemKind . Variable ) ) ;
21+ }
22+
23+ resolveCompletionItem ?( item : vscode . CompletionItem , token : vscode . CancellationToken ) : vscode . ProviderResult < vscode . CompletionItem > {
24+ throw new Error ( 'Method not implemented.' ) ;
25+ }
26+
27+ private async loadAccountFile ( filePath : string ) : Promise < string [ ] > {
28+ try {
29+ const fileUri = vscode . Uri . file ( filePath ) ;
30+ const fileData = await vscode . workspace . fs . readFile ( fileUri ) ;
31+ const fileText = Buffer . from ( fileData ) . toString ( 'utf8' ) ;
32+ return this . loadAccounts ( fileText ) ;
33+ } catch ( error ) {
34+ console . error ( `Error reading account file ${ filePath } :` , error ) ;
35+ return [ ] ;
36+ }
37+ }
38+
39+ private loadAccounts ( fileText : string ) : string [ ] {
40+ const accounts : string [ ] = [ ] ;
41+ const lines = fileText . split ( / \r ? \n / ) ;
42+ for ( const line of lines ) {
43+ if ( this . isAccountDeclarationLine ( line ) ) {
44+ const account = this . extractAccountDeclarationLineEntry ( line ) ;
45+ if ( account ) {
46+ accounts . push ( account ) ;
47+ }
48+ }
49+ }
50+ return accounts ;
51+ }
52+
53+ private isAccountDeclarationLine ( text : string ) : boolean {
54+ return this . getAccountDeclarationPattern ( ) . test ( text ) ;
55+ }
56+
57+ private extractAccountDeclarationLineEntry ( text : string ) : string | null {
58+ const pattern = this . getAccountDeclarationPattern ( ) ;
59+ const match = pattern . exec ( text ) ;
60+ if ( match && match . groups ) {
61+ return match . groups [ 'account' ] . trim ( ) ;
62+ }
63+ return null ;
64+ }
65+
66+ private getAccountDeclarationPattern ( ) : RegExp {
67+ const accountNamePattern = / (?< account > [ \[ \( ] ? [ A - Z a - z 0 - 9 : _ \- ] + ) [ \] \) ] ? / ;
68+ const commentPattern = / \s * (?< comment > [ ; # % \| \* ] .* ) ? / ;
69+ return new RegExp (
70+ "^account\\s" +
71+ accountNamePattern . source +
72+ commentPattern . source +
73+ "$"
74+ ) ;
75+ }
76+ }
0 commit comments