openalgo-script 0.2.0 → 0.4.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.
Files changed (276) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/README.md +65 -31
  3. package/dist/adapters/charts/surfaces.d.ts +17 -0
  4. package/dist/adapters/charts/surfaces.d.ts.map +1 -1
  5. package/dist/adapters/charts/tables.js +82 -0
  6. package/dist/adapters/charts/tables.js.map +1 -1
  7. package/dist/adapters/codemirror/commands.d.ts +14 -0
  8. package/dist/adapters/codemirror/commands.d.ts.map +1 -0
  9. package/dist/adapters/codemirror/commands.js +52 -0
  10. package/dist/adapters/codemirror/commands.js.map +1 -0
  11. package/dist/adapters/codemirror/completion.d.ts +15 -0
  12. package/dist/adapters/codemirror/completion.d.ts.map +1 -0
  13. package/dist/adapters/codemirror/completion.js +64 -0
  14. package/dist/adapters/codemirror/completion.js.map +1 -0
  15. package/dist/adapters/codemirror/contract.d.ts +156 -0
  16. package/dist/adapters/codemirror/contract.d.ts.map +1 -0
  17. package/dist/adapters/codemirror/contract.js +42 -0
  18. package/dist/adapters/codemirror/contract.js.map +1 -0
  19. package/dist/adapters/codemirror/index.d.ts +43 -0
  20. package/dist/adapters/codemirror/index.d.ts.map +1 -0
  21. package/dist/adapters/codemirror/index.js +8 -0
  22. package/dist/adapters/codemirror/index.js.map +1 -0
  23. package/dist/adapters/codemirror/lint.d.ts +17 -0
  24. package/dist/adapters/codemirror/lint.d.ts.map +1 -0
  25. package/dist/adapters/codemirror/lint.js +62 -0
  26. package/dist/adapters/codemirror/lint.js.map +1 -0
  27. package/dist/adapters/codemirror/positions.d.ts +16 -0
  28. package/dist/adapters/codemirror/positions.d.ts.map +1 -0
  29. package/dist/adapters/codemirror/positions.js +65 -0
  30. package/dist/adapters/codemirror/positions.js.map +1 -0
  31. package/dist/adapters/codemirror/stream.d.ts +23 -0
  32. package/dist/adapters/codemirror/stream.d.ts.map +1 -0
  33. package/dist/adapters/codemirror/stream.js +70 -0
  34. package/dist/adapters/codemirror/stream.js.map +1 -0
  35. package/dist/adapters/codemirror/tokens.d.ts +44 -0
  36. package/dist/adapters/codemirror/tokens.d.ts.map +1 -0
  37. package/dist/adapters/codemirror/tokens.js +34 -0
  38. package/dist/adapters/codemirror/tokens.js.map +1 -0
  39. package/dist/adapters/codemirror/tooltips.d.ts +35 -0
  40. package/dist/adapters/codemirror/tooltips.d.ts.map +1 -0
  41. package/dist/adapters/codemirror/tooltips.js +108 -0
  42. package/dist/adapters/codemirror/tooltips.js.map +1 -0
  43. package/dist/core/accounting/charges.d.ts +136 -0
  44. package/dist/core/accounting/charges.d.ts.map +1 -0
  45. package/dist/core/accounting/charges.js +362 -0
  46. package/dist/core/accounting/charges.js.map +1 -0
  47. package/dist/core/accounting/equity.d.ts +158 -0
  48. package/dist/core/accounting/equity.d.ts.map +1 -0
  49. package/dist/core/accounting/equity.js +155 -0
  50. package/dist/core/accounting/equity.js.map +1 -0
  51. package/dist/core/accounting/index.d.ts +44 -0
  52. package/dist/core/accounting/index.d.ts.map +1 -0
  53. package/dist/core/accounting/index.js +36 -0
  54. package/dist/core/accounting/index.js.map +1 -0
  55. package/dist/core/accounting/markers.d.ts +43 -0
  56. package/dist/core/accounting/markers.d.ts.map +1 -0
  57. package/dist/core/accounting/markers.js +64 -0
  58. package/dist/core/accounting/markers.js.map +1 -0
  59. package/dist/core/accounting/monthly.d.ts +52 -0
  60. package/dist/core/accounting/monthly.d.ts.map +1 -0
  61. package/dist/core/accounting/monthly.js +99 -0
  62. package/dist/core/accounting/monthly.js.map +1 -0
  63. package/dist/core/accounting/report.d.ts +38 -0
  64. package/dist/core/accounting/report.d.ts.map +1 -0
  65. package/dist/core/accounting/report.js +63 -0
  66. package/dist/core/accounting/report.js.map +1 -0
  67. package/dist/core/accounting/shapes.d.ts +70 -0
  68. package/dist/core/accounting/shapes.d.ts.map +1 -0
  69. package/dist/core/accounting/shapes.js +21 -0
  70. package/dist/core/accounting/shapes.js.map +1 -0
  71. package/dist/core/accounting/statistics.d.ts +75 -0
  72. package/dist/core/accounting/statistics.d.ts.map +1 -0
  73. package/dist/core/accounting/statistics.js +246 -0
  74. package/dist/core/accounting/statistics.js.map +1 -0
  75. package/dist/core/accounting/trades.d.ts +118 -0
  76. package/dist/core/accounting/trades.d.ts.map +1 -0
  77. package/dist/core/accounting/trades.js +186 -0
  78. package/dist/core/accounting/trades.js.map +1 -0
  79. package/dist/core/backtest/compare.d.ts +38 -0
  80. package/dist/core/backtest/compare.d.ts.map +1 -0
  81. package/dist/core/backtest/compare.js +189 -0
  82. package/dist/core/backtest/compare.js.map +1 -0
  83. package/dist/core/backtest/declaration.d.ts +52 -0
  84. package/dist/core/backtest/declaration.d.ts.map +1 -0
  85. package/dist/core/backtest/declaration.js +48 -0
  86. package/dist/core/backtest/declaration.js.map +1 -0
  87. package/dist/core/backtest/drive.d.ts +29 -0
  88. package/dist/core/backtest/drive.d.ts.map +1 -0
  89. package/dist/core/backtest/drive.js +262 -0
  90. package/dist/core/backtest/drive.js.map +1 -0
  91. package/dist/core/backtest/index.d.ts +46 -0
  92. package/dist/core/backtest/index.d.ts.map +1 -0
  93. package/dist/core/backtest/index.js +36 -0
  94. package/dist/core/backtest/index.js.map +1 -0
  95. package/dist/core/backtest/range.d.ts +84 -0
  96. package/dist/core/backtest/range.d.ts.map +1 -0
  97. package/dist/core/backtest/range.js +90 -0
  98. package/dist/core/backtest/range.js.map +1 -0
  99. package/dist/core/backtest/record.d.ts +238 -0
  100. package/dist/core/backtest/record.d.ts.map +1 -0
  101. package/dist/core/backtest/record.js +176 -0
  102. package/dist/core/backtest/record.js.map +1 -0
  103. package/dist/core/backtest/replay.d.ts +48 -0
  104. package/dist/core/backtest/replay.d.ts.map +1 -0
  105. package/dist/core/backtest/replay.js +127 -0
  106. package/dist/core/backtest/replay.js.map +1 -0
  107. package/dist/core/backtest/resting.d.ts +62 -0
  108. package/dist/core/backtest/resting.d.ts.map +1 -0
  109. package/dist/core/backtest/resting.js +59 -0
  110. package/dist/core/backtest/resting.js.map +1 -0
  111. package/dist/core/backtest/settings.d.ts +117 -0
  112. package/dist/core/backtest/settings.d.ts.map +1 -0
  113. package/dist/core/backtest/settings.js +207 -0
  114. package/dist/core/backtest/settings.js.map +1 -0
  115. package/dist/core/backtest/simulate.d.ts +146 -0
  116. package/dist/core/backtest/simulate.d.ts.map +1 -0
  117. package/dist/core/backtest/simulate.js +217 -0
  118. package/dist/core/backtest/simulate.js.map +1 -0
  119. package/dist/core/catalogue/catalogue.generated.d.ts +66 -0
  120. package/dist/core/catalogue/catalogue.generated.d.ts.map +1 -1
  121. package/dist/core/catalogue/catalogue.generated.js +6 -0
  122. package/dist/core/catalogue/catalogue.generated.js.map +1 -1
  123. package/dist/core/catalogue/values.generated.d.ts +24 -0
  124. package/dist/core/catalogue/values.generated.d.ts.map +1 -1
  125. package/dist/core/check/index.d.ts +2 -1
  126. package/dist/core/check/index.d.ts.map +1 -1
  127. package/dist/core/check/index.js +1 -1
  128. package/dist/core/check/index.js.map +1 -1
  129. package/dist/core/check/library-prose.generated.d.ts +16 -0
  130. package/dist/core/check/library-prose.generated.d.ts.map +1 -0
  131. package/dist/core/check/library-prose.generated.js +353 -0
  132. package/dist/core/check/library-prose.generated.js.map +1 -0
  133. package/dist/core/check/surface.d.ts +24 -0
  134. package/dist/core/check/surface.d.ts.map +1 -1
  135. package/dist/core/check/surface.js +29 -0
  136. package/dist/core/check/surface.js.map +1 -1
  137. package/dist/core/emit/defaults.d.ts +35 -16
  138. package/dist/core/emit/defaults.d.ts.map +1 -1
  139. package/dist/core/emit/defaults.js +66 -0
  140. package/dist/core/emit/defaults.js.map +1 -1
  141. package/dist/core/emit/index.d.ts +2 -0
  142. package/dist/core/emit/index.d.ts.map +1 -1
  143. package/dist/core/emit/index.js +2 -0
  144. package/dist/core/emit/index.js.map +1 -1
  145. package/dist/core/engine/index.d.ts +1 -1
  146. package/dist/core/engine/index.d.ts.map +1 -1
  147. package/dist/core/engine/index.js +1 -1
  148. package/dist/core/engine/index.js.map +1 -1
  149. package/dist/core/engine/load.d.ts +15 -1
  150. package/dist/core/engine/load.d.ts.map +1 -1
  151. package/dist/core/engine/load.js +1 -0
  152. package/dist/core/engine/load.js.map +1 -1
  153. package/dist/core/index.d.ts +37 -3
  154. package/dist/core/index.d.ts.map +1 -1
  155. package/dist/core/index.js +17 -1
  156. package/dist/core/index.js.map +1 -1
  157. package/dist/core/version/version.generated.d.ts +1 -1
  158. package/dist/core/version/version.generated.js +1 -1
  159. package/dist/editor/complete.d.ts +40 -0
  160. package/dist/editor/complete.d.ts.map +1 -0
  161. package/dist/editor/complete.js +206 -0
  162. package/dist/editor/complete.js.map +1 -0
  163. package/dist/editor/diagnose.d.ts +18 -0
  164. package/dist/editor/diagnose.d.ts.map +1 -0
  165. package/dist/editor/diagnose.js +70 -0
  166. package/dist/editor/diagnose.js.map +1 -0
  167. package/dist/editor/format.d.ts +11 -0
  168. package/dist/editor/format.d.ts.map +1 -0
  169. package/dist/editor/format.js +50 -0
  170. package/dist/editor/format.js.map +1 -0
  171. package/dist/editor/highlight.d.ts +28 -0
  172. package/dist/editor/highlight.d.ts.map +1 -0
  173. package/dist/editor/highlight.js +65 -0
  174. package/dist/editor/highlight.js.map +1 -0
  175. package/dist/editor/hover.d.ts +40 -0
  176. package/dist/editor/hover.d.ts.map +1 -0
  177. package/dist/editor/hover.js +147 -0
  178. package/dist/editor/hover.js.map +1 -0
  179. package/dist/editor/index.d.ts +60 -0
  180. package/dist/editor/index.d.ts.map +1 -0
  181. package/dist/editor/index.js +7 -0
  182. package/dist/editor/index.js.map +1 -0
  183. package/dist/editor/kinds.d.ts +27 -0
  184. package/dist/editor/kinds.d.ts.map +1 -0
  185. package/dist/editor/kinds.js +118 -0
  186. package/dist/editor/kinds.js.map +1 -0
  187. package/dist/editor/layout.d.ts +47 -0
  188. package/dist/editor/layout.d.ts.map +1 -0
  189. package/dist/editor/layout.js +135 -0
  190. package/dist/editor/layout.js.map +1 -0
  191. package/dist/editor/manifest.d.ts +47 -0
  192. package/dist/editor/manifest.d.ts.map +1 -0
  193. package/dist/editor/manifest.js +93 -0
  194. package/dist/editor/manifest.js.map +1 -0
  195. package/dist/editor/reading.d.ts +41 -0
  196. package/dist/editor/reading.d.ts.map +1 -0
  197. package/dist/editor/reading.js +51 -0
  198. package/dist/editor/reading.js.map +1 -0
  199. package/dist/editor/scan.d.ts +26 -0
  200. package/dist/editor/scan.d.ts.map +1 -0
  201. package/dist/editor/scan.js +139 -0
  202. package/dist/editor/scan.js.map +1 -0
  203. package/dist/editor/scope.d.ts +19 -0
  204. package/dist/editor/scope.d.ts.map +1 -0
  205. package/dist/editor/scope.js +99 -0
  206. package/dist/editor/scope.js.map +1 -0
  207. package/dist/editor/signature.d.ts +38 -0
  208. package/dist/editor/signature.d.ts.map +1 -0
  209. package/dist/editor/signature.js +112 -0
  210. package/dist/editor/signature.js.map +1 -0
  211. package/dist/editor/site.d.ts +46 -0
  212. package/dist/editor/site.d.ts.map +1 -0
  213. package/dist/editor/site.js +184 -0
  214. package/dist/editor/site.js.map +1 -0
  215. package/dist/editor/spacing.d.ts +29 -0
  216. package/dist/editor/spacing.d.ts.map +1 -0
  217. package/dist/editor/spacing.js +116 -0
  218. package/dist/editor/spacing.js.map +1 -0
  219. package/package.json +30 -3
  220. package/spec/errors.json +140 -0
  221. package/src/adapters/charts/surfaces.ts +17 -0
  222. package/src/adapters/charts/tables.ts +88 -0
  223. package/src/adapters/codemirror/commands.ts +53 -0
  224. package/src/adapters/codemirror/completion.ts +74 -0
  225. package/src/adapters/codemirror/contract.ts +156 -0
  226. package/src/adapters/codemirror/index.ts +66 -0
  227. package/src/adapters/codemirror/lint.ts +66 -0
  228. package/src/adapters/codemirror/positions.ts +79 -0
  229. package/src/adapters/codemirror/stream.ts +87 -0
  230. package/src/adapters/codemirror/tokens.ts +64 -0
  231. package/src/adapters/codemirror/tooltips.ts +113 -0
  232. package/src/core/accounting/charges.ts +452 -0
  233. package/src/core/accounting/equity.ts +276 -0
  234. package/src/core/accounting/index.ts +49 -0
  235. package/src/core/accounting/markers.ts +95 -0
  236. package/src/core/accounting/monthly.ts +137 -0
  237. package/src/core/accounting/report.ts +89 -0
  238. package/src/core/accounting/shapes.ts +73 -0
  239. package/src/core/accounting/statistics.ts +350 -0
  240. package/src/core/accounting/trades.ts +313 -0
  241. package/src/core/backtest/compare.ts +244 -0
  242. package/src/core/backtest/declaration.ts +97 -0
  243. package/src/core/backtest/drive.ts +364 -0
  244. package/src/core/backtest/index.ts +52 -0
  245. package/src/core/backtest/range.ts +137 -0
  246. package/src/core/backtest/record.ts +341 -0
  247. package/src/core/backtest/replay.ts +158 -0
  248. package/src/core/backtest/resting.ts +125 -0
  249. package/src/core/backtest/settings.ts +280 -0
  250. package/src/core/backtest/simulate.ts +304 -0
  251. package/src/core/catalogue/catalogue.generated.ts +6 -0
  252. package/src/core/catalogue/values.generated.ts +6 -0
  253. package/src/core/check/index.ts +3 -0
  254. package/src/core/check/library-prose.generated.ts +367 -0
  255. package/src/core/check/surface.ts +34 -0
  256. package/src/core/emit/defaults.ts +70 -0
  257. package/src/core/emit/index.ts +2 -0
  258. package/src/core/engine/index.ts +1 -1
  259. package/src/core/engine/load.ts +16 -2
  260. package/src/core/index.ts +85 -1
  261. package/src/core/version/version.generated.ts +1 -1
  262. package/src/editor/complete.ts +266 -0
  263. package/src/editor/diagnose.ts +71 -0
  264. package/src/editor/format.ts +85 -0
  265. package/src/editor/highlight.ts +110 -0
  266. package/src/editor/hover.ts +199 -0
  267. package/src/editor/index.ts +65 -0
  268. package/src/editor/kinds.ts +157 -0
  269. package/src/editor/layout.ts +189 -0
  270. package/src/editor/manifest.ts +119 -0
  271. package/src/editor/reading.ts +69 -0
  272. package/src/editor/scan.ts +162 -0
  273. package/src/editor/scope.ts +122 -0
  274. package/src/editor/signature.ts +150 -0
  275. package/src/editor/site.ts +233 -0
  276. package/src/editor/spacing.ts +132 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * `signature`: the call being written, and which parameter the cursor is in.
3
+ *
4
+ * The call is found from the brackets rather than from the tree, because a call
5
+ * being written has no finished tree node: `ema(close, ` is the state every call
6
+ * is in while somebody types one, and that is exactly when this is asked.
7
+ * `site.ts` does that part.
8
+ *
9
+ * ## The default shown is the default the compiler applies
10
+ *
11
+ * This is the trap worth naming, because getting it wrong produces a tooltip
12
+ * that is confidently wrong rather than absent. `stdlib.md` states a default for
13
+ * every optional argument, and `scripts/check-defaults.mjs` already holds the
14
+ * compiler to those: a value the surface carries that the specification does not
15
+ * state fails the build, and so does one the specification states that the
16
+ * compiler does not apply.
17
+ *
18
+ * So this reads the same two places that check reads, through `parametersOf`:
19
+ * the library manifest for an ordinary call, and the emitter for the eight
20
+ * declaration calls whose optional arguments become fields of a declaration
21
+ * rather than arguments. A number shown here therefore cannot differ from the
22
+ * number the compiler fills in; if it ever does, the defaults check fails before
23
+ * anybody sees the tooltip.
24
+ *
25
+ * A writer's own function is answered too, from the checker's record of it. Its
26
+ * parameter types are the ones the checker worked out, and a default it declares
27
+ * is quoted from the source text rather than printed from the tree, because the
28
+ * text is what the writer wrote.
29
+ */
30
+ import { endOffset, entryFor, fillTemplate, proseFor, typeText } from '../core/index.js';
31
+ import { entryAt, parametersOf, signatureTextOf } from './manifest.js';
32
+ import { readChecked } from './reading.js';
33
+ import { siteAt } from './site.js';
34
+ /** Which parameter a position in the argument list means. */
35
+ function activeIn(parameters, call) {
36
+ if (call.label !== undefined) {
37
+ return parameters.findIndex((one) => one.name === call.label);
38
+ }
39
+ return call.argument < parameters.length ? call.argument : -1;
40
+ }
41
+ /**
42
+ * A function the file declares, as the checker recorded it.
43
+ *
44
+ * `language.md` 11.1 lets a parameter carry a default, and the text of that
45
+ * default is quoted from the source rather than printed back from the tree: the
46
+ * tree holds an expression and printing one would be a second formatter, while
47
+ * the source holds what the writer typed.
48
+ */
49
+ function declaredSignature(checked, text, call) {
50
+ const held = checked.functions.find((one) => one.declaration.name.text === call.name);
51
+ if (held === undefined)
52
+ return undefined;
53
+ const parameters = held.declaration.parameters.map((one, index) => {
54
+ const value = one.defaultValue;
55
+ const binding = held.parameters[index];
56
+ return {
57
+ name: one.name.text,
58
+ type: binding === undefined ? 'unknown' : typeText(binding.type),
59
+ required: value === undefined,
60
+ defaultText: value === undefined ? undefined : text.slice(value.span.offset, endOffset(value.span)),
61
+ values: [],
62
+ };
63
+ });
64
+ const written = parameters.map((one) => {
65
+ const head = `${one.name}${one.required ? '' : '?'}: ${one.type}`;
66
+ return one.defaultText === undefined ? head : `${head} = ${one.defaultText}`;
67
+ });
68
+ return {
69
+ name: call.name,
70
+ of: 'declared',
71
+ signature: `fn ${call.name}(${written.join(', ')})`,
72
+ parameters,
73
+ active: activeIn(parameters, call),
74
+ summary: undefined,
75
+ planned: false,
76
+ refusal: undefined,
77
+ span: call.nameSpan,
78
+ };
79
+ }
80
+ /**
81
+ * The call the cursor is inside, or nothing where it is inside none.
82
+ *
83
+ * Nothing is the answer for a cursor outside every bracket, and for one inside a
84
+ * bracket whose callee the language does not have: a name that resolves to
85
+ * neither the library nor the file is OS2001, and `diagnose` is what says so.
86
+ * A tooltip that invented a signature for it would be a second opinion about
87
+ * what the file declares.
88
+ */
89
+ export function signature(source, offset) {
90
+ const { file, tokens, checked } = readChecked(source);
91
+ const call = siteAt(file, tokens, offset).call;
92
+ if (call === undefined)
93
+ return undefined;
94
+ const entry = entryAt(call.name, call.argument + 1);
95
+ if (entry === undefined)
96
+ return declaredSignature(checked, file.text, call);
97
+ const parameters = parametersOf(entry);
98
+ return {
99
+ name: call.name,
100
+ of: 'library',
101
+ signature: signatureTextOf(entry),
102
+ parameters,
103
+ active: activeIn(parameters, call),
104
+ summary: proseFor(call.name)?.summary,
105
+ planned: entry.planned,
106
+ refusal: entry.planned
107
+ ? fillTemplate(entryFor('OS2020').message, { name: call.name })
108
+ : undefined,
109
+ span: call.nameSpan,
110
+ };
111
+ }
112
+ //# sourceMappingURL=signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.js","sourceRoot":"","sources":["../../src/editor/signature.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { SourceFile, Span, Token } from '../core/index.js';
2
+ /** The call the cursor is inside, as far as the brackets say. */
3
+ export interface CallSite {
4
+ /** The callee as written, with its namespace: `ema`, `draw.box`. */
5
+ readonly name: string;
6
+ readonly nameSpan: Span;
7
+ /** Which argument the cursor is in, counting from zero. */
8
+ readonly argument: number;
9
+ /** The label written for this argument, when it was written as `name = ...`. */
10
+ readonly label: string | undefined;
11
+ /** Every label already written in this call, so a completion can drop them. */
12
+ readonly labels: readonly string[];
13
+ /** The bracket that opened it, which is what a host anchors a tooltip to. */
14
+ readonly open: Span;
15
+ }
16
+ /** What the cursor is on, and what it is inside. */
17
+ export interface Site {
18
+ /** The word being typed, when the cursor is in or at the end of one. */
19
+ readonly word: string;
20
+ /** Where it sits, so a host replaces the word rather than inserting into it. */
21
+ readonly replace: Span;
22
+ /** The namespace the word follows, when it was written as `draw.` */
23
+ readonly namespace: string | undefined;
24
+ /** Whether the cursor sits after a dot, where only members may be written. */
25
+ readonly afterDot: boolean;
26
+ readonly call: CallSite | undefined;
27
+ }
28
+ /**
29
+ * Everything the two functions need to know about a position.
30
+ *
31
+ * The word is the token the offset is inside or immediately after, which is
32
+ * what a writer half way through typing a name has. A cursor sitting on a space
33
+ * has no word and an empty replacement span at the cursor, so a host inserts
34
+ * there rather than overwriting whatever is to the left.
35
+ */
36
+ export declare function siteAt(file: SourceFile, tokens: readonly Token[], offset: number): Site;
37
+ /**
38
+ * The token an offset is inside, for a hover, which is not the same question.
39
+ *
40
+ * A completion is about what is being typed, so the token that ends at the
41
+ * cursor is the word. A hover is about what is under the pointer, so the token
42
+ * that contains the offset is the answer and one that merely ends there is not:
43
+ * pointing at the space after `ema` is not pointing at `ema`.
44
+ */
45
+ export declare function tokenOn(tokens: readonly Token[], offset: number): Token | undefined;
46
+ //# sourceMappingURL=site.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../../src/editor/site.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAGhE,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACvB,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AAED,oDAAoD;AACpD,MAAM,WAAW,IAAI;IACnB,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;CACrC;AA4HD;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAyBvF;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAKnF"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Where the cursor is, in the language's own terms.
3
+ *
4
+ * `complete` and `signature` both need the same three answers: what word is
5
+ * being typed, whether it follows a namespace and a dot, and which argument of
6
+ * which call it sits in. They are worked out once, here, because two copies of
7
+ * this would disagree on the day somebody fixes one of them.
8
+ *
9
+ * ## It reads tokens, not the tree
10
+ *
11
+ * A file being typed into is a file that does not parse: `ema(close, ` is the
12
+ * state a call is in for as long as it takes to write one, and it has no
13
+ * complete tree node for the parser to hand back. The tokens, on the other hand,
14
+ * are exactly what the writer has typed so far, and the real lexer produced
15
+ * them. So the enclosing call is found by walking bracket depth backwards over
16
+ * the token stream rather than by looking for a `Call` node that is not there
17
+ * yet.
18
+ *
19
+ * This is not a second parser. It asks one question the grammar already fixes,
20
+ * which bracket is still open, and it answers nothing else: what the call means,
21
+ * whether its arguments type check and whether the name exists are the checker's
22
+ * and are asked of the checker.
23
+ *
24
+ * **An unclosed bracket swallows the rest of the file**, and that is the
25
+ * compiler's reading too: a call opened on line 5 and never closed makes every
26
+ * line below it part of one unfinished statement, which is what the parser
27
+ * reports and what `diagnose-typing` in the benchmark suite measures. A special
28
+ * case here that stopped at the end of a line would give a writer a different
29
+ * answer from the diagnostics beside them.
30
+ */
31
+ import { endOffset } from '../core/index.js';
32
+ import { isReserved } from './kinds.js';
33
+ const OPENERS = new Set(['(', '[']);
34
+ const CLOSERS = new Set([')', ']']);
35
+ /** Whether a token is a word: a name, or a reserved word, which is also a word. */
36
+ function isWord(token) {
37
+ return token !== undefined && (token.kind === 'identifier' || isReserved(token.kind));
38
+ }
39
+ /**
40
+ * The tokens that end at or before an offset, and the one the offset is inside.
41
+ *
42
+ * A layout token is skipped: an `indent` covers a line's leading spaces and a
43
+ * `dedent` and the end of the file cover nothing, so none of them is ever the
44
+ * word somebody is typing, and a bracket scan that counted them would still be
45
+ * correct but a word scan that returned one would not.
46
+ */
47
+ function before(tokens, offset) {
48
+ const taken = [];
49
+ for (const token of tokens) {
50
+ if (token.span.offset >= offset)
51
+ break;
52
+ if (token.kind === 'newline' || token.kind === 'indent')
53
+ continue;
54
+ if (token.kind === 'dedent' || token.kind === 'endOfFile')
55
+ continue;
56
+ taken.push(token);
57
+ }
58
+ return taken;
59
+ }
60
+ /**
61
+ * The call whose bracket is still open at the cursor, and where in it.
62
+ *
63
+ * Walked forwards with a stack rather than backwards with a counter, because
64
+ * the answer wanted is the innermost frame that is still open and a stack is
65
+ * what that is. A square bracket counts too: `f(a[1], b` has the cursor in `f`'s
66
+ * second argument, and a scan that only knew round brackets would put it in the
67
+ * first.
68
+ */
69
+ function callAt(tokens, text) {
70
+ const stack = [];
71
+ for (let i = 0; i < tokens.length; i += 1) {
72
+ const token = tokens[i];
73
+ if (token === undefined)
74
+ continue;
75
+ if (OPENERS.has(token.kind)) {
76
+ stack.push({
77
+ open: token,
78
+ callee: calleeOf(tokens, i),
79
+ commas: 0,
80
+ label: undefined,
81
+ labels: [],
82
+ });
83
+ continue;
84
+ }
85
+ if (CLOSERS.has(token.kind)) {
86
+ stack.pop();
87
+ continue;
88
+ }
89
+ const frame = stack[stack.length - 1];
90
+ if (frame === undefined)
91
+ continue;
92
+ if (token.kind === ',') {
93
+ frame.commas += 1;
94
+ frame.label = undefined;
95
+ continue;
96
+ }
97
+ // `name =` is a label, and `name ==` is a comparison. The lexer has already
98
+ // told the two apart: they are different tokens.
99
+ if (token.kind === '=' && isWord(tokens[i - 1])) {
100
+ const label = tokens[i - 1];
101
+ if (label !== undefined) {
102
+ frame.label = label.text;
103
+ frame.labels.push(label.text);
104
+ }
105
+ }
106
+ }
107
+ const frame = stack[stack.length - 1];
108
+ if (frame === undefined || frame.open.kind !== '(' || frame.callee.length === 0) {
109
+ return undefined;
110
+ }
111
+ const first = frame.callee[0];
112
+ const last = frame.callee[frame.callee.length - 1];
113
+ if (first === undefined || last === undefined)
114
+ return undefined;
115
+ return {
116
+ name: text.slice(first.span.offset, endOffset(last.span)),
117
+ nameSpan: first.span,
118
+ argument: frame.commas,
119
+ label: frame.label,
120
+ labels: frame.labels,
121
+ open: frame.open.span,
122
+ };
123
+ }
124
+ /**
125
+ * The name in front of a bracket, as one or three tokens.
126
+ *
127
+ * A dotted name is `identifier . identifier` to the lexer, so a call to
128
+ * `draw.box` is found by reading back over the dot. A bracket with no name in
129
+ * front of it is a grouping or an array literal rather than a call, and this
130
+ * returns nothing for it.
131
+ */
132
+ function calleeOf(tokens, open) {
133
+ const name = tokens[open - 1];
134
+ if (!isWord(name) || name === undefined)
135
+ return [];
136
+ const dot = tokens[open - 2];
137
+ const namespace = tokens[open - 3];
138
+ if (dot?.kind === '.' && isWord(namespace) && namespace !== undefined) {
139
+ return [namespace, dot, name];
140
+ }
141
+ return [name];
142
+ }
143
+ /**
144
+ * Everything the two functions need to know about a position.
145
+ *
146
+ * The word is the token the offset is inside or immediately after, which is
147
+ * what a writer half way through typing a name has. A cursor sitting on a space
148
+ * has no word and an empty replacement span at the cursor, so a host inserts
149
+ * there rather than overwriting whatever is to the left.
150
+ */
151
+ export function siteAt(file, tokens, offset) {
152
+ const text = file.text;
153
+ const at = Math.min(Math.max(Math.trunc(offset), 0), text.length);
154
+ const taken = before(tokens, at);
155
+ const last = taken[taken.length - 1];
156
+ const touching = last !== undefined && endOffset(last.span) === at;
157
+ const word = touching && isWord(last) ? last : undefined;
158
+ // The dot is the token before the word being typed, or the last token when
159
+ // nothing has been typed after it yet.
160
+ const dot = word === undefined ? last : taken[taken.length - 2];
161
+ const holder = word === undefined ? taken[taken.length - 2] : taken[taken.length - 3];
162
+ const afterDot = dot?.kind === '.' && (word !== undefined || touching);
163
+ const namespace = afterDot && isWord(holder) ? holder?.text : undefined;
164
+ const scanned = word === undefined ? taken : taken.slice(0, -1);
165
+ return {
166
+ word: word?.text ?? '',
167
+ replace: word?.span ?? file.spanAt(at, 0),
168
+ namespace,
169
+ afterDot: afterDot === true,
170
+ call: callAt(scanned, text),
171
+ };
172
+ }
173
+ /**
174
+ * The token an offset is inside, for a hover, which is not the same question.
175
+ *
176
+ * A completion is about what is being typed, so the token that ends at the
177
+ * cursor is the word. A hover is about what is under the pointer, so the token
178
+ * that contains the offset is the answer and one that merely ends there is not:
179
+ * pointing at the space after `ema` is not pointing at `ema`.
180
+ */
181
+ export function tokenOn(tokens, offset) {
182
+ return tokens.find((token) => token.span.length > 0 && offset >= token.span.offset && offset < endOffset(token.span));
183
+ }
184
+ //# sourceMappingURL=site.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.js","sourceRoot":"","sources":["../../src/editor/site.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { Script, Token } from '../core/index.js';
2
+ /** The three questions the tree answers, as sets of source offsets. */
3
+ export interface Shapes {
4
+ /** Where a `+` or a `-` is a sign rather than an operator between two values. */
5
+ readonly signs: ReadonlySet<number>;
6
+ /** Where a `(` groups an expression, or a `[` opens an array literal. */
7
+ readonly grouped: ReadonlySet<number>;
8
+ /** Where a `:` separates the two arms of a ternary. */
9
+ readonly arms: ReadonlySet<number>;
10
+ }
11
+ /**
12
+ * Reads the three from a tree.
13
+ *
14
+ * A tree from a file that did not parse is not passed here: the formatter
15
+ * refuses such a file before this is reached, because a tree with recovery in it
16
+ * describes a program nobody wrote.
17
+ */
18
+ export declare function shapesOf(script: Script, tokens: readonly Token[]): Shapes;
19
+ /**
20
+ * Whether a space goes between two tokens that are printed on one line.
21
+ *
22
+ * The default is a space, and every rule below takes one away. That direction is
23
+ * deliberate: a missing space is almost always harmless to read and never
24
+ * changes what the lexer sees, and an added space between two marks that have to
25
+ * touch is the one mistake that changes a program. The arrow above is the only
26
+ * case where that could happen, and it is refused first.
27
+ */
28
+ export declare function spaceBetween(left: Token, right: Token, shapes: Shapes): boolean;
29
+ //# sourceMappingURL=spacing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spacing.d.ts","sourceRoot":"","sources":["../../src/editor/spacing.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEtD,uEAAuE;AACvE,MAAM,WAAW,MAAM;IACrB,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACpC;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CA6BzE;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CA4B/E"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * What goes between two tokens on a line, and how each rule is decided.
3
+ *
4
+ * A formatter's spacing is where a language tool usually starts guessing. The
5
+ * classic guess is the one every reprinter makes about a minus sign: it looks at
6
+ * the token before it and decides from a list of what can precede a binary
7
+ * operator. That list is a second, smaller grammar, it is wrong in a case
8
+ * nobody thought of, and being wrong means printing `a - -b` as `a--b` or
9
+ * `dir == -1` as `dir == - 1`.
10
+ *
11
+ * Nothing here guesses. Three questions cannot be answered by looking at two
12
+ * tokens, and all three are put to the parser, which has already answered them
13
+ * to build the tree:
14
+ *
15
+ * - **Is this minus a sign or a subtraction?** A `unary` node begins at its
16
+ * operator, so the tree names the offset of every sign in the file.
17
+ * - **Does this bracket open a call or group an expression?** A `grouping`
18
+ * node begins at its `(` and an `arrayLiteral` at its `[`. Every other
19
+ * bracket is an argument list, a parameter list or an index, which are the
20
+ * brackets that touch the name in front of them.
21
+ * - **Is this colon a ternary's or a type annotation's?** A `ternary` node
22
+ * carries the span of the arm before the colon, so the colon is the first
23
+ * one after it. Every other colon introduces a type.
24
+ *
25
+ * The rest is a table of marks, and it is small because the language is small.
26
+ */
27
+ import { endOffset, walk } from '../core/index.js';
28
+ /**
29
+ * Reads the three from a tree.
30
+ *
31
+ * A tree from a file that did not parse is not passed here: the formatter
32
+ * refuses such a file before this is reached, because a tree with recovery in it
33
+ * describes a program nobody wrote.
34
+ */
35
+ export function shapesOf(script, tokens) {
36
+ const colons = tokens.filter((token) => token.kind === ':').map((token) => token.span.offset);
37
+ const signs = new Set();
38
+ const grouped = new Set();
39
+ const arms = new Set();
40
+ walk(script, {
41
+ enter(node) {
42
+ switch (node.kind) {
43
+ case 'unary':
44
+ signs.add(node.span.offset);
45
+ return;
46
+ case 'grouping':
47
+ case 'arrayLiteral':
48
+ grouped.add(node.span.offset);
49
+ return;
50
+ case 'ternary': {
51
+ const after = endOffset(node.whenTrue.span);
52
+ const colon = colons.find((offset) => offset >= after);
53
+ if (colon !== undefined)
54
+ arms.add(colon);
55
+ return;
56
+ }
57
+ default:
58
+ return;
59
+ }
60
+ },
61
+ });
62
+ return { signs, grouped, arms };
63
+ }
64
+ /**
65
+ * Whether the arrow of a single-line `fn` is being written.
66
+ *
67
+ * `=>` is not one token. The punctuation table has `=` and `>` and no arrow, and
68
+ * the lexer reads the pair as one only while the two touch, which is why the
69
+ * form is recognised by the two tokens being adjacent rather than by a mark. A
70
+ * space between them turns a function declaration into an assignment followed by
71
+ * a comparison, so this is the one place a formatter may not insert one.
72
+ */
73
+ function isArrow(left, right) {
74
+ return (left.kind === '=' &&
75
+ right.kind === '>' &&
76
+ endOffset(left.span) === right.span.offset);
77
+ }
78
+ /**
79
+ * Whether a space goes between two tokens that are printed on one line.
80
+ *
81
+ * The default is a space, and every rule below takes one away. That direction is
82
+ * deliberate: a missing space is almost always harmless to read and never
83
+ * changes what the lexer sees, and an added space between two marks that have to
84
+ * touch is the one mistake that changes a program. The arrow above is the only
85
+ * case where that could happen, and it is refused first.
86
+ */
87
+ export function spaceBetween(left, right, shapes) {
88
+ if (isArrow(left, right))
89
+ return false;
90
+ // A sign belongs to the value it signs. `not` is a word and keeps its space:
91
+ // taking it away would spell a different name.
92
+ if (shapes.signs.has(left.span.offset) && (left.kind === '-' || left.kind === '+'))
93
+ return false;
94
+ // Inside a bracket, against the bracket.
95
+ if (left.kind === '(' || left.kind === '[')
96
+ return false;
97
+ if (right.kind === ')' || right.kind === ']')
98
+ return false;
99
+ // A comma belongs to the item before it.
100
+ if (right.kind === ',')
101
+ return false;
102
+ // A dotted name is one name to read, so it is printed as one.
103
+ if (left.kind === '.' || right.kind === '.')
104
+ return false;
105
+ // A bracket that is not grouping an expression is an argument list, a
106
+ // parameter list or an index, and all three touch what they are applied to.
107
+ if ((right.kind === '(' || right.kind === '[') && !shapes.grouped.has(right.span.offset)) {
108
+ return false;
109
+ }
110
+ // A type annotation's colon belongs to the name it follows. A ternary's has a
111
+ // space on both sides, which is what the default already gives it.
112
+ if (right.kind === ':' && !shapes.arms.has(right.span.offset))
113
+ return false;
114
+ return true;
115
+ }
116
+ //# sourceMappingURL=spacing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spacing.js","sourceRoot":"","sources":["../../src/editor/spacing.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openalgo-script",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "An open trading language. Write a study or a strategy once, plot it, backtest it, trade it.",
5
5
  "keywords": [
6
6
  "trading",
@@ -26,10 +26,18 @@
26
26
  "types": "./dist/core/index.d.ts",
27
27
  "import": "./dist/core/index.js"
28
28
  },
29
+ "./editor": {
30
+ "types": "./dist/editor/index.d.ts",
31
+ "import": "./dist/editor/index.js"
32
+ },
29
33
  "./adapters/charts": {
30
34
  "types": "./dist/adapters/charts/index.d.ts",
31
35
  "import": "./dist/adapters/charts/index.js"
32
36
  },
37
+ "./adapters/codemirror": {
38
+ "types": "./dist/adapters/codemirror/index.d.ts",
39
+ "import": "./dist/adapters/codemirror/index.js"
40
+ },
33
41
  "./package.json": "./package.json"
34
42
  },
35
43
  "files": [
@@ -51,8 +59,10 @@
51
59
  "check:raises": "node --disallow-code-generation-from-strings scripts/check-raises.mjs",
52
60
  "check:defaults": "npm run build && node --disallow-code-generation-from-strings scripts/check-defaults.mjs",
53
61
  "check:chart": "npm run build && node --disallow-code-generation-from-strings scripts/check-chart-surface.mjs",
62
+ "check:reproducible": "npm run build && node --disallow-code-generation-from-strings scripts/check-reproducible.mjs",
54
63
  "check:section-20": "node --disallow-code-generation-from-strings scripts/check-section-20.mjs",
55
- "test": "node --disallow-code-generation-from-strings scripts/check-duplication.mjs && node --disallow-code-generation-from-strings scripts/check-error-codes.mjs && node --disallow-code-generation-from-strings scripts/check-examples.mjs && node --disallow-code-generation-from-strings scripts/check-catalogue-tests.mjs && node --disallow-code-generation-from-strings scripts/check-layering.mjs && node --disallow-code-generation-from-strings scripts/check-limits.mjs && node --disallow-code-generation-from-strings scripts/check-modularity.mjs && node --disallow-code-generation-from-strings scripts/check-names.mjs && node --disallow-code-generation-from-strings scripts/check-raises.mjs && node --disallow-code-generation-from-strings scripts/check-section-20.mjs && npm run build && node --disallow-code-generation-from-strings scripts/check-defaults.mjs && node --disallow-code-generation-from-strings scripts/check-chart-surface.mjs && npm run test:unit && node --disallow-code-generation-from-strings scripts/check-examples-compile.mjs && node --disallow-code-generation-from-strings scripts/check-no-eval.mjs && npm run bench",
64
+ "check:entry-points": "npm run build && node --disallow-code-generation-from-strings scripts/check-entry-points.mjs",
65
+ "test": "node --disallow-code-generation-from-strings scripts/check-duplication.mjs && node --disallow-code-generation-from-strings scripts/check-error-codes.mjs && node --disallow-code-generation-from-strings scripts/check-examples.mjs && node --disallow-code-generation-from-strings scripts/check-catalogue-tests.mjs && node --disallow-code-generation-from-strings scripts/check-layering.mjs && node --disallow-code-generation-from-strings scripts/check-limits.mjs && node --disallow-code-generation-from-strings scripts/check-modularity.mjs && node --disallow-code-generation-from-strings scripts/check-names.mjs && node --disallow-code-generation-from-strings scripts/check-raises.mjs && node --disallow-code-generation-from-strings scripts/check-section-20.mjs && npm run build && node --disallow-code-generation-from-strings scripts/check-defaults.mjs && node --disallow-code-generation-from-strings scripts/check-entry-points.mjs && node --disallow-code-generation-from-strings scripts/check-chart-surface.mjs && npm run test:unit && node --disallow-code-generation-from-strings scripts/check-reproducible.mjs && node --disallow-code-generation-from-strings scripts/check-examples-compile.mjs && node --disallow-code-generation-from-strings scripts/check-no-eval.mjs && npm run bench",
56
66
  "test:unit": "npm run build:test && node --disallow-code-generation-from-strings scripts/run-tests.mjs",
57
67
  "check:layering": "node --disallow-code-generation-from-strings scripts/check-layering.mjs",
58
68
  "check:duplication": "node --disallow-code-generation-from-strings scripts/check-duplication.mjs",
@@ -64,7 +74,8 @@
64
74
  "build:test": "npm run generate && node --disallow-code-generation-from-strings scripts/clean-output.mjs tsconfig.test.json && tsc -p tsconfig.test.json",
65
75
  "prepack": "npm run build",
66
76
  "generate:version": "node --disallow-code-generation-from-strings scripts/generate-version.mjs",
67
- "generate": "npm run generate:errors && npm run generate:version",
77
+ "generate:library": "node --disallow-code-generation-from-strings scripts/generate-library-prose.mjs",
78
+ "generate": "npm run generate:errors && npm run generate:version && npm run generate:library",
68
79
  "check:changelog": "node --disallow-code-generation-from-strings scripts/check-changelog.mjs",
69
80
  "bench": "node --disallow-code-generation-from-strings scripts/bench.mjs",
70
81
  "bench:record": "node --disallow-code-generation-from-strings scripts/bench.mjs --record"
@@ -74,9 +85,25 @@
74
85
  },
75
86
  "dependencies": {},
76
87
  "peerDependencies": {
88
+ "@codemirror/autocomplete": ">=6.0.0",
89
+ "@codemirror/language": ">=6.0.0",
90
+ "@codemirror/lint": ">=6.0.0",
91
+ "@codemirror/view": ">=6.0.0",
77
92
  "openalgo-charts": ">=2.4.0"
78
93
  },
79
94
  "peerDependenciesMeta": {
95
+ "@codemirror/autocomplete": {
96
+ "optional": true
97
+ },
98
+ "@codemirror/language": {
99
+ "optional": true
100
+ },
101
+ "@codemirror/lint": {
102
+ "optional": true
103
+ },
104
+ "@codemirror/view": {
105
+ "optional": true
106
+ },
80
107
  "openalgo-charts": {
81
108
  "optional": true
82
109
  }