@gjsify/gtksource-nativescript 0.0.0-stage → 0.56.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/README.md +66 -2
- package/lib/esm/_virtual/_rolldown/runtime.js +1 -0
- package/lib/esm/android-types.js +0 -0
- package/lib/esm/buffer.js +5 -0
- package/lib/esm/builder.js +1 -0
- package/lib/esm/coerce.js +1 -0
- package/lib/esm/color.js +1 -0
- package/lib/esm/editor-driver.js +0 -0
- package/lib/esm/editor-session.js +2 -0
- package/lib/esm/fallback-schemes.js +2 -0
- package/lib/esm/gutter.js +1 -0
- package/lib/esm/highlight-controller.js +1 -0
- package/lib/esm/highlighter.js +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/language-manager.js +1 -0
- package/lib/esm/line-store.js +1 -0
- package/lib/esm/namespace/gtksource.js +1 -0
- package/lib/esm/native-editor.android.js +2 -0
- package/lib/esm/native-editor.js +1 -0
- package/lib/esm/signals.js +1 -0
- package/lib/esm/style-scheme.js +1 -0
- package/lib/esm/token-styler.js +1 -0
- package/lib/esm/view.js +1 -0
- package/lib/types/android-types.d.ts +108 -0
- package/lib/types/buffer.d.ts +64 -0
- package/lib/types/buffer.spec.d.ts +2 -0
- package/lib/types/builder.d.ts +1 -0
- package/lib/types/coerce.d.ts +2 -0
- package/lib/types/color.d.ts +6 -0
- package/lib/types/editor-driver.d.ts +38 -0
- package/lib/types/editor-session.d.ts +52 -0
- package/lib/types/editor-session.spec.d.ts +2 -0
- package/lib/types/fallback-schemes.d.ts +4 -0
- package/lib/types/fixtures.spec.d.ts +3 -0
- package/lib/types/gutter.d.ts +20 -0
- package/lib/types/gutter.spec.d.ts +2 -0
- package/lib/types/highlight-controller.d.ts +24 -0
- package/lib/types/highlighter.d.ts +33 -0
- package/lib/types/highlighter.spec.d.ts +2 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/language-manager.d.ts +31 -0
- package/lib/types/line-store.d.ts +9 -0
- package/lib/types/managers.spec.d.ts +2 -0
- package/lib/types/namespace/gtksource.d.ts +4 -0
- package/lib/types/native-editor.android.d.ts +2 -0
- package/lib/types/native-editor.d.ts +9 -0
- package/lib/types/signals.d.ts +7 -0
- package/lib/types/style-scheme.d.ts +51 -0
- package/lib/types/token-styler.d.ts +26 -0
- package/lib/types/view-tree.spec.d.ts +2 -0
- package/lib/types/view.d.ts +70 -0
- package/package.json +91 -5
package/README.md
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @gjsify/gtksource-nativescript
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`GtkSource.View` for NativeScript on Android: an `EditText` whose `Editable` carries the syntax
|
|
4
|
+
highlight as spans (set in place, re-tokenized per changed line range), a line-number gutter drawn
|
|
5
|
+
from the text `Layout` in `onDraw`, and `GtkSource.Buffer` / `LanguageManager` /
|
|
6
|
+
`StyleSchemeManager` over `@gjsify/gtksource-core`.
|
|
7
|
+
|
|
8
|
+
- No word wrap: every logical line is one layout line, the view scrolls horizontally.
|
|
9
|
+
- GtkSourceView's `Adwaita` scheme and `def.lang` are LGPL and not bundled. A small own stand-in is
|
|
10
|
+
registered under `Adwaita` / `Adwaita-dark`; add the real files with `addSchemeFromXml()`.
|
|
11
|
+
- `indent-width` is held and read back, not applied: an `EditText` has no indent step. Its only
|
|
12
|
+
Tab is a hardware key that inserts `\t`, and `tab-width` would need a `TabStopSpan` per line that
|
|
13
|
+
GtkSourceView does not tie to `indent-width`. `auto-indent` copies the previous line's blanks.
|
|
14
|
+
- The caret line's number is emphasised only under `highlight-current-line` (default false).
|
|
15
|
+
- Android API used (R8): the consuming app must keep `android.widget.EditText`, `android.text.*`
|
|
16
|
+
spans, `android.graphics.Paint`/`Typeface` in its `native-api-usage.json` whitelist. Shared
|
|
17
|
+
widget classes that come with `@gjsify/adwaita-nativescript` add `android.view.View`
|
|
18
|
+
(`setTooltipText`, API 26; duck-typed, no `TooltipCompat`) to that list.
|
|
19
|
+
- The platform half (`native-editor.android.ts`) is not verified on a device yet.
|
|
20
|
+
|
|
21
|
+
## Using it from XML
|
|
22
|
+
|
|
23
|
+
The package publishes the `GtkSource` namespace as a subpath, and an app re-exports it as its own
|
|
24
|
+
barrel, one barrel per library (see [docs/nativescript-xml.md](../../../docs/nativescript-xml.md)):
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// app/gtksource.ts
|
|
28
|
+
export * from '@gjsify/gtksource-nativescript/gtksource';
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```xml
|
|
32
|
+
<gtksource:View xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:gtksource="~/gtksource" />
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Using it from a `.blp`
|
|
36
|
+
|
|
37
|
+
A Blueprint file that says `GtkSource.View` builds on Android through the shared-tree builder of
|
|
38
|
+
`@gjsify/adwaita-nativescript`, the same file GNOME loads. Import the builder subpath once, for its
|
|
39
|
+
effect, beside the adwaita builder:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { build } from '@gjsify/adwaita-nativescript/builder';
|
|
43
|
+
import '@gjsify/gtksource-nativescript/builder'; // registers the `GtkSource` library
|
|
44
|
+
import tree from './source-view.blp?shared-tree';
|
|
45
|
+
|
|
46
|
+
const view = build(tree);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`@gjsify/adwaita-nativescript` is a dependency, not a peer: the build order follows production
|
|
50
|
+
dependencies only. Keep your app on the same version range, so the view and your app share one
|
|
51
|
+
colour-scheme state.
|
|
52
|
+
|
|
53
|
+
What a `.blp` can write: `GtkSource.View`, and `buffer: GtkSource.Buffer { text: "…";
|
|
54
|
+
highlight-syntax: false; };` as the view's `buffer` object child. `LanguageManager` and
|
|
55
|
+
`StyleSchemeManager` are singletons you ask for a `Language` / `StyleScheme`, and `.blp` cannot
|
|
56
|
+
call a method, so set `buffer.language` and `buffer.styleScheme` from code after building.
|
|
57
|
+
|
|
58
|
+
`Gtk.Button`'s `action-name` runs through a minimal `GAction` registry of
|
|
59
|
+
`@gjsify/adwaita-nativescript`: register a `Gio.SimpleAction` in a `Gio.SimpleActionGroup`, put the
|
|
60
|
+
group on an ancestor with `insertActionGroup('source-view', group)`, and a tap on a button whose
|
|
61
|
+
`action-name` is `source-view.copy` calls the action's `activate`. Parameter types, state,
|
|
62
|
+
`app.` / `win.` resolution and accelerators are not modelled.
|
|
63
|
+
|
|
64
|
+
`tooltip-text` also reaches Android's `View.setTooltipText` (long press, API 26) beside the
|
|
65
|
+
accessibility hint. `registerIcons({ 'edit-copy-symbolic': '…' })` registers a generated icon module
|
|
66
|
+
by GNOME name, so an icon-only `Gtk.Button` in a shared `.blp` finds its glyph; such a button wears
|
|
67
|
+
the `image-button` class and renders flat and unlabelled.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=Object.defineProperty,__name=(t,n)=>e(t,`name`,{value:n,configurable:!0}),__exportAll=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r};export{__exportAll,__name};
|
|
File without changes
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{SignalEmitter as e}from"./signals.js";var GtkSourceBuffer=class extends e{lines=[``];lineStarts=[0];startsValidTo=1;cursor=0;lang=null;scheme=null;highlight=!0;constructor(e=``){super();let{text:t=``,highlightSyntax:n=!0}=typeof e==`string`?{text:e}:e;t!==``&&(this.lines=t.split(`
|
|
2
|
+
`)),this.highlight=n!==!1&&String(n)!==`false`}get text(){return this.lines.join(`
|
|
3
|
+
`)}set text(e){this.replace(0,this.length,e??``),this.placeCursor(this.length)}get length(){return this.offsetOfLine(this.lines.length-1)+this.lines[this.lines.length-1].length}get lineCount(){return this.lines.length}getLine(e){let t=this.lines[e];if(t===void 0)throw RangeError(`Buffer: line ${e} is outside 0..${this.lines.length-1}`);return t}getLines(){return[...this.lines]}offsetOfLine(e){if(e<0||e>=this.lines.length)throw RangeError(`Buffer: line ${e} is outside 0..${this.lines.length-1}`);for(;this.startsValidTo<=e;){let e=this.startsValidTo-1;this.lineStarts[this.startsValidTo]=this.lineStarts[e]+this.lines[e].length+1,this.startsValidTo++}return this.lineStarts[e]}lineOfOffset(e){this.checkOffset(e);let t=0,n=this.lines.length-1;for(;t<n;){let r=t+n+1>>1;this.offsetOfLine(r)<=e?t=r:n=r-1}return t}getText(e=0,t=this.length){if(this.checkOffset(e),this.checkOffset(t),e>t)throw RangeError(`Buffer: range ${e}..${t} is reversed`);return this.text.slice(e,t)}insert(e,t){this.replace(e,e,t)}delete(e,t){this.replace(e,t,``)}replace(e,t,n){if(this.checkOffset(e),this.checkOffset(t),e>t)throw RangeError(`Buffer: range ${e}..${t} is reversed`);let r=this.lineOfOffset(e),i=this.lineOfOffset(t),a=this.offsetOfLine(r),o=this.offsetOfLine(i),s=this.lines.slice(r,i+1).join(`
|
|
4
|
+
`).slice(e-a,t-a);if(s===``&&n===``)return;let c=(this.lines[r].slice(0,e-a)+n+this.lines[i].slice(t-o)).split(`
|
|
5
|
+
`);this.lines.splice(r,i-r+1,...c),this.startsValidTo=Math.min(this.startsValidTo,r+1);let l=this.cursor;l>=t?this.cursor=l-s.length+n.length:l>e&&(this.cursor=e+n.length),this.emit(`changed`,{start:e,removedText:s,insertedText:n,firstLine:r,removedLines:i-r+1,insertedLines:c.length}),this.cursor!==l&&this.emitCursor()}get cursorPosition(){return this.cursor}placeCursor(e){this.checkOffset(e),e!==this.cursor&&(this.cursor=e,this.emitCursor())}emitCursor(){this.emit(`mark-set`,this.cursor,`insert`),this.emit(`notify::cursor-position`)}get language(){return this.lang}set language(e){e!==this.lang&&(this.lang=e,this.emit(`notify::language`))}get styleScheme(){return this.scheme}set styleScheme(e){e!==this.scheme&&(this.scheme=e,this.emit(`notify::style-scheme`))}get highlightSyntax(){return this.highlight}set highlightSyntax(e){e!==this.highlight&&(this.highlight=e,this.emit(`notify::highlight-syntax`))}checkOffset(e){if(!Number.isInteger(e)||e<0||e>this.length)throw RangeError(`Buffer: offset ${e} is outside 0..${this.length}`)}};export{GtkSourceBuffer as Buffer,GtkSourceBuffer};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{gtksource_exports as e}from"./namespace/gtksource.js";import{registerBarrel as t}from"@gjsify/adwaita-nativescript/builder";t(`gtksource`,`GtkSource`,e);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";function toBoolean(e,t){if(typeof e==`boolean`)return e;if(e===`true`)return!0;if(e===`false`)return!1;throw TypeError(`${t}: ${JSON.stringify(e)} is not a boolean`)}function toNumber(e,t){let n=typeof e==`string`&&e.trim()!==``?Number(e):e;if(typeof n!=`number`||!Number.isFinite(n))throw TypeError(`${t}: ${JSON.stringify(e)} is not a number`);return n}export{toBoolean,toNumber};
|
package/lib/esm/color.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";function parseColor(e){let t=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.exec(e.trim());if(!t)return;let n=t[1];n.length===3&&(n=[...n].map(e=>e+e).join(``)),n.length===6&&(n+=`ff`);let r=parseInt(n.slice(0,2),16),i=parseInt(n.slice(2,4),16),a=parseInt(n.slice(4,6),16);return parseInt(n.slice(6,8),16)<<24|r<<16|i<<8|a|0}export{parseColor};
|
|
File without changes
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{SignalEmitter as e}from"./signals.js";import{Buffer as t}from"./buffer.js";import{StyleSchemeManager as n}from"./style-scheme.js";import{HighlightController as r}from"./highlight-controller.js";function leadingWhitespace(e){return/^[ \t]*/.exec(e)[0]}var EditorSession=class extends e{driver;schemes;current;controller;bufferHandlers=[];mirroring=!1;fromNative=!1;variant;props={autoIndent:!1,indentWidth:-1,showLineNumbers:!1,monospace:!1,editable:!0,highlightCurrentLine:!1,leftMargin:0,rightMargin:0,topMargin:0,bottomMargin:0};constructor(e,r=n.getDefault(),i=`light`){super(),this.driver=e,this.schemes=r,this.variant=i,e.bind(this),this.attach(new t)}get buffer(){return this.current}set buffer(e){e!==this.current&&(this.attach(e),this.emit(`notify::buffer`))}attach(e){if(this.current){for(let e of this.bufferHandlers.splice(0))this.current.disconnect(e);this.controller.dispose()}this.current=e,this.bufferHandlers.push(e.connect(`changed`,(e,t)=>this.onBufferChanged(t)),e.connect(`mark-set`,(e,t)=>this.onBufferCursor(t))),this.mirroring=!0;try{this.driver.setText(e.text)}finally{this.mirroring=!1}this.controller=new r(e,this.driver,this.schemes,this.variant),this.driver.setLineCount(e.lineCount),this.driver.setSelection(e.cursorPosition,e.cursorPosition),this.pushLayout()}onBufferChanged(e){if(!this.fromNative){this.mirroring=!0;try{this.driver.replaceRange(e.start,e.start+e.removedText.length,e.insertedText)}finally{this.mirroring=!1}}e.insertedLines!==e.removedLines&&this.driver.setLineCount(this.current.lineCount)}onBufferCursor(e){this.fromNative||this.mirroring||this.driver.setSelection(e,e)}onNativeEdit(e,t,n){if(!this.mirroring){this.fromNative=!0;try{this.current.replace(e,e+t,n)}finally{this.fromNative=!1}if(this.props.autoIndent&&n===`
|
|
2
|
+
`){let t=leadingWhitespace(this.current.getLine(this.current.lineOfOffset(e)));t!==``&&(this.current.insert(e+1,t),this.driver.setSelection(this.current.cursorPosition,this.current.cursorPosition))}}}onNativeSelection(e,t){this.mirroring||this.current.placeCursor(Math.min(Math.max(0,t),this.current.length))}setProp(e,t,n){this.props[e]!==t&&(this.props[e]=t,this.emit(`notify::${n}`),this.pushLayout())}pushLayout(){let{props:e}=this;this.driver.setLayout({showLineNumbers:e.showLineNumbers,monospace:e.monospace,editable:e.editable,highlightCurrentLine:e.highlightCurrentLine,leftMargin:e.leftMargin,rightMargin:e.rightMargin,topMargin:e.topMargin,bottomMargin:e.bottomMargin})}get autoIndent(){return this.props.autoIndent}set autoIndent(e){this.setProp(`autoIndent`,e,`auto-indent`)}get indentWidth(){return this.props.indentWidth}set indentWidth(e){this.setProp(`indentWidth`,e,`indent-width`)}get showLineNumbers(){return this.props.showLineNumbers}set showLineNumbers(e){this.setProp(`showLineNumbers`,e,`show-line-numbers`)}get monospace(){return this.props.monospace}set monospace(e){this.setProp(`monospace`,e,`monospace`)}get editable(){return this.props.editable}set editable(e){this.setProp(`editable`,e,`editable`)}get highlightCurrentLine(){return this.props.highlightCurrentLine}set highlightCurrentLine(e){this.setProp(`highlightCurrentLine`,e,`highlight-current-line`)}get leftMargin(){return this.props.leftMargin}set leftMargin(e){this.setProp(`leftMargin`,e,`left-margin`)}get rightMargin(){return this.props.rightMargin}set rightMargin(e){this.setProp(`rightMargin`,e,`right-margin`)}get topMargin(){return this.props.topMargin}set topMargin(e){this.setProp(`topMargin`,e,`top-margin`)}get bottomMargin(){return this.props.bottomMargin}set bottomMargin(e){this.setProp(`bottomMargin`,e,`bottom-margin`)}setColorScheme(e){this.variant=e,this.controller.setColorScheme(e)}dispose(){for(let e of this.bufferHandlers.splice(0))this.current.disconnect(e);this.controller.dispose()}};export{EditorSession,leadingWhitespace};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";const scheme=(e,t,n)=>`<?xml version="1.0" encoding="UTF-8"?>\n<style-scheme id="${e}" name="${t}" version="1.0">\n${Object.entries(n).map(([e,t])=>` <style name="${e}" ${t}/>`).join(`
|
|
2
|
+
`)}\n</style-scheme>\n`,e=`Adwaita`,t=`Adwaita-dark`,n=scheme(e,`Adwaita (gjsify fallback)`,{text:`foreground="#2e3436" background="#ffffff"`,selection:`background="#a8c8f0"`,cursor:`foreground="#2e3436"`,"current-line":`background="#f0f0f0"`,"line-numbers":`foreground="#8a8f92" background="#f6f5f4"`,"current-line-number":`foreground="#2e3436" background="#f0f0f0"`,"def:comment":`foreground="#77767b" italic="true"`,"def:shebang":`foreground="#77767b" italic="true"`,"def:doc-comment-element":`foreground="#77767b" italic="true"`,"def:keyword":`foreground="#a51d2d" bold="true"`,"def:statement":`foreground="#a51d2d" bold="true"`,"def:preprocessor":`foreground="#813d9c"`,"def:type":`foreground="#1a5fb4"`,"def:builtin":`foreground="#1a5fb4"`,"def:function":`foreground="#1a5fb4"`,"def:identifier":`foreground="#1a5fb4"`,"def:constant":`foreground="#26a269"`,"def:number":`foreground="#26a269"`,"def:decimal":`foreground="#26a269"`,"def:base-n-integer":`foreground="#26a269"`,"def:floating-point":`foreground="#26a269"`,"def:boolean":`foreground="#26a269"`,"def:string":`foreground="#c64600"`,"def:character":`foreground="#c64600"`,"def:special-char":`foreground="#c64600" bold="true"`,"def:special-constant":`foreground="#c64600"`,"def:operator":`foreground="#5e5c64"`,"def:error":`foreground="#c01c28" underline="error"`,"def:note":`foreground="#813d9c" bold="true"`}),r=scheme(t,`Adwaita Dark (gjsify fallback)`,{text:`foreground="#ebebeb" background="#1e1e1e"`,selection:`background="#35516e"`,cursor:`foreground="#ebebeb"`,"current-line":`background="#2a2a2a"`,"line-numbers":`foreground="#8a8a8a" background="#242424"`,"current-line-number":`foreground="#ebebeb" background="#2a2a2a"`,"def:comment":`foreground="#9a9996" italic="true"`,"def:shebang":`foreground="#9a9996" italic="true"`,"def:doc-comment-element":`foreground="#9a9996" italic="true"`,"def:keyword":`foreground="#ff7b63" bold="true"`,"def:statement":`foreground="#ff7b63" bold="true"`,"def:preprocessor":`foreground="#dc8add"`,"def:type":`foreground="#78aeed"`,"def:builtin":`foreground="#78aeed"`,"def:function":`foreground="#78aeed"`,"def:identifier":`foreground="#78aeed"`,"def:constant":`foreground="#8ff0a4"`,"def:number":`foreground="#8ff0a4"`,"def:decimal":`foreground="#8ff0a4"`,"def:base-n-integer":`foreground="#8ff0a4"`,"def:floating-point":`foreground="#8ff0a4"`,"def:boolean":`foreground="#8ff0a4"`,"def:string":`foreground="#ffbe6f"`,"def:character":`foreground="#ffbe6f"`,"def:special-char":`foreground="#ffbe6f" bold="true"`,"def:special-constant":`foreground="#ffbe6f"`,"def:operator":`foreground="#c0bfbc"`,"def:error":`foreground="#ff7b63" underline="error"`,"def:note":`foreground="#dc8add" bold="true"`});export{t as FALLBACK_DARK_ID,e as FALLBACK_LIGHT_ID,r as fallbackDarkScheme,n as fallbackLightScheme};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";function digitCount(e,t=2){return Math.max(t,String(Math.max(1,e)).length)}function gutterWidth(e,t,n,r=2){return Math.ceil(digitCount(e,r)*t+2*n)}function visibleLines(e,t,n,r,i){if(e<=0)return null;let a=0,o=e-1;for(;a<o;){let e=a+o>>1;n(e)<=r?a=e+1:o=e}let s=a;if(t(s)>=i||n(s)<=r)return null;for(a=s,o=e-1;a<o;){let e=a+o+1>>1;t(e)<i?a=e:o=e-1}return{first:s,last:a}}function emphasisedLine(e,t){return e?t:-1}export{digitCount,emphasisedLine,gutterWidth,visibleLines};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{StyleSchemeManager as e,paletteOf as t}from"./style-scheme.js";import{IncrementalHighlighter as n}from"./highlighter.js";import{TokenStyler as r}from"./token-styler.js";var HighlightController=class{buffer;sink;schemes;highlighter=null;styler=null;variant;handlers=[];constructor(t,n,r=e.getDefault(),i=`light`){this.buffer=t,this.sink=n,this.schemes=r,this.variant=i,this.handlers.push(t.connect(`changed`,(e,t)=>this.onChanged(t)),t.connect(`notify::language`,()=>this.rebuild()),t.connect(`notify::style-scheme`,()=>this.rebuild()),t.connect(`notify::highlight-syntax`,()=>this.rebuild())),this.rebuild()}get scheme(){let e=this.buffer.styleScheme;return e?this.schemes.variantOf(e,this.variant):this.schemes.getDefaultFor(this.variant)}setColorScheme(e){e!==this.variant&&(this.variant=e,this.rebuild(!1))}dispose(){for(let e of this.handlers.splice(0))this.buffer.disconnect(e)}rebuild(e=!0){let i=this.scheme,a=this.buffer.language;if(i&&this.sink.setPalette(t(i,this.variant)),!a||!i||!this.buffer.highlightSyntax){this.highlighter=null,this.styler=null,this.sink.clearAll();return}(e||!this.highlighter||this.highlighter.tokenizer!==a.tokenizer)&&(this.highlighter=new n(a.tokenizer),this.highlighter.reset(this.buffer.getLines())),this.styler=new r(a.definition,i),this.paint(0,this.buffer.lineCount-1)}onChanged(e){if(this.sink.spliceLines(e.firstLine,e.removedLines,e.insertedLines),!this.highlighter)return;let t=this.highlighter.update(this.buffer.getLines(),{first:e.firstLine,removed:e.removedLines,inserted:e.insertedLines});this.paint(t.first,t.last)}paint(e,t){let{highlighter:n,styler:r}=this;if(!(!n||!r))for(let i=e;i<=t;i++)this.sink.paintLine(i,this.buffer.offsetOfLine(i),r.runsOf(n.tokensOf(i)))}};export{HighlightController};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{INITIAL_STATE as e}from"@gjsify/gtksource-core";function sameState(e,t){return e.stack.length===t.stack.length?e.stack.every((e,n)=>e===t.stack[n]):!1}var IncrementalHighlighter=class{tokenizer;results=[];constructor(e){this.tokenizer=e}get lineCount(){return this.results.length}tokensOf(e){let t=this.results[e];if(!t)throw RangeError(`IncrementalHighlighter: line ${e} is outside 0..${this.results.length-1}`);return t.tokens}reset(t){this.results=[];let n=e;for(let e of t){let t=this.tokenizer.tokenize(e,n);this.results.push(t),n=t.state}return t.length===0?null:{first:0,last:t.length-1}}update(t,n){let{first:r,removed:i,inserted:a}=n;if(r<0||i<1||a<1||r+i>this.results.length)throw RangeError(`IncrementalHighlighter: edit ${JSON.stringify(n)} does not fit ${this.results.length} lines`);if(t.length!==this.results.length-i+a)throw RangeError(`IncrementalHighlighter: ${t.length} lines do not match the edit`);let o=this.results[r+i-1].state,s=Array.from({length:a},()=>void 0);this.results.splice(r,i,...s);let c=r,l=r===0?e:this.results[r-1].state;for(;c<r+a;c++){let e=this.tokenizer.tokenize(t[c],l);this.results[c]=e,l=e.state}let u=r+a-1;for(;!sameState(l,o)&&c<t.length;){o=this.results[c].state;let e=this.tokenizer.tokenize(t[c],l);this.results[c]=e,l=e.state,u=c,c++}return{first:r,last:u}}};export{IncrementalHighlighter,sameState};
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{paletteOf as e}from"./style-scheme.js";import{gtksource_exports as t}from"./namespace/gtksource.js";export{t as GtkSource,e as paletteOf};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Tokenizer as e,parseLanguage as t}from"@gjsify/gtksource-core";const splitList=e=>(e??``).split(`;`).map(e=>e.trim()).filter(e=>e!==``);function globMatches(e,t){let n=e.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`.*`).replace(/\?/g,`.`);return RegExp(`^${n}$`).test(t)}var Language=class{definition;cached;constructor(e){this.definition=e}get id(){return this.definition.id}get name(){return this.definition.name??this.definition.id}get section(){return this.definition.section??`Others`}get globs(){return splitList(this.definition.metadata.globs)}get mimeTypes(){return splitList(this.definition.metadata.mimetypes)}get tokenizer(){return this.cached??=new e(this.definition)}},n=class LanguageManager{static instance;static getDefault(){return LanguageManager.instance??=new LanguageManager}languages=new Map;get languageIds(){return[...this.languages.keys()].sort()}addLanguageFromXml(e,n={}){let r=new Language(t(e,n));return this.languages.set(r.id,r),r}getLanguage(e){return this.languages.get(e)??null}guessLanguage(e,t){let n=[...this.languages.values()].sort((e,t)=>e.id.localeCompare(t.id));if(e!==null){let t=e.slice(Math.max(e.lastIndexOf(`/`),e.lastIndexOf(`\\`))+1),r=n.find(e=>e.globs.some(e=>globMatches(e,t)));if(r)return r}return t===null?null:n.find(e=>e.mimeTypes.includes(t))??null}};export{Language,n as LanguageManager};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";var LineStore=class{slots=[];get(e){return this.slots[e]}set(e,t){for(;this.slots.length<=e;)this.slots.push(void 0);this.slots[e]=t}splice(e,t,n){for(;this.slots.length<e+t;)this.slots.push(void 0);return this.slots.splice(e,t,...Array.from({length:n},()=>void 0)).filter(e=>e!==void 0)}clear(){let e=this.slots.filter(e=>e!==void 0);return this.slots=[],e}};export{LineStore};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{__exportAll as e}from"../_virtual/_rolldown/runtime.js";import{Buffer as t}from"../buffer.js";import{Language as n,LanguageManager as r}from"../language-manager.js";import{StyleScheme as i,StyleSchemeManager as a}from"../style-scheme.js";import{GtkSourceView as o}from"../view.js";var s=e({Buffer:()=>t,Language:()=>n,LanguageManager:()=>r,StyleScheme:()=>i,StyleSchemeManager:()=>a,View:()=>o});export{t as Buffer,n as Language,r as LanguageManager,i as StyleScheme,a as StyleSchemeManager,o as View,s as gtksource_exports};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{emphasisedLine as e,gutterWidth as t,visibleLines as n}from"./gutter.js";import{LineStore as r}from"./line-store.js";let i;function gutterEditText(){return i||(i=android.widget.EditText.extend({onDraw(e){let t=this.driver;t?.drawBehind(this,e),this.super.onDraw(e),t?.drawGutter(this,e)},onSelectionChanged(e,t){this.super.onSelectionChanged(e,t),this.driver?.selectionChanged(e,t)}}),i)}var AndroidEditorDriver=class{host=null;view=null;applying=!1;queue=[];keyListener=null;pendingText=``;selection={start:0,end:0};lineCount=1;layout=null;palette=null;runs=new r;spans=new r;fillPaint=null;textPaint=null;bind(e){this.host=e}createNativeView(e){let t=new(gutterEditText())(e);return t.driver=this,t}attach(e){let t=e;this.view=t,t.setInputType(android.text.InputType.TYPE_CLASS_TEXT|android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE|android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS),t.setHorizontallyScrolling(!0),t.setGravity(android.view.Gravity.TOP|android.view.Gravity.START),this.keyListener=t.getKeyListener(),t.addTextChangedListener(new android.text.TextWatcher({beforeTextChanged:()=>{},onTextChanged:(e,t,n,r)=>{this.applying||this.queue.push({start:t,removed:n,inserted:e.subSequence(t,t+r).toString()})},afterTextChanged:()=>this.flushEdits()})),this.applyLayout(),this.applyPalette(),this.applying=!0;try{t.setText(this.pendingText??``)}finally{this.applying=!1}this.pendingText=null,this.repaintAll(),this.applySelection()}detach(){this.view&&(this.pendingText=this.view.getText().toString()),this.view=null,this.spans.clear(),this.queue=[]}setText(e){if(this.removeAllSpans(),this.runs.clear(),!this.view){this.pendingText=e;return}this.applying=!0;try{this.view.setText(e)}finally{this.applying=!1}}replaceRange(e,t,n){let r=this.view;if(!r){let r=this.pendingText??``;this.pendingText=r.slice(0,e)+n+r.slice(t);return}let i=r.getText();this.applying=!0;try{i.replace(e,Math.min(t,i.length()),n)}finally{this.applying=!1}}setSelection(e,t){this.selection={start:e,end:t},this.applySelection()}setLineCount(e){this.lineCount=e,this.view&&this.layout?.showLineNumbers&&this.applyLayout()}setLayout(e){this.layout=e,this.applyLayout()}setPalette(e){this.palette=e,this.applyPalette()}spliceLines(e,t,n){let r=this.view?.getText();for(let i of this.spans.splice(e,t,n))if(r)for(let e of i)r.removeSpan(e);this.runs.splice(e,t,n)}paintLine(e,t,n){this.runs.set(e,n);let r=this.view?.getText();r&&this.applyRuns(r,e,t,n)}clearAll(){this.removeAllSpans(),this.runs.clear()}removeAllSpans(){let e=this.view?.getText(),t=this.spans.clear();if(e)for(let n of t)for(let t of n)e.removeSpan(t)}repaintAll(){let e=this.view?.getText();if(!e)return;let t=e.toString().split(`
|
|
2
|
+
`),n=0;t.forEach((t,r)=>{let i=this.runs.get(r);i&&this.applyRuns(e,r,n,i),n+=t.length+1})}applyRuns(e,t,n,r){for(let n of this.spans.get(t)??[])e.removeSpan(n);let i=e.length(),a=android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,{ForegroundColorSpan:o,BackgroundColorSpan:s,StyleSpan:c,UnderlineSpan:l,StrikethroughSpan:u}=android.text.style,d=android.graphics.Typeface,f=[],put=(t,n,r)=>{e.setSpan(t,n,r,a),f.push(t)};for(let e of r){let t=n+e.start,r=Math.min(n+e.end,i);if(t>=r)continue;let{style:a}=e;a.foreground!==void 0&&put(new o(a.foreground),t,r),a.background!==void 0&&put(new s(a.background),t,r),(a.bold||a.italic)&&put(new c(a.bold&&a.italic?d.BOLD_ITALIC:a.bold?d.BOLD:d.ITALIC),t,r),a.underline&&put(new l,t,r),a.strikethrough&&put(new u,t,r)}this.spans.set(t,f)}density(e){return e.getResources().getDisplayMetrics().density}gutterPixels(e){if(!this.layout?.showLineNumbers)return 0;let n=8*this.density(e);return t(this.lineCount,this.paintFor(e).measureText(`0`),n)}paintFor(e){return this.textPaint??=new android.graphics.Paint(1),this.textPaint.setTextSize(e.getTextSize()),this.textPaint.setTypeface(e.getTypeface()),this.textPaint.setTextAlign(android.graphics.Paint.Align.RIGHT),this.textPaint}applyLayout(){let e=this.view,t=this.layout;if(!e||!t)return;e.setTypeface(t.monospace?android.graphics.Typeface.MONOSPACE:android.graphics.Typeface.DEFAULT);let n=this.density(e);e.setPadding(Math.round(t.leftMargin*n)+this.gutterPixels(e),Math.round(t.topMargin*n),Math.round(t.rightMargin*n),Math.round(t.bottomMargin*n)),e.setKeyListener(t.editable?this.keyListener:null),e.setCursorVisible(t.editable),e.invalidate()}applyPalette(){let e=this.view,t=this.palette;!e||!t||(e.setBackgroundColor(t.background),e.setTextColor(t.foreground),e.setHighlightColor(t.selectionBackground),e.invalidate())}applySelection(){let e=this.view;if(!e)return;let t=e.getText().length(),n=Math.min(this.selection.start,t);e.getSelectionStart()===n&&e.getSelectionEnd()===Math.min(this.selection.end,t)||e.setSelection(n,Math.min(this.selection.end,t))}flushEdits(){let e=this.view,t=this.host;if(this.applying||!e||!t||this.queue.length===0)return;let n=this.queue;this.queue=[];for(let e of n)t.onNativeEdit(e.start,e.removed,e.inserted);t.onNativeSelection(e.getSelectionStart(),e.getSelectionEnd())}selectionChanged(e,t){this.applying||this.queue.length>0||(this.selection={start:e,end:t},this.host?.onNativeSelection(e,t),this.view?.invalidate())}fill(e,t,n,r,i,a){this.fillPaint??=new android.graphics.Paint(0),this.fillPaint.setColor(t),e.drawRect(n,r,i,a,this.fillPaint)}drawBehind(e,t){let n=this.palette,r=e.getLayout();if(!n||!r||!this.layout?.highlightCurrentLine||n.currentLineBackground===0)return;let i=r.getLineForOffset(e.getSelectionEnd()),a=e.getExtendedPaddingTop();this.fill(t,n.currentLineBackground,e.getScrollX(),a+r.getLineTop(i),e.getScrollX()+e.getWidth(),a+r.getLineBottom(i))}drawGutter(r,i){let a=this.palette,o=r.getLayout();if(!a||!o||!this.layout?.showLineNumbers)return;let s=this.paintFor(r),c=8*this.density(r),l=t(o.getLineCount(),s.measureText(`0`),c),u=r.getScrollX(),d=r.getScrollY(),f=r.getExtendedPaddingTop();this.fill(i,a.lineNumberBackground,u,d,u+l,d+r.getHeight());let p=n(o.getLineCount(),e=>f+o.getLineTop(e),e=>f+o.getLineBottom(e),d,d+r.getHeight());if(!p)return;let m=e(this.layout.highlightCurrentLine,o.getLineForOffset(r.getSelectionEnd()));for(let e=p.first;e<=p.last;e++){let t=e===m;t&&a.currentLineNumberBackground!==0&&this.fill(i,a.currentLineNumberBackground,u,f+o.getLineTop(e),u+l,f+o.getLineBottom(e)),s.setColor(t?a.currentLineNumberForeground:a.lineNumberForeground),i.drawText(String(e+1),u+l-c,f+o.getLineBaseline(e),s)}}};function createEditorDriver(){return new AndroidEditorDriver}export{createEditorDriver};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";var UnsupportedEditorDriver=class{bind(e){}createNativeView(){throw Error(`Platform not supported: GtkSource.View is implemented for Android only`)}attach(){}detach(){}setText(){}replaceRange(){}setSelection(){}setLineCount(){}setLayout(){}spliceLines(){}paintLine(){}clearAll(){}setPalette(){}};function createEditorDriver(){return new UnsupportedEditorDriver}export{createEditorDriver};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";let e=1;var SignalEmitter=class{handlers=new Map;connect(t,n){let r=e++;return this.handlers.set(r,{name:t,callback:n}),r}disconnect(e){if(!this.handlers.delete(e))throw Error(`No signal handler with id ${e} on this object`)}emit(e,...t){for(let n of Array.from(this.handlers.values()))n.name===e&&n.callback(this,...t)}};export{SignalEmitter};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{parseColor as e}from"./color.js";import{FALLBACK_DARK_ID as t,FALLBACK_LIGHT_ID as n,fallbackDarkScheme as r,fallbackLightScheme as i}from"./fallback-schemes.js";import{parseStyleScheme as a,resolveStyle as o}from"@gjsify/gtksource-core";var StyleScheme=class{definition;lookup;constructor(e,t){this.definition=e,this.lookup=t}get id(){return this.definition.id}get name(){return this.definition.name??this.definition.id}get parentId(){return this.definition.parentScheme}getStyle(e){return o(this.definition,e,this.lookup)}};const s={foreground:-13749194,background:-1,selection:-5715728,lineNumber:-7696494},c={foreground:-1315861,background:-14803426,selection:-13282962,lineNumber:-7697782};function paletteOf(t,n){let r=n===`dark`?c:s,color=t=>t===void 0?void 0:e(t),i=t.getStyle(`text`),a=t.getStyle(`selection`),o=t.getStyle(`current-line`),l=t.getStyle(`line-numbers`),u=t.getStyle(`current-line-number`),d=color(i?.foreground)??r.foreground,f=color(i?.background)??r.background,p=color(l?.foreground)??r.lineNumber,m=color(l?.background)??f,h=color(o?.background)??0;return{dark:n===`dark`,foreground:d,background:f,selectionBackground:color(a?.background)??r.selection,currentLineBackground:h,lineNumberForeground:p,lineNumberBackground:m,currentLineNumberForeground:color(u?.foreground)??d,currentLineNumberBackground:color(u?.background)??h}}var l=class StyleSchemeManager{static instance;static getDefault(){return StyleSchemeManager.instance??=new StyleSchemeManager}definitions=new Map;fallbacks=new Set;constructor(e=!0){if(e)for(let e of[i,r]){let t=a(e);this.definitions.set(t.id,t),this.fallbacks.add(t.id)}}get schemeIds(){return[...this.definitions.keys()].sort()}isFallback(e){return this.fallbacks.has(e)}addScheme(e){return this.definitions.set(e.id,e),this.fallbacks.delete(e.id),this.wrap(e)}addSchemeFromXml(e){return this.addScheme(a(e))}getScheme(e){let t=this.definitions.get(e);return t?this.wrap(t):null}getDefaultFor(e){return this.getScheme(e===`dark`?t:n)}variantOf(e,t){let n=e.id.endsWith(`-dark`);if(n===(t===`dark`))return e;let r=n?e.id.slice(0,-5):`${e.id}-dark`;return this.getScheme(r)??e}wrap(e){return new StyleScheme(e,e=>this.definitions.get(e))}};export{StyleScheme,l as StyleSchemeManager,paletteOf};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{parseColor as e}from"./color.js";import{schemeStyleName as t}from"@gjsify/gtksource-core";var TokenStyler=class{language;scheme;cache=new Map;constructor(e,t){this.language=e,this.scheme=t}styleFor(n){if(this.cache.has(n))return this.cache.get(n);let r=this.scheme.getStyle(t(this.language,n)),i;if(r){let t=r.foreground===void 0?void 0:e(r.foreground),n=r.background===void 0?void 0:e(r.background),a=r.underline!==void 0&&r.underline!==`none`,o=r.bold===!0,s=r.italic===!0,c=r.strikethrough===!0;(t!==void 0||n!==void 0||o||s||a||c)&&(i={foreground:t,background:n,bold:o,italic:s,underline:a,strikethrough:c})}return this.cache.set(n,i),i}runsOf(e){let t=[];for(let n of e){let e=this.styleFor(n.style);e&&n.end>n.start&&t.push({start:n.start,end:n.end,style:e})}return t}};export{TokenStyler};
|
package/lib/esm/view.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{Buffer as e}from"./buffer.js";import{toBoolean as t,toNumber as n}from"./coerce.js";import{EditorSession as r}from"./editor-session.js";import{createEditorDriver as i}from"./native-editor.js";import{View as a}from"@nativescript/core";import{adwaitaColorScheme as o,onAdwaitaColorSchemeChanged as s,withGtkWidgetLayout as c}from"@gjsify/adwaita-nativescript";var GtkSourceView=class extends c(a){static builderSlots=[`buffer`];driver=i();session;unsubscribe=null;constructor(){super(),this.className=`gtksource-view`,this.session=new r(this.driver,void 0,o())}createNativeView(){return this.driver.createNativeView(this._context)}initNativeView(){super.initNativeView(),this.driver.attach(this.nativeViewProtected),this.unsubscribe=s(()=>this.session.setColorScheme(o())),this.session.setColorScheme(o())}disposeNativeView(){this.unsubscribe?.(),this.unsubscribe=null,this.driver.detach(),super.disposeNativeView()}_addChildFromBuilder(t,n){if(t!==`buffer`||!(n instanceof e))throw Error(`GtkSource.View takes only a \`buffer\` object child, not '${t}'.`);this.buffer=n}get buffer(){return this.session.buffer}set buffer(e){this.session.buffer=e}get autoIndent(){return this.session.autoIndent}set autoIndent(e){this.session.autoIndent=t(e,`GtkSource.View.autoIndent`)}get indentWidth(){return this.session.indentWidth}set indentWidth(e){this.session.indentWidth=n(e,`GtkSource.View.indentWidth`)}get showLineNumbers(){return this.session.showLineNumbers}set showLineNumbers(e){this.session.showLineNumbers=t(e,`GtkSource.View.showLineNumbers`)}get highlightCurrentLine(){return this.session.highlightCurrentLine}set highlightCurrentLine(e){this.session.highlightCurrentLine=t(e,`GtkSource.View.highlightCurrentLine`)}get monospace(){return this.session.monospace}set monospace(e){this.session.monospace=t(e,`GtkSource.View.monospace`)}get editable(){return this.session.editable}set editable(e){this.session.editable=t(e,`GtkSource.View.editable`)}get leftMargin(){return this.session.leftMargin}set leftMargin(e){this.session.leftMargin=n(e,`GtkSource.View.leftMargin`)}get rightMargin(){return this.session.rightMargin}set rightMargin(e){this.session.rightMargin=n(e,`GtkSource.View.rightMargin`)}get topMargin(){return this.session.topMargin}set topMargin(e){this.session.topMargin=n(e,`GtkSource.View.topMargin`)}get bottomMargin(){return this.session.bottomMargin}set bottomMargin(e){this.session.bottomMargin=n(e,`GtkSource.View.bottomMargin`)}connect(e,t){return this.session.connect(e,t)}disconnect(e){this.session.disconnect(e)}};export{GtkSourceView};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export interface AndroidCharSequence {
|
|
2
|
+
toString(): string;
|
|
3
|
+
subSequence(start: number, end: number): AndroidCharSequence;
|
|
4
|
+
}
|
|
5
|
+
export interface AndroidEditable extends AndroidCharSequence {
|
|
6
|
+
length(): number;
|
|
7
|
+
replace(start: number, end: number, text: string): AndroidEditable;
|
|
8
|
+
setSpan(what: unknown, start: number, end: number, flags: number): void;
|
|
9
|
+
removeSpan(what: unknown): void;
|
|
10
|
+
}
|
|
11
|
+
export interface AndroidCanvas {
|
|
12
|
+
drawRect(left: number, top: number, right: number, bottom: number, paint: AndroidPaint): void;
|
|
13
|
+
drawText(text: string, x: number, y: number, paint: AndroidPaint): void;
|
|
14
|
+
}
|
|
15
|
+
export interface AndroidPaint {
|
|
16
|
+
setColor(color: number): void;
|
|
17
|
+
setTextSize(size: number): void;
|
|
18
|
+
setTypeface(typeface: unknown): unknown;
|
|
19
|
+
setTextAlign(align: unknown): void;
|
|
20
|
+
measureText(text: string): number;
|
|
21
|
+
}
|
|
22
|
+
export interface AndroidLayout {
|
|
23
|
+
getLineCount(): number;
|
|
24
|
+
getLineTop(line: number): number;
|
|
25
|
+
getLineBottom(line: number): number;
|
|
26
|
+
getLineBaseline(line: number): number;
|
|
27
|
+
getLineForOffset(offset: number): number;
|
|
28
|
+
}
|
|
29
|
+
export interface AndroidEditText {
|
|
30
|
+
driver?: object;
|
|
31
|
+
getText(): AndroidEditable;
|
|
32
|
+
setText(text: string): void;
|
|
33
|
+
getLayout(): AndroidLayout | null;
|
|
34
|
+
getScrollX(): number;
|
|
35
|
+
getScrollY(): number;
|
|
36
|
+
getWidth(): number;
|
|
37
|
+
getHeight(): number;
|
|
38
|
+
getSelectionStart(): number;
|
|
39
|
+
getSelectionEnd(): number;
|
|
40
|
+
getExtendedPaddingTop(): number;
|
|
41
|
+
getTextSize(): number;
|
|
42
|
+
getTypeface(): unknown;
|
|
43
|
+
getResources(): {
|
|
44
|
+
getDisplayMetrics(): {
|
|
45
|
+
density: number;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
getKeyListener(): unknown;
|
|
49
|
+
setKeyListener(listener: unknown): void;
|
|
50
|
+
setSelection(start: number, end: number): void;
|
|
51
|
+
setHorizontallyScrolling(enabled: boolean): void;
|
|
52
|
+
setGravity(gravity: number): void;
|
|
53
|
+
setInputType(type: number): void;
|
|
54
|
+
setBackgroundColor(color: number): void;
|
|
55
|
+
setTextColor(color: number): void;
|
|
56
|
+
setHighlightColor(color: number): void;
|
|
57
|
+
setTypeface(typeface: unknown): void;
|
|
58
|
+
setPadding(left: number, top: number, right: number, bottom: number): void;
|
|
59
|
+
setCursorVisible(visible: boolean): void;
|
|
60
|
+
addTextChangedListener(watcher: unknown): void;
|
|
61
|
+
removeTextChangedListener(watcher: unknown): void;
|
|
62
|
+
invalidate(): void;
|
|
63
|
+
}
|
|
64
|
+
export interface AndroidNamespace {
|
|
65
|
+
widget: {
|
|
66
|
+
EditText: new (context: unknown) => AndroidEditText & {
|
|
67
|
+
onDraw(canvas: AndroidCanvas): void;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
graphics: {
|
|
71
|
+
Paint: (new (flags: number) => AndroidPaint) & {
|
|
72
|
+
Align: {
|
|
73
|
+
RIGHT: unknown;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
Typeface: {
|
|
77
|
+
MONOSPACE: unknown;
|
|
78
|
+
DEFAULT: unknown;
|
|
79
|
+
BOLD: number;
|
|
80
|
+
ITALIC: number;
|
|
81
|
+
BOLD_ITALIC: number;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
text: {
|
|
85
|
+
InputType: {
|
|
86
|
+
TYPE_CLASS_TEXT: number;
|
|
87
|
+
TYPE_TEXT_FLAG_MULTI_LINE: number;
|
|
88
|
+
TYPE_TEXT_FLAG_NO_SUGGESTIONS: number;
|
|
89
|
+
};
|
|
90
|
+
TextWatcher: new (implementation: object) => unknown;
|
|
91
|
+
Spanned: {
|
|
92
|
+
SPAN_EXCLUSIVE_EXCLUSIVE: number;
|
|
93
|
+
};
|
|
94
|
+
style: {
|
|
95
|
+
ForegroundColorSpan: new (color: number) => unknown;
|
|
96
|
+
BackgroundColorSpan: new (color: number) => unknown;
|
|
97
|
+
StyleSpan: new (style: number) => unknown;
|
|
98
|
+
UnderlineSpan: new () => unknown;
|
|
99
|
+
StrikethroughSpan: new () => unknown;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
view: {
|
|
103
|
+
Gravity: {
|
|
104
|
+
TOP: number;
|
|
105
|
+
START: number;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Language } from './language-manager.js';
|
|
2
|
+
import { SignalEmitter } from './signals.js';
|
|
3
|
+
import type { StyleScheme } from './style-scheme.js';
|
|
4
|
+
/** What `changed` carries: one contiguous replacement. */
|
|
5
|
+
export interface TextEdit {
|
|
6
|
+
readonly start: number;
|
|
7
|
+
readonly removedText: string;
|
|
8
|
+
readonly insertedText: string;
|
|
9
|
+
/** The lines `[firstLine, firstLine + removedLines)` of the old text became `insertedLines` lines. */
|
|
10
|
+
readonly firstLine: number;
|
|
11
|
+
readonly removedLines: number;
|
|
12
|
+
readonly insertedLines: number;
|
|
13
|
+
}
|
|
14
|
+
/** What a `.blp` may construct a buffer with: `buffer: GtkSource.Buffer { text: "…"; }`. */
|
|
15
|
+
export interface BufferProps {
|
|
16
|
+
text?: string;
|
|
17
|
+
highlightSyntax?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare class GtkSourceBuffer extends SignalEmitter {
|
|
20
|
+
private lines;
|
|
21
|
+
/** `lineStarts[i]` is the offset of line `i`; valid for `i < startsValidTo`. */
|
|
22
|
+
private lineStarts;
|
|
23
|
+
private startsValidTo;
|
|
24
|
+
private cursor;
|
|
25
|
+
private lang;
|
|
26
|
+
private scheme;
|
|
27
|
+
private highlight;
|
|
28
|
+
constructor(init?: string | BufferProps);
|
|
29
|
+
get text(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Replaces everything. Like `gtk_text_buffer_set_text` — a delete and an insert — the
|
|
32
|
+
* insert mark ends after the new text, so the cursor lands at the end.
|
|
33
|
+
*/
|
|
34
|
+
set text(value: string);
|
|
35
|
+
get length(): number;
|
|
36
|
+
get lineCount(): number;
|
|
37
|
+
/** Line `index` without its terminator. */
|
|
38
|
+
getLine(index: number): string;
|
|
39
|
+
/** A copy of every line. */
|
|
40
|
+
getLines(): string[];
|
|
41
|
+
offsetOfLine(index: number): number;
|
|
42
|
+
lineOfOffset(offset: number): number;
|
|
43
|
+
getText(start?: number, end?: number): string;
|
|
44
|
+
insert(offset: number, text: string): void;
|
|
45
|
+
delete(start: number, end: number): void;
|
|
46
|
+
/** The one mutation every other one goes through. An edit that changes nothing emits nothing. */
|
|
47
|
+
replace(start: number, end: number, text: string): void;
|
|
48
|
+
/** `GtkTextBuffer:cursor-position`. */
|
|
49
|
+
get cursorPosition(): number;
|
|
50
|
+
/** Moves the insert mark; emits `mark-set` and `notify::cursor-position` when it moved. */
|
|
51
|
+
placeCursor(offset: number): void;
|
|
52
|
+
private emitCursor;
|
|
53
|
+
/** `GtkSource.Buffer:language` — what to highlight with; `null` highlights nothing. */
|
|
54
|
+
get language(): Language | null;
|
|
55
|
+
set language(value: Language | null);
|
|
56
|
+
/** `GtkSource.Buffer:style-scheme`; `null` lets the view pick one for the light/dark mode. */
|
|
57
|
+
get styleScheme(): StyleScheme | null;
|
|
58
|
+
set styleScheme(value: StyleScheme | null);
|
|
59
|
+
/** `GtkSource.Buffer:highlight-syntax`, on by default. */
|
|
60
|
+
get highlightSyntax(): boolean;
|
|
61
|
+
set highlightSyntax(value: boolean);
|
|
62
|
+
private checkOffset;
|
|
63
|
+
}
|
|
64
|
+
export { GtkSourceBuffer as Buffer };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `#rgb`, `#rrggbb` and `#rrggbbaa` (CSS puts the alpha LAST: Learn6502's `#00000018` is a
|
|
3
|
+
* barely-there black). Anything else — named colours, `rgb()` — is `undefined`; a scheme
|
|
4
|
+
* that uses them loses that colour rather than crashing the editor.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseColor(value: string): number | undefined;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { EditorPalette } from './style-scheme.js';
|
|
2
|
+
import type { StyledRun } from './token-styler.js';
|
|
3
|
+
/** What the driver reports back. Offsets are UTF-16 code units, valid AFTER the edit. */
|
|
4
|
+
export interface EditorHost {
|
|
5
|
+
/** The user replaced `removedLength` characters at `start` with `inserted`. */
|
|
6
|
+
onNativeEdit(start: number, removedLength: number, inserted: string): void;
|
|
7
|
+
onNativeSelection(start: number, end: number): void;
|
|
8
|
+
}
|
|
9
|
+
export interface EditorLayout {
|
|
10
|
+
readonly showLineNumbers: boolean;
|
|
11
|
+
readonly monospace: boolean;
|
|
12
|
+
readonly editable: boolean;
|
|
13
|
+
readonly highlightCurrentLine: boolean;
|
|
14
|
+
/** The `left-margin` … `bottom-margin` of `Gtk.TextView`, in device-independent pixels. */
|
|
15
|
+
readonly leftMargin: number;
|
|
16
|
+
readonly rightMargin: number;
|
|
17
|
+
readonly topMargin: number;
|
|
18
|
+
readonly bottomMargin: number;
|
|
19
|
+
}
|
|
20
|
+
/** Where highlighted runs go. Spans live on the text, so they follow lines through edits. */
|
|
21
|
+
export interface HighlightSink {
|
|
22
|
+
/** Lines `[first, first + removed)` were replaced by `inserted` lines; drop what they carried. */
|
|
23
|
+
spliceLines(first: number, removed: number, inserted: number): void;
|
|
24
|
+
/** Replace everything painted on `line` (which starts at `lineStart`) with `runs`. */
|
|
25
|
+
paintLine(line: number, lineStart: number, runs: readonly StyledRun[]): void;
|
|
26
|
+
clearAll(): void;
|
|
27
|
+
setPalette(palette: EditorPalette): void;
|
|
28
|
+
}
|
|
29
|
+
export interface EditorDriver extends HighlightSink {
|
|
30
|
+
bind(host: EditorHost): void;
|
|
31
|
+
/** Replaces the whole text and forgets every span: the buffer was swapped. */
|
|
32
|
+
setText(text: string): void;
|
|
33
|
+
/** Mirrors a programmatic edit into the widget's text. */
|
|
34
|
+
replaceRange(start: number, end: number, text: string): void;
|
|
35
|
+
setSelection(start: number, end: number): void;
|
|
36
|
+
setLineCount(count: number): void;
|
|
37
|
+
setLayout(layout: EditorLayout): void;
|
|
38
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Buffer } from './buffer.js';
|
|
2
|
+
import type { EditorDriver, EditorHost } from './editor-driver.js';
|
|
3
|
+
import { StyleSchemeManager } from './style-scheme.js';
|
|
4
|
+
import type { ColorSchemeVariant } from './style-scheme.js';
|
|
5
|
+
import { SignalEmitter } from './signals.js';
|
|
6
|
+
/** The leading blanks of `line`: what `auto-indent` carries onto the next line. */
|
|
7
|
+
export declare function leadingWhitespace(line: string): string;
|
|
8
|
+
export declare class EditorSession extends SignalEmitter implements EditorHost {
|
|
9
|
+
private readonly driver;
|
|
10
|
+
private readonly schemes;
|
|
11
|
+
private current;
|
|
12
|
+
private controller;
|
|
13
|
+
private readonly bufferHandlers;
|
|
14
|
+
private mirroring;
|
|
15
|
+
private fromNative;
|
|
16
|
+
private variant;
|
|
17
|
+
private props;
|
|
18
|
+
constructor(driver: EditorDriver, schemes?: StyleSchemeManager, variant?: ColorSchemeVariant);
|
|
19
|
+
get buffer(): Buffer;
|
|
20
|
+
set buffer(value: Buffer);
|
|
21
|
+
private attach;
|
|
22
|
+
private onBufferChanged;
|
|
23
|
+
private onBufferCursor;
|
|
24
|
+
onNativeEdit(start: number, removedLength: number, inserted: string): void;
|
|
25
|
+
onNativeSelection(_start: number, end: number): void;
|
|
26
|
+
private setProp;
|
|
27
|
+
private pushLayout;
|
|
28
|
+
get autoIndent(): boolean;
|
|
29
|
+
set autoIndent(value: boolean);
|
|
30
|
+
/** Held and read back; Android has no Tab key to apply it to (see the package README). */
|
|
31
|
+
get indentWidth(): number;
|
|
32
|
+
set indentWidth(value: number);
|
|
33
|
+
get showLineNumbers(): boolean;
|
|
34
|
+
set showLineNumbers(value: boolean);
|
|
35
|
+
get monospace(): boolean;
|
|
36
|
+
set monospace(value: boolean);
|
|
37
|
+
get editable(): boolean;
|
|
38
|
+
set editable(value: boolean);
|
|
39
|
+
get highlightCurrentLine(): boolean;
|
|
40
|
+
set highlightCurrentLine(value: boolean);
|
|
41
|
+
get leftMargin(): number;
|
|
42
|
+
set leftMargin(value: number);
|
|
43
|
+
get rightMargin(): number;
|
|
44
|
+
set rightMargin(value: number);
|
|
45
|
+
get topMargin(): number;
|
|
46
|
+
set topMargin(value: number);
|
|
47
|
+
get bottomMargin(): number;
|
|
48
|
+
set bottomMargin(value: number);
|
|
49
|
+
/** Re-tints for the light/dark change; the tokens are kept. */
|
|
50
|
+
setColorScheme(variant: ColorSchemeVariant): void;
|
|
51
|
+
dispose(): void;
|
|
52
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const sixAssemblerLang = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<language id=\"6502-assembler\" name=\"6502 Assembler\" version=\"2.0\" _section=\"Source\">\n <metadata>\n <property name=\"mimetypes\">text/x-asm;text/x-assembler</property>\n <property name=\"globs\">*.asm;*.s</property>\n <property name=\"line-comment-start\">;</property>\n </metadata>\n\n <styles>\n <style id=\"comment\" name=\"Comment\" map-to=\"def:comment\"/>\n <style id=\"string\" name=\"String\" map-to=\"def:string\"/>\n <style id=\"preprocessor\" name=\"Preprocessor\" map-to=\"def:preprocessor\"/>\n <style id=\"instruction\" name=\"Instruction\" map-to=\"def:keyword\"/>\n <style id=\"number\" name=\"Number\" map-to=\"def:number\"/>\n <style id=\"constant\" name=\"Constant\" map-to=\"def:constant\"/>\n <style id=\"operator\" name=\"Operator\" map-to=\"def:operator\"/>\n <style id=\"label\" name=\"Label\" map-to=\"def:type\"/>\n <style id=\"variable\" name=\"Variable\" map-to=\"def:identifier\"/>\n </styles>\n \n <definitions>\n <context id=\"6502-assembler\">\n <include>\n <!-- Comments -->\n <context id=\"comment\" style-ref=\"comment\">\n <start>;</start>\n <end>$</end>\n </context>\n \n <!-- Strings -->\n <context id=\"string\" style-ref=\"string\" end-at-line-end=\"true\">\n <start>\"</start>\n <end>\"</end>\n <include>\n <context id=\"escape\" style-ref=\"def:special-char\">\n <match>\\\\.</match>\n </context>\n </include>\n </context>\n \n <!-- Numbers -->\n <context id=\"number\" style-ref=\"number\">\n <match extended=\"true\">\n (\\$[0-9a-fA-F]+\\b)|\n (\\@[0-1]+\\b)|\n (\\b[0-9]+\\b)\n </match>\n </context>\n \n <!-- Instructions -->\n <context id=\"instructions\" style-ref=\"instruction\">\n <keyword>LDA</keyword>\n <keyword>lda</keyword>\n <keyword>LDX</keyword>\n <keyword>ldx</keyword>\n <keyword>LDY</keyword>\n <keyword>ldy</keyword>\n <keyword>STA</keyword>\n <keyword>sta</keyword>\n <keyword>STX</keyword>\n <keyword>stx</keyword>\n <keyword>STY</keyword>\n <keyword>sty</keyword>\n <keyword>TXA</keyword>\n <keyword>txa</keyword>\n <keyword>TAX</keyword>\n <keyword>tax</keyword>\n <keyword>TYA</keyword>\n <keyword>tya</keyword>\n <keyword>TAY</keyword>\n <keyword>tay</keyword>\n <keyword>TXS</keyword>\n <keyword>txs</keyword>\n <keyword>TSX</keyword>\n <keyword>tsx</keyword>\n <keyword>ADC</keyword>\n <keyword>adc</keyword>\n <keyword>SBC</keyword>\n <keyword>sbc</keyword>\n <keyword>INC</keyword>\n <keyword>inc</keyword>\n <keyword>DEC</keyword>\n <keyword>dec</keyword>\n <keyword>INX</keyword>\n <keyword>inx</keyword>\n <keyword>DEX</keyword>\n <keyword>dex</keyword>\n <keyword>INY</keyword>\n <keyword>iny</keyword>\n <keyword>DEY</keyword>\n <keyword>dey</keyword>\n <keyword>AND</keyword>\n <keyword>and</keyword>\n <keyword>ORA</keyword>\n <keyword>ora</keyword>\n <keyword>EOR</keyword>\n <keyword>eor</keyword>\n <keyword>CLC</keyword>\n <keyword>clc</keyword>\n <keyword>SEC</keyword>\n <keyword>sec</keyword>\n <keyword>CLD</keyword>\n <keyword>cld</keyword>\n <keyword>SED</keyword>\n <keyword>sed</keyword>\n <keyword>CLV</keyword>\n <keyword>clv</keyword>\n <keyword>CLI</keyword>\n <keyword>cli</keyword>\n <keyword>SEI</keyword>\n <keyword>sei</keyword>\n <keyword>CMP</keyword>\n <keyword>cmp</keyword>\n <keyword>CPX</keyword>\n <keyword>cpx</keyword>\n <keyword>CPY</keyword>\n <keyword>cpy</keyword>\n <keyword>BIT</keyword>\n <keyword>bit</keyword>\n <keyword>ASL</keyword>\n <keyword>asl</keyword>\n <keyword>LSR</keyword>\n <keyword>lsr</keyword>\n <keyword>ROL</keyword>\n <keyword>rol</keyword>\n <keyword>ROR</keyword>\n <keyword>ror</keyword>\n <keyword>PHA</keyword>\n <keyword>pha</keyword>\n <keyword>PLA</keyword>\n <keyword>pla</keyword>\n <keyword>PHP</keyword>\n <keyword>php</keyword>\n <keyword>PLP</keyword>\n <keyword>plp</keyword>\n <keyword>JMP</keyword>\n <keyword>jmp</keyword>\n <keyword>JSR</keyword>\n <keyword>jsr</keyword>\n <keyword>NOP</keyword>\n <keyword>nop</keyword>\n <keyword>BEQ</keyword>\n <keyword>beq</keyword>\n <keyword>BNE</keyword>\n <keyword>bne</keyword>\n <keyword>BCS</keyword>\n <keyword>bcs</keyword>\n <keyword>BCC</keyword>\n <keyword>bcc</keyword>\n <keyword>BMI</keyword>\n <keyword>bmi</keyword>\n <keyword>BPL</keyword>\n <keyword>bpl</keyword>\n <keyword>BVS</keyword>\n <keyword>bvs</keyword>\n <keyword>BVC</keyword>\n <keyword>bvc</keyword>\n <keyword>RTS</keyword>\n <keyword>rts</keyword>\n <keyword>RTI</keyword>\n <keyword>rti</keyword>\n <keyword>BRK</keyword>\n <keyword>brk</keyword>\n </context>\n \n <!-- Preprocessor directives -->\n <context id=\"preprocessor\" style-ref=\"preprocessor\">\n <prefix>^\\s*\\.</prefix>\n <keyword>BASE</keyword>\n <keyword>ORG</keyword>\n <keyword>DEF</keyword>\n <keyword>IF</keyword>\n <keyword>INCLUDE</keyword>\n <keyword>INCBIN</keyword>\n <keyword>ELSEIF</keyword>\n <keyword>ELSE</keyword>\n <keyword>ENDIF</keyword>\n <keyword>IFDEF</keyword>\n <keyword>IFNDEF</keyword>\n <keyword>DB</keyword>\n <keyword>DW</keyword>\n <keyword>DBG</keyword>\n <keyword>DWG</keyword>\n <keyword>ENDD</keyword>\n <keyword>REPEAT</keyword>\n <keyword>ENDR</keyword>\n <keyword>MACRO</keyword>\n <keyword>ENDM</keyword>\n <keyword>MSG</keyword>\n <keyword>HEX</keyword>\n </context>\n\n <!-- Define constants -->\n <context id=\"define-constant\" style-ref=\"constant\">\n <match>^\\s*(define)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s+(.+)$</match>\n <include>\n <context sub-pattern=\"1\" style-ref=\"preprocessor\"/>\n <context sub-pattern=\"2\" style-ref=\"variable\"/>\n </include>\n </context>\n\n <!-- Operators -->\n <context id=\"operator\" style-ref=\"operator\">\n <match>[\\+\\-\\*\\/\\>\\<\\(\\)\\,\\#\\=\\!\\[\\]]</match>\n </context>\n\n <!-- Labels -->\n <context id=\"label\" style-ref=\"label\">\n <match>^[a-zA-Z_][a-zA-Z0-9_]*:</match>\n </context>\n\n <!-- Variables -->\n <context id=\"variable\" style-ref=\"variable\">\n <match>[a-zA-Z_][a-zA-Z0-9_]*</match>\n </context>\n </include>\n </context>\n </definitions>\n</language>";
|
|
2
|
+
export declare const learnStyle = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<style-scheme id=\"Learn6502\" _name=\"Learn6502\" parent-scheme=\"Adwaita\" version=\"1.0\">\n <!--\n Only override current line background; inherit everything else from Adwaita\n Docs:\n - https://gnome.pages.gitlab.gnome.org/gtksourceview/gtksourceview5/style-reference.html\n -->\n <style name=\"current-line\" background=\"#00000018\"/>\n <style name=\"current-line-number\" background=\"#00000018\"/>\n</style-scheme>\n";
|
|
3
|
+
export declare const learnStyleDark = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<style-scheme id=\"Learn6502-dark\" _name=\"Learn6502 Dark\" parent-scheme=\"Adwaita-dark\" version=\"1.0\">\n <!--\n Only override current line background; inherit everything else from Adwaita-dark\n Docs:\n - https://gnome.pages.gitlab.gnome.org/gtksourceview/gtksourceview5/style-reference.html\n -->\n <style name=\"current-line\" background=\"#ffffff10\"/>\n <style name=\"current-line-number\" background=\"#ffffff10\"/>\n</style-scheme>\n";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Digits needed to write `lineCount`; never fewer than `minDigits`, so a 9-line file does not jitter at line 10. */
|
|
2
|
+
export declare function digitCount(lineCount: number, minDigits?: number): number;
|
|
3
|
+
/** Total gutter width in pixels: the widest label plus padding on both sides. */
|
|
4
|
+
export declare function gutterWidth(lineCount: number, digitWidth: number, padding: number, minDigits?: number): number;
|
|
5
|
+
/**
|
|
6
|
+
* The lines whose vertical extent meets `[viewTop, viewBottom)`, found by binary search over
|
|
7
|
+
* the layout's line tops so a 10 000-line file draws the ~40 labels it shows, not 10 000.
|
|
8
|
+
* `lineBottom(i)` is the bottom edge of line `i`; both edges are in the same pixel space as
|
|
9
|
+
* the view range. `null` when nothing is visible.
|
|
10
|
+
*/
|
|
11
|
+
export declare function visibleLines(lineCount: number, lineTop: (line: number) => number, lineBottom: (line: number) => number, viewTop: number, viewBottom: number): {
|
|
12
|
+
first: number;
|
|
13
|
+
last: number;
|
|
14
|
+
} | null;
|
|
15
|
+
/**
|
|
16
|
+
* The line whose number carries the `current-line-number` style, or `-1`. The style rides on
|
|
17
|
+
* `highlight-current-line`: that property defaults to false, so a read-only snippet's first
|
|
18
|
+
* line (where the caret rests at offset 0) must not look picked out.
|
|
19
|
+
*/
|
|
20
|
+
export declare function emphasisedLine(highlightCurrentLine: boolean, caretLine: number): number;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Buffer } from './buffer.js';
|
|
2
|
+
import type { HighlightSink } from './editor-driver.js';
|
|
3
|
+
import { StyleSchemeManager } from './style-scheme.js';
|
|
4
|
+
import type { ColorSchemeVariant, StyleScheme } from './style-scheme.js';
|
|
5
|
+
export declare class HighlightController {
|
|
6
|
+
private readonly buffer;
|
|
7
|
+
private readonly sink;
|
|
8
|
+
private readonly schemes;
|
|
9
|
+
private highlighter;
|
|
10
|
+
private styler;
|
|
11
|
+
private variant;
|
|
12
|
+
private readonly handlers;
|
|
13
|
+
constructor(buffer: Buffer, sink: HighlightSink, schemes?: StyleSchemeManager, variant?: ColorSchemeVariant);
|
|
14
|
+
/** The scheme actually in force: the buffer's (its other-mode sibling when one exists), else the default. */
|
|
15
|
+
get scheme(): StyleScheme | null;
|
|
16
|
+
setColorScheme(variant: ColorSchemeVariant): void;
|
|
17
|
+
dispose(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Full repaint. `retokenize` is false for a pure re-tint: the tokens did not change, only what they look like.
|
|
20
|
+
*/
|
|
21
|
+
private rebuild;
|
|
22
|
+
private onChanged;
|
|
23
|
+
private paint;
|
|
24
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { LineState, Token, Tokenizer } from '@gjsify/gtksource-core';
|
|
2
|
+
/** Lines `first..last`, both inclusive. */
|
|
3
|
+
export interface LineRange {
|
|
4
|
+
readonly first: number;
|
|
5
|
+
readonly last: number;
|
|
6
|
+
}
|
|
7
|
+
/** `lines[first .. first + removed)` of the old text are now `lines[first .. first + inserted)`. */
|
|
8
|
+
export interface LineEdit {
|
|
9
|
+
readonly first: number;
|
|
10
|
+
readonly removed: number;
|
|
11
|
+
readonly inserted: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Two line states are the same when the same span contexts are open. The tokenizer hands out
|
|
15
|
+
* the same node object for the same context every time (its candidate lists are cached), so
|
|
16
|
+
* identity is the right comparison; if it ever returned fresh nodes this would only cost
|
|
17
|
+
* speed — the propagation would run to the end of the document — never correctness.
|
|
18
|
+
*/
|
|
19
|
+
export declare function sameState(a: LineState, b: LineState): boolean;
|
|
20
|
+
export declare class IncrementalHighlighter {
|
|
21
|
+
readonly tokenizer: Tokenizer;
|
|
22
|
+
private results;
|
|
23
|
+
constructor(tokenizer: Tokenizer);
|
|
24
|
+
get lineCount(): number;
|
|
25
|
+
tokensOf(line: number): readonly Token[];
|
|
26
|
+
/** Tokenizes the whole text; returns the range now valid, `null` for no lines. */
|
|
27
|
+
reset(lines: readonly string[]): LineRange | null;
|
|
28
|
+
/**
|
|
29
|
+
* Applies one line edit. `lines` is the NEW full text, already edited. Returns the lines
|
|
30
|
+
* whose tokens were recomputed — the ones a renderer must repaint.
|
|
31
|
+
*/
|
|
32
|
+
update(lines: readonly string[], edit: LineEdit): LineRange;
|
|
33
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LanguageDefinition } from '@gjsify/gtksource-core';
|
|
2
|
+
import { Tokenizer } from '@gjsify/gtksource-core';
|
|
3
|
+
export declare class Language {
|
|
4
|
+
readonly definition: LanguageDefinition;
|
|
5
|
+
private cached;
|
|
6
|
+
constructor(definition: LanguageDefinition);
|
|
7
|
+
get id(): string;
|
|
8
|
+
get name(): string;
|
|
9
|
+
get section(): string;
|
|
10
|
+
get globs(): string[];
|
|
11
|
+
get mimeTypes(): string[];
|
|
12
|
+
/** Built on first use: compiling every pattern is the expensive part of loading a language. */
|
|
13
|
+
get tokenizer(): Tokenizer;
|
|
14
|
+
}
|
|
15
|
+
export declare class LanguageManager {
|
|
16
|
+
private static instance;
|
|
17
|
+
/** `GtkSource.LanguageManager.get_default()`. */
|
|
18
|
+
static getDefault(): LanguageManager;
|
|
19
|
+
private readonly languages;
|
|
20
|
+
get languageIds(): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Parses and registers a `.lang` file. Constructs the core does not model land in
|
|
23
|
+
* `language.definition.unsupported`; pass `strict` to throw on them instead.
|
|
24
|
+
*/
|
|
25
|
+
addLanguageFromXml(xml: string, options?: {
|
|
26
|
+
strict?: boolean;
|
|
27
|
+
}): Language;
|
|
28
|
+
getLanguage(id: string): Language | null;
|
|
29
|
+
/** `gtk_source_language_manager_guess_language()`: by file name first, then by content type. */
|
|
30
|
+
guessLanguage(filename: string | null, contentType: string | null): Language | null;
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class LineStore<T> {
|
|
2
|
+
private slots;
|
|
3
|
+
get(line: number): T | undefined;
|
|
4
|
+
set(line: number, value: T | undefined): void;
|
|
5
|
+
/** Returns the values that were dropped, so the caller can release what they hold. */
|
|
6
|
+
splice(first: number, removed: number, inserted: number): T[];
|
|
7
|
+
/** Empties every slot and returns the values that were held. */
|
|
8
|
+
clear(): T[];
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EditorDriver } from './editor-driver.js';
|
|
2
|
+
export interface NativeEditorDriver extends EditorDriver {
|
|
3
|
+
/** Called from `createNativeView()` with the Android `Context`. */
|
|
4
|
+
createNativeView(context: unknown): unknown;
|
|
5
|
+
/** The view `createNativeView()` returned is live: apply everything remembered so far. */
|
|
6
|
+
attach(nativeView: unknown): void;
|
|
7
|
+
detach(): void;
|
|
8
|
+
}
|
|
9
|
+
export declare function createEditorDriver(): NativeEditorDriver;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class SignalEmitter {
|
|
2
|
+
private readonly handlers;
|
|
3
|
+
connect(name: string, callback: (self: this, ...args: never[]) => void): number;
|
|
4
|
+
/** Removes exactly the handler `connect` returned this id for; an id nothing holds throws. */
|
|
5
|
+
disconnect(id: number): void;
|
|
6
|
+
protected emit(name: string, ...args: unknown[]): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ResolvedStyle, StyleSchemeDefinition } from '@gjsify/gtksource-core';
|
|
2
|
+
export type ColorSchemeVariant = 'light' | 'dark';
|
|
3
|
+
export declare class StyleScheme {
|
|
4
|
+
readonly definition: StyleSchemeDefinition;
|
|
5
|
+
private readonly lookup;
|
|
6
|
+
constructor(definition: StyleSchemeDefinition, lookup: (id: string) => StyleSchemeDefinition | undefined);
|
|
7
|
+
get id(): string;
|
|
8
|
+
get name(): string;
|
|
9
|
+
get parentId(): string | undefined;
|
|
10
|
+
/** `text`, `line-numbers`, `def:keyword`, …; throws on a parent-scheme loop or a missing parent. */
|
|
11
|
+
getStyle(name: string): ResolvedStyle | undefined;
|
|
12
|
+
}
|
|
13
|
+
/** The colours the view itself paints — everything that is not a syntax token. ARGB ints. */
|
|
14
|
+
export interface EditorPalette {
|
|
15
|
+
readonly dark: boolean;
|
|
16
|
+
readonly foreground: number;
|
|
17
|
+
readonly background: number;
|
|
18
|
+
readonly selectionBackground: number;
|
|
19
|
+
readonly currentLineBackground: number;
|
|
20
|
+
readonly lineNumberForeground: number;
|
|
21
|
+
readonly lineNumberBackground: number;
|
|
22
|
+
readonly currentLineNumberForeground: number;
|
|
23
|
+
readonly currentLineNumberBackground: number;
|
|
24
|
+
}
|
|
25
|
+
/** Reads the palette off a scheme; a style the scheme (and its parents) lack takes a neutral default. */
|
|
26
|
+
export declare function paletteOf(scheme: StyleScheme, variant: ColorSchemeVariant): EditorPalette;
|
|
27
|
+
export declare class StyleSchemeManager {
|
|
28
|
+
private static instance;
|
|
29
|
+
/** `GtkSource.StyleSchemeManager.get_default()`. */
|
|
30
|
+
static getDefault(): StyleSchemeManager;
|
|
31
|
+
private readonly definitions;
|
|
32
|
+
private readonly fallbacks;
|
|
33
|
+
/** @param withFallbacks register this package's own `Adwaita`/`Adwaita-dark` stand-ins. */
|
|
34
|
+
constructor(withFallbacks?: boolean);
|
|
35
|
+
get schemeIds(): string[];
|
|
36
|
+
/** Whether `id` is still this package's stand-in rather than a scheme the consumer supplied. */
|
|
37
|
+
isFallback(id: string): boolean;
|
|
38
|
+
/** Adds a scheme, replacing one with the same id (that is how the real Adwaita replaces the stand-in). */
|
|
39
|
+
addScheme(definition: StyleSchemeDefinition): StyleScheme;
|
|
40
|
+
addSchemeFromXml(xml: string): StyleScheme;
|
|
41
|
+
getScheme(id: string): StyleScheme | null;
|
|
42
|
+
/** The scheme to use when nothing was chosen: the stand-in or real `Adwaita` / `Adwaita-dark`. */
|
|
43
|
+
getDefaultFor(variant: ColorSchemeVariant): StyleScheme | null;
|
|
44
|
+
/**
|
|
45
|
+
* The same scheme for the other mode, found by the `<id>-dark` naming convention
|
|
46
|
+
* (`Learn6502` / `Learn6502-dark`). `scheme` itself when it already is the asked variant
|
|
47
|
+
* or has no sibling — never a guess across unrelated schemes.
|
|
48
|
+
*/
|
|
49
|
+
variantOf(scheme: StyleScheme, variant: ColorSchemeVariant): StyleScheme;
|
|
50
|
+
private wrap;
|
|
51
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { LanguageDefinition, Token } from '@gjsify/gtksource-core';
|
|
2
|
+
import type { StyleScheme } from './style-scheme.js';
|
|
3
|
+
/** What one run of text looks like. Colours are signed ARGB ints. */
|
|
4
|
+
export interface RunStyle {
|
|
5
|
+
readonly foreground?: number;
|
|
6
|
+
readonly background?: number;
|
|
7
|
+
readonly bold: boolean;
|
|
8
|
+
readonly italic: boolean;
|
|
9
|
+
readonly underline: boolean;
|
|
10
|
+
readonly strikethrough: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** `[start, end)` within one line. */
|
|
13
|
+
export interface StyledRun {
|
|
14
|
+
readonly start: number;
|
|
15
|
+
readonly end: number;
|
|
16
|
+
readonly style: RunStyle;
|
|
17
|
+
}
|
|
18
|
+
export declare class TokenStyler {
|
|
19
|
+
private readonly language;
|
|
20
|
+
private readonly scheme;
|
|
21
|
+
private readonly cache;
|
|
22
|
+
constructor(language: LanguageDefinition, scheme: StyleScheme);
|
|
23
|
+
/** `undefined` when the scheme gives the style nothing to paint: the run keeps the text colour. */
|
|
24
|
+
styleFor(tokenStyle: string): RunStyle | undefined;
|
|
25
|
+
runsOf(tokens: readonly Token[]): StyledRun[];
|
|
26
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { View as NsView } from '@nativescript/core';
|
|
2
|
+
import { type Buffer } from './buffer.js';
|
|
3
|
+
declare const GtkSourceView_base: (abstract new (...args: any[]) => {
|
|
4
|
+
get halign(): string;
|
|
5
|
+
set halign(value: string | number): any;
|
|
6
|
+
get valign(): string;
|
|
7
|
+
set valign(value: string | number): any;
|
|
8
|
+
get hexpand(): boolean;
|
|
9
|
+
set hexpand(value: boolean | string): any;
|
|
10
|
+
get vexpand(): boolean;
|
|
11
|
+
set vexpand(value: boolean | string): any;
|
|
12
|
+
get marginStart(): number;
|
|
13
|
+
set marginStart(value: number | string): any;
|
|
14
|
+
get marginEnd(): number;
|
|
15
|
+
set marginEnd(value: number | string): any;
|
|
16
|
+
get visible(): boolean;
|
|
17
|
+
set visible(value: boolean | string): any;
|
|
18
|
+
get sensitive(): boolean;
|
|
19
|
+
set sensitive(value: boolean | string): any;
|
|
20
|
+
get name(): string;
|
|
21
|
+
set name(value: string | null): any;
|
|
22
|
+
get widthRequest(): number;
|
|
23
|
+
set widthRequest(value: number | string): any;
|
|
24
|
+
get heightRequest(): number;
|
|
25
|
+
set heightRequest(value: number | string): any;
|
|
26
|
+
_emit(eventName: string): void;
|
|
27
|
+
addEventListener(eventName: string, callback: (data: import("@nativescript/core").EventData) => void, thisArg?: unknown, once?: boolean): void;
|
|
28
|
+
removeEventListener(eventName: string, callback?: (data: import("@nativescript/core").EventData) => void, thisArg?: unknown): void;
|
|
29
|
+
notify<T extends import("@nativescript/core").EventData>(data: T): void;
|
|
30
|
+
notifyPropertyChange(name: string, value: unknown, oldValue?: unknown): void;
|
|
31
|
+
set(name: string, value: unknown): void;
|
|
32
|
+
get(name: string): unknown;
|
|
33
|
+
}) & typeof NsView;
|
|
34
|
+
export declare class GtkSourceView extends GtkSourceView_base {
|
|
35
|
+
/** The one slot a `.blp` fills with an object: `buffer: GtkSource.Buffer { … }`. */
|
|
36
|
+
static readonly builderSlots: readonly string[];
|
|
37
|
+
private readonly driver;
|
|
38
|
+
private readonly session;
|
|
39
|
+
private unsubscribe;
|
|
40
|
+
constructor();
|
|
41
|
+
createNativeView(): unknown;
|
|
42
|
+
initNativeView(): void;
|
|
43
|
+
disposeNativeView(): void;
|
|
44
|
+
_addChildFromBuilder(name: string, child: object): void;
|
|
45
|
+
get buffer(): Buffer;
|
|
46
|
+
set buffer(value: Buffer);
|
|
47
|
+
get autoIndent(): boolean;
|
|
48
|
+
set autoIndent(value: boolean | string);
|
|
49
|
+
get indentWidth(): number;
|
|
50
|
+
set indentWidth(value: number | string);
|
|
51
|
+
get showLineNumbers(): boolean;
|
|
52
|
+
set showLineNumbers(value: boolean | string);
|
|
53
|
+
get highlightCurrentLine(): boolean;
|
|
54
|
+
set highlightCurrentLine(value: boolean | string);
|
|
55
|
+
get monospace(): boolean;
|
|
56
|
+
set monospace(value: boolean | string);
|
|
57
|
+
get editable(): boolean;
|
|
58
|
+
set editable(value: boolean | string);
|
|
59
|
+
get leftMargin(): number;
|
|
60
|
+
set leftMargin(value: number | string);
|
|
61
|
+
get rightMargin(): number;
|
|
62
|
+
set rightMargin(value: number | string);
|
|
63
|
+
get topMargin(): number;
|
|
64
|
+
set topMargin(value: number | string);
|
|
65
|
+
get bottomMargin(): number;
|
|
66
|
+
set bottomMargin(value: number | string);
|
|
67
|
+
connect(name: string, callback: (self: GtkSourceView, ...args: never[]) => void): number;
|
|
68
|
+
disconnect(id: number): void;
|
|
69
|
+
}
|
|
70
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,92 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@gjsify/gtksource-nativescript",
|
|
3
|
+
"version": "0.56.0",
|
|
4
|
+
"description": "GtkSource.View for NativeScript — an Android EditText with incremental syntax highlighting, a line-number gutter and GtkSourceView language/scheme managers, driven by @gjsify/gtksource-core",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"module": "lib/esm/index.js",
|
|
7
|
+
"types": "lib/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"default": "./lib/esm/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./gtksource": {
|
|
14
|
+
"types": "./lib/types/namespace/gtksource.d.ts",
|
|
15
|
+
"default": "./lib/esm/namespace/gtksource.js"
|
|
16
|
+
},
|
|
17
|
+
"./builder": {
|
|
18
|
+
"types": "./lib/types/builder.d.ts",
|
|
19
|
+
"default": "./lib/esm/builder.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"lib",
|
|
24
|
+
"!lib/types/**/*.d.mts",
|
|
25
|
+
"!lib/types/**/*.spec.d.ts"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"clear": "gjsify clear lib tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo test.gjs.mjs test.node.mjs test.trees.gjs.mjs test.trees.node.mjs",
|
|
29
|
+
"check": "gjsify tsc --noEmit",
|
|
30
|
+
"build": "gjsify run build:gjsify && gjsify run build:types",
|
|
31
|
+
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
32
|
+
"build:types": "gjsify tsc",
|
|
33
|
+
"build:test": "gjsify run build:test:gjs && gjsify run build:test:node && gjsify run build:test:trees:gjs && gjsify run build:test:trees:node",
|
|
34
|
+
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
|
|
35
|
+
"build:test:node": "gjsify build src/test.mts --app node --outfile test.node.mjs",
|
|
36
|
+
"build:test:trees:gjs": "gjsify build src/test.trees.mts --app gjs --no-minify --alias @nativescript/core=@gjsify/adwaita-nativescript/testing/ns-core --outfile test.trees.gjs.mjs",
|
|
37
|
+
"build:test:trees:node": "gjsify build src/test.trees.mts --app node --no-minify --alias @nativescript/core=@gjsify/adwaita-nativescript/testing/ns-core --outfile test.trees.node.mjs",
|
|
38
|
+
"test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:node && gjsify run test:gjs",
|
|
39
|
+
"test:gjs": "gjsify run test.gjs.mjs && gjsify run test.trees.gjs.mjs",
|
|
40
|
+
"test:node": "node test.node.mjs && node test.trees.node.mjs"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"gjs",
|
|
44
|
+
"nativescript",
|
|
45
|
+
"gtksourceview",
|
|
46
|
+
"source-view",
|
|
47
|
+
"syntax",
|
|
48
|
+
"highlighting",
|
|
49
|
+
"android",
|
|
50
|
+
"editor"
|
|
51
|
+
],
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@gjsify/adwaita-nativescript": "^0.56.0",
|
|
54
|
+
"@gjsify/gtksource-core": "^0.56.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@nativescript/core": "*"
|
|
58
|
+
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"@nativescript/core": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@gjsify/cli": "^0.56.0",
|
|
66
|
+
"@gjsify/unit": "^0.56.0",
|
|
67
|
+
"@types/node": "^25.9.2",
|
|
68
|
+
"typescript": "^6.0.3"
|
|
69
|
+
},
|
|
70
|
+
"gjsify": {
|
|
71
|
+
"runtimes": {
|
|
72
|
+
"gjs": "none",
|
|
73
|
+
"node": "none",
|
|
74
|
+
"browser": "none",
|
|
75
|
+
"nativescript": "native"
|
|
76
|
+
},
|
|
77
|
+
"tier": 2,
|
|
78
|
+
"nativescriptPlatforms": [
|
|
79
|
+
"android"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
"license": "MIT",
|
|
83
|
+
"repository": {
|
|
84
|
+
"type": "git",
|
|
85
|
+
"url": "git+https://github.com/gjsify/gjsify.git",
|
|
86
|
+
"directory": "packages/nativescript-bridge/gtksource"
|
|
87
|
+
},
|
|
88
|
+
"bugs": {
|
|
89
|
+
"url": "https://github.com/gjsify/gjsify/issues"
|
|
90
|
+
},
|
|
91
|
+
"homepage": "https://github.com/gjsify/gjsify/tree/main/packages/nativescript-bridge/gtksource#readme"
|
|
92
|
+
}
|