hledger-lsp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +632 -0
- package/out/extension.d.ts +1 -0
- package/out/extension.d.ts.map +1 -0
- package/out/extension.js +2 -0
- package/out/extension.js.map +1 -0
- package/out/features/codeActions.d.ts +73 -0
- package/out/features/codeActions.d.ts.map +1 -0
- package/out/features/codeActions.js +417 -0
- package/out/features/codeActions.js.map +1 -0
- package/out/features/completion.d.ts +94 -0
- package/out/features/completion.d.ts.map +1 -0
- package/out/features/completion.js +323 -0
- package/out/features/completion.js.map +1 -0
- package/out/features/definition.d.ts +12 -0
- package/out/features/definition.d.ts.map +1 -0
- package/out/features/definition.js +61 -0
- package/out/features/definition.js.map +1 -0
- package/out/features/documentLinks.d.ts +17 -0
- package/out/features/documentLinks.d.ts.map +1 -0
- package/out/features/documentLinks.js +68 -0
- package/out/features/documentLinks.js.map +1 -0
- package/out/features/findReferences.d.ts +33 -0
- package/out/features/findReferences.d.ts.map +1 -0
- package/out/features/findReferences.js +79 -0
- package/out/features/findReferences.js.map +1 -0
- package/out/features/foldingRanges.d.ts +27 -0
- package/out/features/foldingRanges.d.ts.map +1 -0
- package/out/features/foldingRanges.js +111 -0
- package/out/features/foldingRanges.js.map +1 -0
- package/out/features/formatter.d.ts +70 -0
- package/out/features/formatter.d.ts.map +1 -0
- package/out/features/formatter.js +373 -0
- package/out/features/formatter.js.map +1 -0
- package/out/features/hover.d.ts +66 -0
- package/out/features/hover.d.ts.map +1 -0
- package/out/features/hover.js +387 -0
- package/out/features/hover.js.map +1 -0
- package/out/features/inlayHints.d.ts +43 -0
- package/out/features/inlayHints.d.ts.map +1 -0
- package/out/features/inlayHints.js +221 -0
- package/out/features/inlayHints.js.map +1 -0
- package/out/features/selectionRange.d.ts +47 -0
- package/out/features/selectionRange.d.ts.map +1 -0
- package/out/features/selectionRange.js +273 -0
- package/out/features/selectionRange.js.map +1 -0
- package/out/features/semanticTokens.d.ts +83 -0
- package/out/features/semanticTokens.d.ts.map +1 -0
- package/out/features/semanticTokens.js +370 -0
- package/out/features/semanticTokens.js.map +1 -0
- package/out/features/symbols.d.ts +47 -0
- package/out/features/symbols.d.ts.map +1 -0
- package/out/features/symbols.js +249 -0
- package/out/features/symbols.js.map +1 -0
- package/out/features/transactionAnalyzer.d.ts +63 -0
- package/out/features/transactionAnalyzer.d.ts.map +1 -0
- package/out/features/transactionAnalyzer.js +127 -0
- package/out/features/transactionAnalyzer.js.map +1 -0
- package/out/features/validator.d.ts +142 -0
- package/out/features/validator.d.ts.map +1 -0
- package/out/features/validator.js +633 -0
- package/out/features/validator.js.map +1 -0
- package/out/parser/ast.d.ts +37 -0
- package/out/parser/ast.d.ts.map +1 -0
- package/out/parser/ast.js +606 -0
- package/out/parser/ast.js.map +1 -0
- package/out/parser/includes.d.ts +25 -0
- package/out/parser/includes.d.ts.map +1 -0
- package/out/parser/includes.js +106 -0
- package/out/parser/includes.js.map +1 -0
- package/out/parser/index.d.ts +54 -0
- package/out/parser/index.d.ts.map +1 -0
- package/out/parser/index.js +146 -0
- package/out/parser/index.js.map +1 -0
- package/out/server/deps.d.ts +19 -0
- package/out/server/deps.d.ts.map +1 -0
- package/out/server/deps.js +77 -0
- package/out/server/deps.js.map +1 -0
- package/out/server/settings.d.ts +60 -0
- package/out/server/settings.d.ts.map +1 -0
- package/out/server/settings.js +110 -0
- package/out/server/settings.js.map +1 -0
- package/out/server.d.ts +3 -0
- package/out/server.d.ts.map +1 -0
- package/out/server.js +420 -0
- package/out/server.js.map +1 -0
- package/out/types.d.ts +84 -0
- package/out/types.d.ts.map +1 -0
- package/out/types.js +6 -0
- package/out/types.js.map +1 -0
- package/out/utils/index.d.ts +38 -0
- package/out/utils/index.d.ts.map +1 -0
- package/out/utils/index.js +89 -0
- package/out/utils/index.js.map +1 -0
- package/out/utils/uri.d.ts +32 -0
- package/out/utils/uri.d.ts.map +1 -0
- package/out/utils/uri.js +215 -0
- package/out/utils/uri.js.map +1 -0
- package/package.json +58 -0
package/out/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for the hledger language server
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Check if a line is a transaction header
|
|
6
|
+
* Transaction headers start with a date in YYYY-MM-DD or YYYY/MM/DD format
|
|
7
|
+
*/
|
|
8
|
+
export declare function isTransactionHeader(line: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Check if a line is a posting (indented account line)
|
|
11
|
+
*/
|
|
12
|
+
export declare function isPosting(line: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Check if a line is a comment
|
|
15
|
+
*/
|
|
16
|
+
export declare function isComment(line: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Check if a line is a directive
|
|
19
|
+
*/
|
|
20
|
+
export declare function isDirective(line: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Extract account name from a posting line
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractAccountFromPosting(line: string): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Parse a tag from a comment
|
|
27
|
+
* Tags are in the format tag:value or just tag:
|
|
28
|
+
*/
|
|
29
|
+
export declare function extractTags(comment: string): Record<string, string>;
|
|
30
|
+
/**
|
|
31
|
+
* Get the indentation level of a line
|
|
32
|
+
*/
|
|
33
|
+
export declare function getIndentationLevel(line: string): number;
|
|
34
|
+
/**
|
|
35
|
+
* Normalize account name (collapse multiple spaces)
|
|
36
|
+
*/
|
|
37
|
+
export declare function normalizeAccountName(account: string): string;
|
|
38
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG/C;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUjD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUnE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Utility functions for the hledger language server
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isTransactionHeader = isTransactionHeader;
|
|
7
|
+
exports.isPosting = isPosting;
|
|
8
|
+
exports.isComment = isComment;
|
|
9
|
+
exports.isDirective = isDirective;
|
|
10
|
+
exports.extractAccountFromPosting = extractAccountFromPosting;
|
|
11
|
+
exports.extractTags = extractTags;
|
|
12
|
+
exports.getIndentationLevel = getIndentationLevel;
|
|
13
|
+
exports.normalizeAccountName = normalizeAccountName;
|
|
14
|
+
/**
|
|
15
|
+
* Check if a line is a transaction header
|
|
16
|
+
* Transaction headers start with a date in YYYY-MM-DD or YYYY/MM/DD format
|
|
17
|
+
*/
|
|
18
|
+
function isTransactionHeader(line) {
|
|
19
|
+
const trimmed = line.trim();
|
|
20
|
+
if (!trimmed)
|
|
21
|
+
return false;
|
|
22
|
+
// Simple regex for date patterns
|
|
23
|
+
const datePattern = /^\d{4}[-/]\d{2}[-/]\d{2}/;
|
|
24
|
+
return datePattern.test(trimmed);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if a line is a posting (indented account line)
|
|
28
|
+
*/
|
|
29
|
+
function isPosting(line) {
|
|
30
|
+
// Postings must be indented with at least one space or tab
|
|
31
|
+
return /^[ \t]+\S/.test(line);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Check if a line is a comment
|
|
35
|
+
*/
|
|
36
|
+
function isComment(line) {
|
|
37
|
+
const trimmed = line.trim();
|
|
38
|
+
return trimmed.startsWith(';') || trimmed.startsWith('#');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Check if a line is a directive
|
|
42
|
+
*/
|
|
43
|
+
function isDirective(line) {
|
|
44
|
+
const trimmed = line.trim();
|
|
45
|
+
const directives = ['account', 'commodity', 'payee', 'tag', 'include', 'alias', 'end'];
|
|
46
|
+
return directives.some(d => {
|
|
47
|
+
if (d === 'end') {
|
|
48
|
+
// 'end' can be standalone or followed by a space
|
|
49
|
+
return trimmed === d || trimmed.startsWith(d + ' ');
|
|
50
|
+
}
|
|
51
|
+
return trimmed.startsWith(d + ' ');
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract account name from a posting line
|
|
56
|
+
*/
|
|
57
|
+
function extractAccountFromPosting(line) {
|
|
58
|
+
const trimmed = line.trim();
|
|
59
|
+
// Account name is the first token after indentation
|
|
60
|
+
const match = trimmed.match(/^([^;\s]+(?:\s+[^;\s]+)*?)(?:\s{2,}|\s+\$|\s+[0-9-]|$)/);
|
|
61
|
+
return match ? match[1].trim() : null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Parse a tag from a comment
|
|
65
|
+
* Tags are in the format tag:value or just tag:
|
|
66
|
+
*/
|
|
67
|
+
function extractTags(comment) {
|
|
68
|
+
const tags = {};
|
|
69
|
+
const tagPattern = /(\w+):([^,\s]*)/g;
|
|
70
|
+
let match;
|
|
71
|
+
while ((match = tagPattern.exec(comment)) !== null) {
|
|
72
|
+
tags[match[1]] = match[2] || '';
|
|
73
|
+
}
|
|
74
|
+
return tags;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get the indentation level of a line
|
|
78
|
+
*/
|
|
79
|
+
function getIndentationLevel(line) {
|
|
80
|
+
const match = line.match(/^([ \t]+)/);
|
|
81
|
+
return match ? match[1].length : 0;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Normalize account name (collapse multiple spaces)
|
|
85
|
+
*/
|
|
86
|
+
function normalizeAccountName(account) {
|
|
87
|
+
return account.replace(/\s+/g, ' ').trim();
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAMH,kDAOC;AAKD,8BAGC;AAKD,8BAGC;AAKD,kCAUC;AAKD,8DAKC;AAMD,kCAUC;AAKD,kDAGC;AAKD,oDAEC;AAnFD;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,IAAY;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAE3B,iCAAiC;IACjC,MAAM,WAAW,GAAG,0BAA0B,CAAC;IAC/C,OAAO,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS,CAAC,IAAY;IACpC,2DAA2D;IAC3D,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS,CAAC,IAAY;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,OAAO,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,IAAY;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IACvF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;QACzB,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;YAChB,iDAAiD;YACjD,OAAO,OAAO,KAAK,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAgB,yBAAyB,CAAC,IAAY;IACpD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,oDAAoD;IACpD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IACtF,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,OAAe;IACzC,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,MAAM,UAAU,GAAG,kBAAkB,CAAC;IACtC,IAAI,KAAK,CAAC;IAEV,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CAAC,IAAY;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACtC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAAC,OAAe;IAClD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
2
|
+
/**
|
|
3
|
+
* Convert a file:// URI to a filesystem path
|
|
4
|
+
* Properly decodes URI-encoded characters (e.g., %20 → space)
|
|
5
|
+
*/
|
|
6
|
+
export declare function toFilePath(uri: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Ensure a path is represented as a file:// URI
|
|
9
|
+
* Properly encodes special characters (e.g., space → %20)
|
|
10
|
+
*/
|
|
11
|
+
export declare function toFileUri(path: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Default fileReader implementation used by parser/server
|
|
14
|
+
*/
|
|
15
|
+
export declare function defaultFileReader(uri: string): TextDocument | null;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve include paths relative to a base URI.
|
|
18
|
+
* Behavior:
|
|
19
|
+
* - If includePath starts with 'file://': treat as absolute URI
|
|
20
|
+
* - If includePath starts with '/': treat as absolute filesystem path
|
|
21
|
+
* - If includePath starts with '~': expand tilde to home directory
|
|
22
|
+
* - Otherwise, treat as relative to the directory of baseUri
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveIncludePath(includePath: string, baseUri: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve include paths into one or more file:// URIs using fast-glob.
|
|
27
|
+
* This delegates glob expansion to fast-glob, configured to exclude dotfiles
|
|
28
|
+
* and to return absolute file paths. The pattern is interpreted relative to
|
|
29
|
+
* the including file's directory when not absolute.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveIncludePaths(includePath: string, baseUri: string): string[];
|
|
32
|
+
//# sourceMappingURL=uri.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uri.d.ts","sourceRoot":"","sources":["../../src/utils/uri.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAgB9C;AA2BD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAWlE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAoC/E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAyClF"}
|
package/out/utils/uri.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.toFilePath = toFilePath;
|
|
40
|
+
exports.toFileUri = toFileUri;
|
|
41
|
+
exports.defaultFileReader = defaultFileReader;
|
|
42
|
+
exports.resolveIncludePath = resolveIncludePath;
|
|
43
|
+
exports.resolveIncludePaths = resolveIncludePaths;
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
47
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
48
|
+
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
|
|
49
|
+
/**
|
|
50
|
+
* Convert a file:// URI to a filesystem path
|
|
51
|
+
* Properly decodes URI-encoded characters (e.g., %20 → space)
|
|
52
|
+
*/
|
|
53
|
+
function toFilePath(uri) {
|
|
54
|
+
if (uri.startsWith('file://')) {
|
|
55
|
+
const encodedPath = uri.substring(7);
|
|
56
|
+
// Decode each path component separately to handle encoded characters
|
|
57
|
+
const parts = encodedPath.split('/');
|
|
58
|
+
const decoded = parts.map(part => {
|
|
59
|
+
try {
|
|
60
|
+
return decodeURIComponent(part);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// If decoding fails, return the part as-is
|
|
64
|
+
return part;
|
|
65
|
+
}
|
|
66
|
+
}).join('/');
|
|
67
|
+
return decoded;
|
|
68
|
+
}
|
|
69
|
+
return uri;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Encode a path component for use in a file:// URI
|
|
73
|
+
* Encodes characters that are not allowed in URI paths according to RFC 3986
|
|
74
|
+
* Allowed unencoded: unreserved (A-Za-z0-9-._~) + sub-delims (!$&'()*+,;=) + : @
|
|
75
|
+
*/
|
|
76
|
+
function encodePathComponent(component) {
|
|
77
|
+
// Characters that should NOT be encoded in file URI paths (per RFC 3986)
|
|
78
|
+
// unreserved: A-Z a-z 0-9 - . _ ~
|
|
79
|
+
// sub-delims: ! $ & ' ( ) * + , ; =
|
|
80
|
+
// also allowed in paths: : @
|
|
81
|
+
const allowedChars = /[A-Za-z0-9\-._~!$&'()*+,;=:@]/;
|
|
82
|
+
let result = '';
|
|
83
|
+
for (let i = 0; i < component.length; i++) {
|
|
84
|
+
const char = component[i];
|
|
85
|
+
if (allowedChars.test(char)) {
|
|
86
|
+
result += char;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Encode this character
|
|
90
|
+
result += '%' + char.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Ensure a path is represented as a file:// URI
|
|
97
|
+
* Properly encodes special characters (e.g., space → %20)
|
|
98
|
+
*/
|
|
99
|
+
function toFileUri(path) {
|
|
100
|
+
if (path.startsWith('file://'))
|
|
101
|
+
return path;
|
|
102
|
+
// Encode each path component separately to preserve slashes
|
|
103
|
+
const parts = path.split('/');
|
|
104
|
+
const encoded = parts.map(part => encodePathComponent(part)).join('/');
|
|
105
|
+
return `file://${encoded}`;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Default fileReader implementation used by parser/server
|
|
109
|
+
*/
|
|
110
|
+
function defaultFileReader(uri) {
|
|
111
|
+
try {
|
|
112
|
+
const filePath = toFilePath(uri);
|
|
113
|
+
if (fs.existsSync(filePath)) {
|
|
114
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
115
|
+
return vscode_languageserver_textdocument_1.TextDocument.create(uri, 'hledger', 1, content);
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Resolve include paths relative to a base URI.
|
|
125
|
+
* Behavior:
|
|
126
|
+
* - If includePath starts with 'file://': treat as absolute URI
|
|
127
|
+
* - If includePath starts with '/': treat as absolute filesystem path
|
|
128
|
+
* - If includePath starts with '~': expand tilde to home directory
|
|
129
|
+
* - Otherwise, treat as relative to the directory of baseUri
|
|
130
|
+
*/
|
|
131
|
+
function resolveIncludePath(includePath, baseUri) {
|
|
132
|
+
// Handle file:// URI (e.g. file:///home/user/main.journal)
|
|
133
|
+
if (includePath.startsWith('file://')) {
|
|
134
|
+
// Already a file URI, return as-is
|
|
135
|
+
return includePath;
|
|
136
|
+
}
|
|
137
|
+
// Expand tilde to home directory (e.g. ~/main.journal)
|
|
138
|
+
if (includePath.startsWith('~')) {
|
|
139
|
+
const home = os.homedir();
|
|
140
|
+
// support both '~' and '~/...'
|
|
141
|
+
let rest = '';
|
|
142
|
+
if (includePath === '~') {
|
|
143
|
+
rest = '';
|
|
144
|
+
}
|
|
145
|
+
else if (includePath.startsWith('~/')) {
|
|
146
|
+
// remove the leading '~/'
|
|
147
|
+
rest = includePath.slice(2);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// something like '~user/foo' - leave as-is for now (resolve will handle)
|
|
151
|
+
rest = includePath.slice(1);
|
|
152
|
+
}
|
|
153
|
+
const resolved = path.resolve(home, rest);
|
|
154
|
+
return toFileUri(resolved);
|
|
155
|
+
}
|
|
156
|
+
// If includePath starts with '/', treat it as an absolute filesystem path
|
|
157
|
+
// (matching hledger behaviour: leading slash means system-root absolute path)
|
|
158
|
+
if (includePath.startsWith('/')) {
|
|
159
|
+
const resolved = path.resolve(includePath);
|
|
160
|
+
return toFileUri(resolved);
|
|
161
|
+
}
|
|
162
|
+
// Relative to the including file
|
|
163
|
+
const basePath = toFilePath(baseUri);
|
|
164
|
+
const baseDir = path.dirname(basePath);
|
|
165
|
+
const resolved = path.join(baseDir, includePath);
|
|
166
|
+
return toFileUri(resolved);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Resolve include paths into one or more file:// URIs using fast-glob.
|
|
170
|
+
* This delegates glob expansion to fast-glob, configured to exclude dotfiles
|
|
171
|
+
* and to return absolute file paths. The pattern is interpreted relative to
|
|
172
|
+
* the including file's directory when not absolute.
|
|
173
|
+
*/
|
|
174
|
+
function resolveIncludePaths(includePath, baseUri) {
|
|
175
|
+
// If not a glob, reuse resolveIncludePath for single-path cases
|
|
176
|
+
if (!/[*?\[\]{}]/.test(includePath)) {
|
|
177
|
+
return [resolveIncludePath(includePath, baseUri)];
|
|
178
|
+
}
|
|
179
|
+
// Determine cwd and pattern for fast-glob
|
|
180
|
+
let cwd;
|
|
181
|
+
let pattern = includePath;
|
|
182
|
+
if (includePath.startsWith('/')) {
|
|
183
|
+
// absolute pattern: remove leading slash and search from filesystem root
|
|
184
|
+
cwd = '/';
|
|
185
|
+
pattern = includePath.slice(1);
|
|
186
|
+
}
|
|
187
|
+
else if (includePath.startsWith('~')) {
|
|
188
|
+
const home = os.homedir();
|
|
189
|
+
if (includePath === '~') {
|
|
190
|
+
cwd = home;
|
|
191
|
+
pattern = '';
|
|
192
|
+
}
|
|
193
|
+
else if (includePath.startsWith('~/')) {
|
|
194
|
+
cwd = home;
|
|
195
|
+
pattern = includePath.slice(2);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
cwd = os.homedir();
|
|
199
|
+
pattern = includePath.slice(1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
const basePath = toFilePath(baseUri);
|
|
204
|
+
cwd = path.dirname(basePath);
|
|
205
|
+
pattern = includePath;
|
|
206
|
+
}
|
|
207
|
+
// fast-glob options: only files, absolute paths, ignore dotfiles/directories
|
|
208
|
+
const entries = fast_glob_1.default.sync(pattern, { cwd, onlyFiles: true, absolute: true, dot: false });
|
|
209
|
+
// Exclude the including file itself if present
|
|
210
|
+
const includingFile = toFilePath(baseUri);
|
|
211
|
+
const filtered = entries.filter(p => p !== includingFile).map(p => toFileUri(p));
|
|
212
|
+
filtered.sort();
|
|
213
|
+
return filtered;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=uri.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uri.js","sourceRoot":"","sources":["../../src/utils/uri.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hledger-lsp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Language Server Protocol implementation for hledger plain text accounting",
|
|
5
|
+
"main": "./out/server.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"hledger-lsp": "./out/server.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"out/**/*",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc -p .",
|
|
16
|
+
"watch": "tsc -watch -p .",
|
|
17
|
+
"lint": "eslint src --ext ts",
|
|
18
|
+
"test": "jest",
|
|
19
|
+
"test:watch": "jest --watch",
|
|
20
|
+
"test:coverage": "jest --coverage",
|
|
21
|
+
"test:verbose": "jest --verbose",
|
|
22
|
+
"prepare": "npm run build"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"hledger",
|
|
26
|
+
"lsp",
|
|
27
|
+
"language-server",
|
|
28
|
+
"accounting"
|
|
29
|
+
],
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/ptimoney/hledger-lsp.git"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/ptimoney/hledger-lsp/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/ptimoney/hledger-lsp#readme",
|
|
38
|
+
"author": "Patrick Timoney",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=16.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"vscode-languageserver": "^9.0.1",
|
|
45
|
+
"fast-glob": "^3.2.12",
|
|
46
|
+
"vscode-languageserver-textdocument": "^1.0.12"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/jest": "^30.0.0",
|
|
50
|
+
"@types/node": "^24.10.0",
|
|
51
|
+
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
|
52
|
+
"@typescript-eslint/parser": "^8.46.3",
|
|
53
|
+
"eslint": "^9.39.1",
|
|
54
|
+
"jest": "^30.2.0",
|
|
55
|
+
"ts-jest": "^29.4.5",
|
|
56
|
+
"typescript": "^5.9.3"
|
|
57
|
+
}
|
|
58
|
+
}
|