bunmicro 0.8.2 → 0.9.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/CHANGELOG.md +13 -0
- package/README.md +16 -1
- package/package.json +1 -1
- package/runtime/help/defaultkeys.md +7 -0
- package/runtime/help/help.md +14 -9
- package/runtime/help/keybindings.md +32 -437
- package/runtime/syntax/javascript.yaml +49 -1
- package/runtime/syntax/python3.yaml +18 -0
- package/src/highlight/parser.js +78 -4
- package/src/index.js +159 -28
- package/src/plugins/js-bridge.js +5 -0
- package/src/screen/screen.js +13 -1
- package/src/screen/vt100.js +98 -9
- package/todo.txt +4 -0
|
@@ -3,7 +3,7 @@ filetype: javascript
|
|
|
3
3
|
detect:
|
|
4
4
|
filename: "(\\.(m|c)?js$|\\.es[5678]?$)"
|
|
5
5
|
header: "^#!.*/(env +)?(bun|node)( |$)"
|
|
6
|
-
|
|
6
|
+
# console
|
|
7
7
|
rules:
|
|
8
8
|
- constant.number: "\\b[-+]?([1-9][0-9]*|0[0-7]*|0x[0-9a-fA-F]+)([uU][lL]?|[lL][uU]?)?\\b"
|
|
9
9
|
- constant.number: "\\b[-+]?([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+)([EePp][+-]?[0-9]+)?[fFlL]?"
|
|
@@ -74,3 +74,51 @@ rules:
|
|
|
74
74
|
# function documentation
|
|
75
75
|
- identifier: "\\s\\*\\s.*"
|
|
76
76
|
- todo: "(TODO|XXX|FIXME)"
|
|
77
|
+
|
|
78
|
+
# autocomplete-reference: Object constructor/static properties and methods (MDN Object)
|
|
79
|
+
# Object.length Object.name Object.prototype Object.assign Object.create Object.defineProperties Object.defineProperty Object.entries Object.freeze Object.fromEntries Object.getOwnPropertyDescriptor Object.getOwnPropertyDescriptors Object.getOwnPropertyNames Object.getOwnPropertySymbols Object.getPrototypeOf Object.groupBy Object.hasOwn Object.is Object.isExtensible Object.isFrozen Object.isSealed Object.keys Object.preventExtensions Object.seal Object.setPrototypeOf Object.values
|
|
80
|
+
# autocomplete-reference: Object.prototype properties and methods (MDN Object)
|
|
81
|
+
# Object.prototype.__proto__ Object.prototype.constructor Object.prototype.__defineGetter__ Object.prototype.__defineSetter__ Object.prototype.__lookupGetter__ Object.prototype.__lookupSetter__ Object.prototype.hasOwnProperty Object.prototype.isPrototypeOf Object.prototype.propertyIsEnumerable Object.prototype.toLocaleString Object.prototype.toString Object.prototype.valueOf
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# autocomplete-reference: ECMAScript standard built-ins (MDN Global_Objects)
|
|
85
|
+
# globalThis Infinity NaN undefined eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape
|
|
86
|
+
# Object Function Boolean Symbol Error AggregateError EvalError RangeError ReferenceError SuppressedError SyntaxError TypeError URIError InternalError
|
|
87
|
+
# Number BigInt Math Date Temporal String RegExp
|
|
88
|
+
# Array TypedArray Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array BigInt64Array BigUint64Array Float16Array Float32Array Float64Array
|
|
89
|
+
# Map Set WeakMap WeakSet ArrayBuffer SharedArrayBuffer DataView Atomics JSON stringify parse WeakRef FinalizationRegistry
|
|
90
|
+
# Iterator AsyncIterator Promise GeneratorFunction AsyncGeneratorFunction Generator AsyncGenerator AsyncFunction DisposableStack AsyncDisposableStack
|
|
91
|
+
# Reflect Proxy Intl Collator DateTimeFormat DisplayNames DurationFormat ListFormat Locale NumberFormat PluralRules RelativeTimeFormat Segmenter
|
|
92
|
+
# autocomplete-reference: Browser globals and Web API interfaces (MDN Web/API)
|
|
93
|
+
# window self globalThis document navigator location history screen frames parent top opener origin name status closed crossOriginIsolated isSecureContext customElements visualViewport
|
|
94
|
+
# localStorage sessionStorage indexedDB caches cookieStore scheduler trustedTypes performance crypto console
|
|
95
|
+
# alert confirm prompt print open close focus blur stop find scroll scrollTo scrollBy scrollX scrollY moveTo moveBy resizeTo resizeBy
|
|
96
|
+
# getComputedStyle matchMedia requestAnimationFrame cancelAnimationFrame requestIdleCallback cancelIdleCallback structuredClone postMessage dispatchEvent addEventListener removeEventListener
|
|
97
|
+
# fetch setTimeout clearTimeout setInterval clearInterval queueMicrotask atob btoa createImageBitmap reportError
|
|
98
|
+
# AbortController AbortSignal AbstractRange AnalyserNode Animation AnimationEffect AnimationEvent AnimationPlaybackEvent AnimationTimeline Attr Audio AudioBuffer AudioBufferSourceNode AudioContext AudioData AudioDecoder AudioDestinationNode AudioEncoder AudioListener AudioNode AudioParam AudioParamMap AudioProcessingEvent AudioScheduledSourceNode AudioSinkInfo AudioWorklet AudioWorkletGlobalScope AudioWorkletNode AudioWorkletProcessor AuthenticatorAssertionResponse AuthenticatorAttestationResponse AuthenticatorResponse
|
|
99
|
+
# BarcodeDetector BatteryManager BeforeUnloadEvent BiquadFilterNode Blob BlobEvent Bluetooth BluetoothAdvertisingEvent BluetoothCharacteristicProperties BluetoothDevice BluetoothRemoteGATTCharacteristic BluetoothRemoteGATTDescriptor BluetoothRemoteGATTServer BluetoothRemoteGATTService BluetoothUUID BroadcastChannel BrowserCaptureMediaStreamTrack ByteLengthQueuingStrategy
|
|
100
|
+
# CSS CSSAnimation CSSConditionRule CSSContainerRule CSSCounterStyleRule CSSFontFaceRule CSSFontFeatureValuesRule CSSFontPaletteValuesRule CSSGroupingRule CSSImageValue CSSImportRule CSSKeyframeRule CSSKeyframesRule CSSKeywordValue CSSLayerBlockRule CSSLayerStatementRule CSSMathClamp CSSMathInvert CSSMathMax CSSMathMin CSSMathNegate CSSMathProduct CSSMathSum CSSMathValue CSSMatrixComponent CSSMediaRule CSSNamespaceRule CSSNumericArray CSSNumericValue CSSPageRule CSSPerspective CSSPositionValue CSSPropertyRule CSSRotate CSSRule CSSRuleList CSSScale CSSScopeRule CSSSkew CSSSkewX CSSSkewY CSSStartingStyleRule CSSStyleDeclaration CSSStyleRule CSSStyleSheet CSSStyleValue CSSSupportsRule CSSTransformComponent CSSTransformValue CSSTransition CSSTranslate CSSUnitValue CSSUnparsedValue CSSVariableReferenceValue
|
|
101
|
+
# Cache CacheStorage CanvasCaptureMediaStreamTrack CanvasGradient CanvasPattern CanvasRenderingContext2D CaptureController CaretPosition ChannelMergerNode ChannelSplitterNode CharacterData Clipboard ClipboardEvent ClipboardItem CloseEvent Comment CompositionEvent CompressionStream ConstantSourceNode ContentVisibilityAutoStateChangeEvent ConvolverNode CountQueuingStrategy Credential CredentialsContainer Crypto CryptoKey CustomElementRegistry CustomEvent
|
|
102
|
+
# DOMError DOMException DOMImplementation DOMMatrix DOMMatrixReadOnly DOMParser DOMPoint DOMPointReadOnly DOMQuad DOMRect DOMRectReadOnly DOMStringList DOMStringMap DOMTokenList DataTransfer DataTransferItem DataTransferItemList DecompressionStream DelayNode DeviceMotionEvent DeviceOrientationEvent DevicePosture DirectoryEntry DirectoryReader Document DocumentFragment DocumentPictureInPicture DocumentPictureInPictureEvent DocumentType DragEvent DynamicsCompressorNode
|
|
103
|
+
# EditContext Element ElementInternals EncodedAudioChunk EncodedVideoChunk ErrorEvent Event EventCounts EventSource EventTarget ExtendableCookieChangeEvent ExtendableEvent EyeDropper
|
|
104
|
+
# FeaturePolicy FederatedCredential Fence File FileList FileReader FileSystem FileSystemDirectoryEntry FileSystemDirectoryHandle FileSystemDirectoryReader FileSystemEntry FileSystemFileEntry FileSystemFileHandle FileSystemHandle FileSystemObserver FileSystemSyncAccessHandle FileSystemWritableFileStream FocusEvent FontData FontFace FontFaceSet FontFaceSetLoadEvent FormData FormDataEvent
|
|
105
|
+
# GPU GPUAdapter GPUAdapterInfo GPUBindGroup GPUBindGroupLayout GPUBuffer GPUCanvasContext GPUCommandBuffer GPUCommandEncoder GPUCompilationInfo GPUCompilationMessage GPUComputePassEncoder GPUComputePipeline GPUDevice GPUDeviceLostInfo GPUError GPUExternalTexture GPUInternalError GPUMapMode GPUOutOfMemoryError GPUPipelineError GPUPipelineLayout GPUQuerySet GPUQueue GPURenderBundle GPURenderBundleEncoder GPURenderPassEncoder GPURenderPipeline GPUSampler GPUShaderModule GPUSupportedFeatures GPUSupportedLimits GPUTexture GPUTextureView GPUUncapturedErrorEvent GPUValidationError Gamepad GamepadButton GamepadEvent GamepadHapticActuator Geolocation GeolocationCoordinates GeolocationPosition GeolocationPositionError GravitySensor Gyroscope
|
|
106
|
+
# HTMLAllCollection HTMLAnchorElement HTMLAreaElement HTMLAudioElement HTMLBRElement HTMLBaseElement HTMLBodyElement HTMLButtonElement HTMLCanvasElement HTMLCollection HTMLDListElement HTMLDataElement HTMLDataListElement HTMLDetailsElement HTMLDialogElement HTMLDivElement HTMLDocument HTMLElement HTMLEmbedElement HTMLFencedFrameElement HTMLFieldSetElement HTMLFontElement HTMLFormControlsCollection HTMLFormElement HTMLFrameElement HTMLFrameSetElement HTMLHRElement HTMLHeadElement HTMLHeadingElement HTMLHtmlElement HTMLIFrameElement HTMLImageElement HTMLInputElement HTMLLIElement HTMLLabelElement HTMLLegendElement HTMLLinkElement HTMLMapElement HTMLMarqueeElement HTMLMediaElement HTMLMenuElement HTMLMetaElement HTMLMeterElement HTMLModElement HTMLOListElement HTMLObjectElement HTMLOptGroupElement HTMLOptionElement HTMLOptionsCollection HTMLOutputElement HTMLParagraphElement HTMLParamElement HTMLPictureElement HTMLPreElement HTMLProgressElement HTMLQuoteElement HTMLScriptElement HTMLSelectElement HTMLSelectedContentElement HTMLSlotElement HTMLSourceElement HTMLSpanElement HTMLStyleElement HTMLTableCaptionElement HTMLTableCellElement HTMLTableColElement HTMLTableElement HTMLTableRowElement HTMLTableSectionElement HTMLTemplateElement HTMLTextAreaElement HTMLTimeElement HTMLTitleElement HTMLTrackElement HTMLUListElement HTMLUnknownElement HTMLVideoElement Headers Highlight HighlightRegistry History IDBCursor IDBCursorWithValue IDBDatabase IDBFactory IDBIndex IDBKeyRange IDBObjectStore IDBOpenDBRequest IDBRequest IDBTransaction IDBVersionChangeEvent IdleDeadline ImageBitmap ImageBitmapRenderingContext ImageCapture ImageData ImageDecoder ImageTrack ImageTrackList Ink InputDeviceCapabilities InputDeviceInfo InputEvent InstallEvent IntersectionObserver IntersectionObserverEntry
|
|
107
|
+
# Keyboard KeyboardEvent KeyboardLayoutMap KeyframeEffect LanguageDetector LargestContentfulPaint LaunchParams LaunchQueue LayoutShift LayoutShiftAttribution LinearAccelerationSensor Location Lock LockManager Magnetometer ManagedMediaSource ManagedSourceBuffer MathMLElement MediaCapabilities MediaDeviceInfo MediaDevices MediaElementAudioSourceNode MediaEncryptedEvent MediaError MediaKeyMessageEvent MediaKeys MediaKeySession MediaKeyStatusMap MediaKeySystemAccess MediaList MediaMetadata MediaQueryList MediaQueryListEvent MediaRecorder MediaRecorderErrorEvent MediaSession MediaSource MediaSourceHandle MediaStream MediaStreamAudioDestinationNode MediaStreamAudioSourceNode MediaStreamEvent MediaStreamTrack MediaStreamTrackAudioSourceNode MediaStreamTrackEvent MediaStreamTrackGenerator MediaStreamTrackProcessor MediaTrackConstraints MediaTrackSettings MediaTrackSupportedConstraints MessageChannel MessageEvent MessagePort MIDIAccess MIDIConnectionEvent MIDIInput MIDIInputMap MIDIMessageEvent MIDIOutput MIDIOutputMap MIDIPort MimeType MimeTypeArray MouseEvent MutationEvent MutationObserver MutationRecord
|
|
108
|
+
# NamedNodeMap NavigateEvent Navigation NavigationActivation NavigationCurrentEntryChangeEvent NavigationDestination NavigationHistoryEntry NavigationPrecommitController NavigationPreloadManager NavigationTransition Navigator NavigatorLogin NavigatorUAData NDEFMessage NDEFReader NDEFReadingEvent NDEFRecord NetworkInformation Node NodeIterator NodeList Notification NotificationEvent OffscreenCanvas OfflineAudioCompletionEvent OfflineAudioContext OrientationSensor OscillatorNode OverconstrainedError PageRevealEvent PageSwapEvent PageTransitionEvent PannerNode PasswordCredential Path2D PaymentAddress PaymentMethodChangeEvent PaymentRequest PaymentRequestUpdateEvent PaymentResponse Performance PerformanceElementTiming PerformanceEntry PerformanceEventTiming PerformanceLongAnimationFrameTiming PerformanceLongTaskTiming PerformanceMark PerformanceMeasure PerformanceNavigationTiming PerformanceObserver PerformanceObserverEntryList PerformancePaintTiming PerformanceResourceTiming PerformanceScriptTiming PerformanceServerTiming PerformanceTiming PeriodicSyncManager Permissions PermissionStatus PictureInPictureEvent PictureInPictureWindow Plugin PluginArray PointerEvent PopStateEvent Presentation PresentationAvailability PresentationConnection PresentationConnectionAvailableEvent PresentationConnectionCloseEvent PresentationConnectionList PresentationReceiver PresentationRequest PressureObserver PressureRecord ProcessingInstruction ProgressEvent PromiseRejectionEvent PublicKeyCredential PushEvent PushManager PushMessageData PushSubscription PushSubscriptionOptions
|
|
109
|
+
# RTCCertificate RTCDTMFSender RTCDTMFToneChangeEvent RTCDataChannel RTCDataChannelEvent RTCDtlsTransport RTCEncodedAudioFrame RTCEncodedVideoFrame RTCError RTCErrorEvent RTCIceCandidate RTCIceTransport RTCPeerConnection RTCPeerConnectionIceErrorEvent RTCPeerConnectionIceEvent RTCRtpReceiver RTCRtpScriptTransformer RTCRtpSender RTCRtpTransceiver RTCSctpTransport RTCSessionDescription RTCStatsReport RTCTrackEvent RadioNodeList Range ReadableByteStreamController ReadableStream ReadableStreamBYOBReader ReadableStreamBYOBRequest ReadableStreamDefaultController ReadableStreamDefaultReader RelativeOrientationSensor RemotePlayback Report ReportBody ReportingObserver Request ResizeObserver ResizeObserverEntry ResizeObserverSize Response SVGAElement SVGAngle SVGAnimateElement SVGAnimateMotionElement SVGAnimateTransformElement SVGAnimatedAngle SVGAnimatedBoolean SVGAnimatedEnumeration SVGAnimatedInteger SVGAnimatedLength SVGAnimatedLengthList SVGAnimatedNumber SVGAnimatedNumberList SVGAnimatedPreserveAspectRatio SVGAnimatedRect SVGAnimatedString SVGAnimatedTransformList SVGAnimationElement SVGCircleElement SVGClipPathElement SVGComponentTransferFunctionElement SVGDefsElement SVGDescElement SVGElement SVGEllipseElement SVGFEBlendElement SVGFEColorMatrixElement SVGFEComponentTransferElement SVGFECompositeElement SVGFEConvolveMatrixElement SVGFEDiffuseLightingElement SVGFEDisplacementMapElement SVGFEDistantLightElement SVGFEDropShadowElement SVGFEFloodElement SVGFEFuncAElement SVGFEFuncBElement SVGFEFuncGElement SVGFEFuncRElement SVGFEGaussianBlurElement SVGFEImageElement SVGFEMergeElement SVGFEMergeNodeElement SVGFEMorphologyElement SVGFEOffsetElement SVGFEPointLightElement SVGFESpecularLightingElement SVGFESpotLightElement SVGFETileElement SVGFETurbulenceElement SVGFilterElement SVGForeignObjectElement SVGGElement SVGGeometryElement SVGGradientElement SVGGraphicsElement SVGImageElement SVGLength SVGLengthList SVGLineElement SVGLinearGradientElement SVGMPathElement SVGMarkerElement SVGMaskElement SVGMatrix SVGMetadataElement SVGNumber SVGNumberList SVGPathElement SVGPatternElement SVGPoint SVGPointList SVGPolygonElement SVGPolylineElement SVGPreserveAspectRatio SVGRadialGradientElement SVGRect SVGRectElement SVGSVGElement SVGScriptElement SVGSetElement SVGStopElement SVGStringList SVGStyleElement SVGSwitchElement SVGSymbolElement SVGTSpanElement SVGTextContentElement SVGTextElement SVGTextPathElement SVGTextPositioningElement SVGTitleElement SVGTransform SVGTransformList SVGUnitTypes SVGUseElement SVGViewElement Screen ScreenDetailed ScreenDetails ScreenOrientation ScriptProcessorNode SecurityPolicyViolationEvent Selection Sensor SensorErrorEvent Serial SerialPort ServiceWorker ServiceWorkerContainer ServiceWorkerGlobalScope ServiceWorkerRegistration ShadowRoot SharedWorker SourceBuffer SourceBufferList SpeechRecognition SpeechRecognitionAlternative SpeechRecognitionErrorEvent SpeechRecognitionEvent SpeechRecognitionResult SpeechRecognitionResultList SpeechSynthesis SpeechSynthesisErrorEvent SpeechSynthesisEvent SpeechSynthesisUtterance SpeechSynthesisVoice StaticRange StereoPannerNode Storage StorageEvent StorageManager StylePropertyMap StylePropertyMapReadOnly StyleSheet StyleSheetList SubmitEvent SubtleCrypto SyncManager
|
|
110
|
+
# TaskAttributionTiming TaskController TaskPriorityChangeEvent TaskSignal Text TextDecoder TextEncoder TextDecoderStream TextEncoderStream TextEvent TextFormat TextFormatUpdateEvent TextMetrics TextTrack TextTrackCue TextTrackCueList TextTrackList TimeRanges ToggleEvent Touch TouchEvent TouchList TrackEvent TransformStream TransformStreamDefaultController TransitionEvent TreeWalker TrustedHTML TrustedScript TrustedScriptURL TrustedTypePolicy TrustedTypePolicyFactory UIEvent URL URLPattern URLSearchParams USB USBAlternateInterface USBConfiguration USBConnectionEvent USBDevice USBEndpoint USBInTransferResult USBInterface USBIsochronousInTransferPacket USBIsochronousInTransferResult USBIsochronousOutTransferPacket USBOutTransferResult UserActivation VTTCue VTTRegion ValidityState VideoColorSpace VideoDecoder VideoEncoder VideoFrame VideoPlaybackQuality ViewTransition VirtualKeyboard VisualViewport WakeLock WakeLockSentinel WebAssembly WebGL2RenderingContext WebGLActiveInfo WebGLBuffer WebGLContextEvent WebGLFramebuffer WebGLProgram WebGLQuery WebGLRenderbuffer WebGLRenderingContext WebGLSampler WebGLShader WebGLShaderPrecisionFormat WebGLSync WebGLTexture WebGLTransformFeedback WebGLUniformLocation WebGLVertexArrayObject WebSocket WebSocketStream WebTransport WebTransportBidirectionalStream WebTransportDatagramDuplexStream WebTransportError WheelEvent Window WindowClient WindowControlsOverlay Worker WorkerGlobalScope WorkerLocation WorkerNavigator Worklet WorkletGlobalScope WritableStream WritableStreamDefaultController WritableStreamDefaultWriter XMLDocument XMLHttpRequest XMLHttpRequestEventTarget XMLHttpRequestUpload XMLSerializer XPathEvaluator XPathExpression XPathResult XRAnchor XRAnchorSet XRBoundedReferenceSpace XRCPUDepthInformation XRCamera XRDOMOverlayState XRDepthInformation XRFrame XRHand XRHitTestResult XRHitTestSource XRInputSource XRInputSourceArray XRInputSourceEvent XRInputSourcesChangeEvent XRJointPose XRJointSpace XRLayer XRLightEstimate XRLightProbe XRPose XRRay XRReferenceSpace XRReferenceSpaceEvent XRRenderState XRRigidTransform XRSession XRSessionEvent XRSpace XRSystem XRTransientInputHitTestResult XRTransientInputHitTestSource XRView XRViewerPose XRViewport XRWebGLBinding XRWebGLDepthInformation XRWebGLLayer XSLTProcessor
|
|
111
|
+
# autocomplete-reference: Node.js globals and builtin modules (Node.js API)
|
|
112
|
+
# __dirname __filename exports module require process console Buffer
|
|
113
|
+
# AbortController AbortSignal Blob BroadcastChannel ByteLengthQueuingStrategy CloseEvent CompressionStream CountQueuingStrategy Crypto CryptoKey CustomEvent DecompressionStream DOMException ErrorEvent Event EventSource EventTarget File FormData Headers localStorage MessageChannel MessageEvent MessagePort navigator PerformanceEntry PerformanceMark PerformanceMeasure PerformanceObserver PerformanceObserverEntryList PerformanceResourceTiming performance Request Response sessionStorage Storage structuredClone SubtleCrypto TextDecoder TextDecoderStream TextEncoder TextEncoderStream TransformStream URL URLPattern URLSearchParams WebAssembly WebSocket WritableStream WritableStreamDefaultController WritableStreamDefaultWriter ReadableStream ReadableStreamBYOBReader ReadableStreamBYOBRequest ReadableStreamDefaultController ReadableStreamDefaultReader
|
|
114
|
+
# node assert assert/strict async_hooks buffer child_process cluster console constants crypto dgram diagnostics_channel dns dns/promises domain events fs fs/promises http http2 https inspector inspector/promises module net os path path/posix path/win32 perf_hooks process punycode querystring readline readline/promises repl sea sqlite stream stream/consumers stream/promises stream/web string_decoder test test/reporters timers timers/promises tls trace_events tty url util util/types v8 vm wasi worker_threads zlib
|
|
115
|
+
# autocomplete-reference: Bun globals and Bun native APIs (Bun docs)
|
|
116
|
+
# Bun bun jsc gc CryptoHasher FileSink HTMLBundle Shell ShellError ShellOutput ShellPromise Subprocess Transpiler UnsafeCallback build color console depth dns file gc gzip hash indexOfLine lineColumn listen main mmap nanoseconds openInEditor origin peek readableStreamToArray readableStreamToBlob readableStreamToBytes readableStreamToFormData readableStreamToJSON readableStreamToText resolve resolveSync revision semver serve shell sleep sleepSync spawn spawnSync stderr stdin stdout stringWidth stripANSI udp unzip version which write
|
|
117
|
+
# BunFile S3File ArrayBufferSink BlobPart BodyInit BunPlugin BuildConfig BuildMessage BuildOutput BuildArtifact CompileBuildConfig Cookie CookieMap Env FileBlob FileSystemRouter Glob GlobScanOptions HTTPResponseSink ImportMeta InspectOptions Mock ModuleMock NetworkSink PathLike PluginBuilder Server ServerWebSocket Socket TCPSocketListener TLSOptions TranspilerOptions UDPConnectedSocket UDPSocket WebSocketHandler WebSocketServeOptions
|
|
118
|
+
# fetch Request Response Headers FormData Blob File URL URLSearchParams TextEncoder TextDecoder ReadableStream WritableStream TransformStream WebSocket Event EventTarget MessageEvent CloseEvent ErrorEvent CustomEvent DOMException AbortController AbortSignal crypto Crypto CryptoKey SubtleCrypto performance structuredClone queueMicrotask setTimeout clearTimeout setInterval clearInterval setImmediate clearImmediate
|
|
119
|
+
# bun:test describe test it expect beforeAll beforeEach afterAll afterEach mock spyOn jest setSystemTime restore clearAllMocks restoreAllMocks
|
|
120
|
+
# bun:sqlite Database Statement SQLQueryBindings SQLQueryResult
|
|
121
|
+
# bun:jsc serialize deserialize
|
|
122
|
+
# bun:ffi dlopen suffix ptr CString JSCallback FFIType
|
|
123
|
+
# bun:wrap wrap
|
|
124
|
+
# bun:main bun:internal bun:macro bun:plugin bun:embedded bun:generated
|
|
@@ -60,3 +60,21 @@ rules:
|
|
|
60
60
|
end: "$"
|
|
61
61
|
rules: # AKA Code tags (PEP 350)
|
|
62
62
|
- todo: "(TODO|FIXME|HACK|BUG|NOTE|FAQ|MNEMONIC|REQ|RFE|IDEA|PORT|\\?\\?\\?|!!!|GLOSS|SEE|TODOC|STAT|RVD|CRED):?"
|
|
63
|
+
|
|
64
|
+
# autocomplete-reference: Python built-in constants, functions, and types (Python docs)
|
|
65
|
+
# None True False Ellipsis NotImplemented __debug__ abs aiter all anext any ascii bin bool breakpoint bytearray bytes callable chr classmethod compile complex delattr dict dir divmod enumerate eval exec filter float format frozenset getattr globals hasattr hash help hex id input int isinstance issubclass iter len list locals map max memoryview min next object oct open ord pow print property range repr reversed round set setattr slice sorted staticmethod str sum super tuple type vars zip __import__
|
|
66
|
+
# ArithmeticError AssertionError AttributeError BaseException BaseExceptionGroup BlockingIOError BrokenPipeError BufferError BytesWarning ChildProcessError ConnectionAbortedError ConnectionError ConnectionRefusedError ConnectionResetError DeprecationWarning EOFError EncodingWarning EnvironmentError Exception ExceptionGroup FileExistsError FileNotFoundError FloatingPointError FutureWarning GeneratorExit IOError ImportError ImportWarning IndentationError IndexError InterruptedError IsADirectoryError KeyError KeyboardInterrupt LookupError MemoryError ModuleNotFoundError NameError NotADirectoryError NotImplementedError OSError OverflowError PendingDeprecationWarning PermissionError ProcessLookupError RecursionError ReferenceError ResourceWarning RuntimeError RuntimeWarning StopAsyncIteration StopIteration SyntaxError SyntaxWarning SystemError SystemExit TabError TimeoutError TypeError UnboundLocalError UnicodeDecodeError UnicodeEncodeError UnicodeError UnicodeTranslateError UnicodeWarning UserWarning ValueError Warning ZeroDivisionError
|
|
67
|
+
# autocomplete-reference: Python common object and data model methods
|
|
68
|
+
# __abs__ __add__ __aiter__ __all__ __and__ __annotations__ __anext__ __await__ __bases__ __bool__ __buffer__ __builtins__ __bytes__ __cached__ __call__ __ceil__ __class__ __class_getitem__ __closure__ __code__ __complex__ __contains__ __context__ __debug__ __defaults__ __del__ __delattr__ __delete__ __delitem__ __dict__ __dir__ __divmod__ __doc__ __enter__ __eq__ __exit__ __file__ __float__ __floor__ __floordiv__ __format__ __fspath__ __ge__ __get__ __getattr__ __getattribute__ __getitem__ __getnewargs__ __getstate__ __globals__ __gt__ __hash__ __iadd__ __iand__ __ifloordiv__ __ilshift__ __imatmul__ __imod__ __imul__ __index__ __init__ __init_subclass__ __instancecheck__ __int__ __invert__ __ior__ __ipow__ __irshift__ __isub__ __iter__ __itruediv__ __ixor__ __kwdefaults__ __le__ __len__ __length_hint__ __loader__ __lshift__ __lt__ __matmul__ __missing__ __mod__ __module__ __mro__ __mul__ __name__ __ne__ __neg__ __new__ __next__ __or__ __package__ __path__ __pos__ __pow__ __qualname__ __radd__ __rand__ __rdivmod__ __reduce__ __reduce_ex__ __repr__ __reversed__ __rfloordiv__ __rlshift__ __rmatmul__ __rmod__ __rmul__ __ror__ __round__ __rpow__ __rrshift__ __rshift__ __rsub__ __rtruediv__ __rxor__ __set__ __set_name__ __setattr__ __setitem__ __slots__ __spec__ __str__ __sub__ __subclasscheck__ __subclasses__ __traceback__ __truediv__ __trunc__ __weakref__ __xor__
|
|
69
|
+
# autocomplete-reference: Python str, bytes, list, tuple, dict, set, file/path methods
|
|
70
|
+
# capitalize casefold center count encode endswith expandtabs find format format_map index isalnum isalpha isascii isdecimal isdigit isidentifier islower isnumeric isprintable isspace istitle isupper join ljust lower lstrip maketrans partition removeprefix removesuffix replace rfind rindex rjust rpartition rsplit rstrip split splitlines startswith strip swapcase title translate upper zfill
|
|
71
|
+
# append clear copy count extend index insert pop remove reverse sort
|
|
72
|
+
# clear copy fromkeys get items keys pop popitem setdefault update values
|
|
73
|
+
# add clear copy difference difference_update discard intersection intersection_update isdisjoint issubset issuperset pop remove symmetric_difference symmetric_difference_update union update
|
|
74
|
+
# close closed detach fileno flush isatty read readable readline readlines seek seekable tell truncate writable write writelines exists is_file is_dir iterdir glob rglob mkdir rename replace resolve absolute parent parents name stem suffix suffixes with_name with_stem with_suffix open read_text read_bytes write_text write_bytes
|
|
75
|
+
# autocomplete-reference: Python standard-library module names (Python module index)
|
|
76
|
+
# abc aifc argparse array ast asyncio atexit audioop base64 bdb binascii bisect builtins bz2 calendar cgi cgitb chunk cmath cmd code codecs codeop collections colorsys compileall concurrent configparser contextlib contextvars copy copyreg crypt csv ctypes curses dataclasses datetime dbm decimal difflib dis doctest email encodings ensurepip enum errno faulthandler fcntl filecmp fileinput fnmatch fractions ftplib functools gc getopt getpass gettext glob graphlib grp gzip hashlib heapq hmac html http idlelib imaplib imghdr importlib inspect io ipaddress itertools json keyword linecache locale logging lzma mailbox mailcap marshal math mimetypes mmap modulefinder multiprocessing netrc nis nntplib numbers operator optparse os pathlib pdb pickle pickletools pipes pkgutil platform plistlib poplib posix pprint profile pstats pty pwd py_compile pyclbr pydoc queue quopri random re readline reprlib resource rlcompleter runpy sched secrets select selectors shelve shlex shutil signal site smtpd smtplib sndhdr socket socketserver sqlite3 ssl stat statistics string stringprep struct subprocess sunau symtable sys sysconfig syslog tabnanny tarfile telnetlib tempfile termios textwrap threading time timeit tkinter token tokenize tomllib trace traceback tracemalloc tty turtle types typing unicodedata unittest urllib uuid venv warnings wave weakref webbrowser wsgiref xdrlib xml xmlrpc zipapp zipfile zipimport zlib zoneinfo
|
|
77
|
+
# autocomplete-reference: famous third-party Python packages and common aliases
|
|
78
|
+
# numpy np pandas pd scipy sklearn scikit_learn matplotlib plt seaborn sns plotly bokeh altair statsmodels sympy numba cython polars pyarrow dask xarray networkx requests httpx aiohttp urllib3 beautifulsoup4 bs4 lxml scrapy selenium playwright flask django fastapi starlette pydantic sqlalchemy alembic psycopg2 pymongo redis celery typer click rich textual tqdm pytest hypothesis tox nox black ruff flake8 mypy pyright isort poetry pip setuptools wheel virtualenv ipython jupyter notebook jupyterlab ipykernel ipywidgets traitlets pillow PIL opencv cv2 imageio skimage scikit_image torch torchvision torchaudio tensorflow keras jax flax transformers tokenizers datasets accelerate diffusers sentence_transformers spacy nltk gensim langchain openai anthropic google genai boto3 botocore s3fs fsspec cryptography paramiko fabric pendulum arrow dateutil pyyaml yaml toml tomli tomlkit orjson ujson msgpack pydantic_settings python_dotenv dotenv sqlalchemy_utils flask_sqlalchemy django_rest_framework drf pytest_asyncio pytest_cov coverage
|
|
79
|
+
# autocomplete-reference: common package submodules and method words
|
|
80
|
+
# ndarray array arange linspace zeros ones empty full eye reshape transpose astype dtype shape ndim size mean median std var sum min max argmin argmax argsort sort clip concatenate stack hstack vstack dot matmul einsum where unique random DataFrame Series read_csv read_excel read_json read_parquet read_sql to_csv to_excel to_json to_parquet groupby merge join concat pivot pivot_table drop dropna fillna assign apply map iloc loc values columns index describe head tail info query sort_values reset_index set_index fit transform fit_transform predict predict_proba score train_test_split Pipeline GridSearchCV StandardScaler OneHotEncoder RandomForestClassifier RandomForestRegressor LinearRegression LogisticRegression
|
package/src/highlight/parser.js
CHANGED
|
@@ -29,11 +29,12 @@ export class SyntaxHeader {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export class SyntaxDefinition {
|
|
32
|
-
constructor(header, source) {
|
|
32
|
+
constructor(header, source, text = "") {
|
|
33
33
|
this.header = header;
|
|
34
34
|
this.filetype = header.filetype;
|
|
35
35
|
this.source = source;
|
|
36
36
|
this.rules = parseRules(source.rules ?? []);
|
|
37
|
+
this.autocompleteWords = scanAutocompleteWordsFromText(text);
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
|
|
@@ -45,9 +46,27 @@ export async function loadSyntaxDefinitions(runtime) {
|
|
|
45
46
|
|
|
46
47
|
const definitions = [];
|
|
47
48
|
for (const file of runtime.list(1)) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
let text = "";
|
|
50
|
+
try {
|
|
51
|
+
text = await file.text();
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.error("Failed to read syntax yaml:", file.name);
|
|
54
|
+
console.error(" Will not highlight this kind of file");
|
|
55
|
+
console.error(" @ loadSyntaxDefinitions ");
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let source = null;
|
|
60
|
+
try {
|
|
61
|
+
source = Bun.YAML.parse(text);
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error("Failed to parse syntax yaml:", file.name);
|
|
64
|
+
console.error(" Will not highlight this kind of file");
|
|
65
|
+
console.error(" @ loadSyntaxDefinitions ");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const header = headers.get(file.name) ?? (source ? parseHeaderYaml(source) : parseHeaderTextFallback(text, file.name));
|
|
69
|
+
definitions.push(new SyntaxDefinition(header, source ?? { rules: [] }, text));
|
|
51
70
|
}
|
|
52
71
|
return definitions;
|
|
53
72
|
}
|
|
@@ -80,6 +99,61 @@ export function parseHeaderYaml(source) {
|
|
|
80
99
|
});
|
|
81
100
|
}
|
|
82
101
|
|
|
102
|
+
function parseHeaderTextFallback(text, fileName = "") {
|
|
103
|
+
const source = String(text ?? "");
|
|
104
|
+
const fallbackType = String(fileName).replace(/\.ya?ml$/i, "");
|
|
105
|
+
const filetype = rawYamlScalar(source.match(/^filetype:[ \t]*(.*)$/m)?.[1]) || fallbackType;
|
|
106
|
+
return new SyntaxHeader({
|
|
107
|
+
filetype,
|
|
108
|
+
filename: rawYamlDetectScalar(source, "filename"),
|
|
109
|
+
header: rawYamlDetectScalar(source, "header"),
|
|
110
|
+
signature: rawYamlDetectScalar(source, "signature"),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function rawYamlDetectScalar(text, key) {
|
|
115
|
+
const detect = text.match(/^detect:[ \t]*(?:#.*)?(?:\r?\n)((?:[ \t]+[^\n]*\r?\n?)*)/m)?.[1] ?? "";
|
|
116
|
+
return rawYamlScalar(detect.match(new RegExp(`^[ \t]+${key}:[ \t]*(.*)$`, "m"))?.[1]);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function rawYamlScalar(value) {
|
|
120
|
+
if (value == null) return "";
|
|
121
|
+
let out = String(value).trim();
|
|
122
|
+
if (!out) return "";
|
|
123
|
+
if (out.startsWith("\"") && out.endsWith("\"")) {
|
|
124
|
+
try { return JSON.parse(out); } catch { return out.slice(1, -1); }
|
|
125
|
+
}
|
|
126
|
+
if (out.startsWith("'") && out.endsWith("'")) return out.slice(1, -1).replaceAll("''", "'");
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function scanAutocompleteWordsFromText(text) {
|
|
131
|
+
const source = String(text ?? "");
|
|
132
|
+
const words = [];
|
|
133
|
+
const seen = new Set();
|
|
134
|
+
let i = 0;
|
|
135
|
+
while (i < source.length) {
|
|
136
|
+
if (!isSyntaxWordChar(source[i])) { i++; continue; }
|
|
137
|
+
let j = i;
|
|
138
|
+
while (j < source.length && isSyntaxWordChar(source[j])) j++;
|
|
139
|
+
const word = source.slice(i, j);
|
|
140
|
+
if (!seen.has(word)) {
|
|
141
|
+
seen.add(word);
|
|
142
|
+
words.push(word);
|
|
143
|
+
}
|
|
144
|
+
i = j;
|
|
145
|
+
}
|
|
146
|
+
return words;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function isSyntaxWordChar(ch) {
|
|
150
|
+
if (!ch) return false;
|
|
151
|
+
const cp = ch.codePointAt(0);
|
|
152
|
+
if ((cp >= 65 && cp <= 90) || (cp >= 97 && cp <= 122) || (cp >= 48 && cp <= 57) || cp === 95) return true;
|
|
153
|
+
if (cp <= 127) return false;
|
|
154
|
+
return /\p{L}|\p{N}/u.test(ch);
|
|
155
|
+
}
|
|
156
|
+
|
|
83
157
|
function parseRules(rules) {
|
|
84
158
|
return rules.map((rule) => parseRule(rule)).filter(Boolean);
|
|
85
159
|
}
|
package/src/index.js
CHANGED
|
@@ -190,25 +190,79 @@ function isWideCodePoint(cp) {
|
|
|
190
190
|
(cp >= 0x1F004 && cp <= 0x1F0CF) ||
|
|
191
191
|
(cp >= 0x1F18F && cp <= 0x1F19A) ||
|
|
192
192
|
(cp >= 0x1F200 && cp <= 0x1F2FF) ||
|
|
193
|
-
(cp >= 0x1F300 && cp <=
|
|
194
|
-
(cp >= 0x1F900 && cp <= 0x1F9FF) ||
|
|
193
|
+
(cp >= 0x1F300 && cp <= 0x1FAFF) ||
|
|
195
194
|
(cp >= 0x20000 && cp <= 0x2FFFD) ||
|
|
196
195
|
(cp >= 0x30000 && cp <= 0x3FFFD)
|
|
197
196
|
);
|
|
198
197
|
}
|
|
199
198
|
|
|
199
|
+
function isZeroWidthCodePoint(cp) {
|
|
200
|
+
return (
|
|
201
|
+
cp === 0x200D ||
|
|
202
|
+
(cp >= 0x0300 && cp <= 0x036F) ||
|
|
203
|
+
(cp >= 0x1AB0 && cp <= 0x1AFF) ||
|
|
204
|
+
(cp >= 0x1DC0 && cp <= 0x1DFF) ||
|
|
205
|
+
(cp >= 0x20D0 && cp <= 0x20FF) ||
|
|
206
|
+
(cp >= 0xFE00 && cp <= 0xFE0F) ||
|
|
207
|
+
(cp >= 0xFE20 && cp <= 0xFE2F) ||
|
|
208
|
+
(cp >= 0xE0100 && cp <= 0xE01EF)
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
200
212
|
function charWidth(ch) {
|
|
201
213
|
if (!ch) return 0;
|
|
202
214
|
const cp = ch.codePointAt(0);
|
|
203
215
|
if (cp === 9) return DEFAULT_SETTINGS.tabsize;
|
|
204
|
-
if (cp < 32 || (cp >= 0x7f && cp < 0xa0)) return 0;
|
|
216
|
+
if (cp < 32 || (cp >= 0x7f && cp < 0xa0) || isZeroWidthCodePoint(cp)) return 0;
|
|
205
217
|
if (isWideCodePoint(cp)) return 2;
|
|
206
218
|
return 1;
|
|
207
219
|
}
|
|
208
220
|
|
|
221
|
+
function isEmojiVariationBase(cp) {
|
|
222
|
+
return (
|
|
223
|
+
cp === 0x00A9 || cp === 0x00AE ||
|
|
224
|
+
cp === 0x203C || cp === 0x2049 ||
|
|
225
|
+
cp === 0x2122 || cp === 0x2139 ||
|
|
226
|
+
(cp >= 0x2194 && cp <= 0x21AA) ||
|
|
227
|
+
(cp >= 0x231A && cp <= 0x231B) ||
|
|
228
|
+
cp === 0x2328 || cp === 0x23CF ||
|
|
229
|
+
(cp >= 0x23E9 && cp <= 0x23F3) ||
|
|
230
|
+
(cp >= 0x23F8 && cp <= 0x23FA) ||
|
|
231
|
+
cp === 0x24C2 ||
|
|
232
|
+
(cp >= 0x25AA && cp <= 0x25AB) ||
|
|
233
|
+
cp === 0x25B6 || cp === 0x25C0 ||
|
|
234
|
+
(cp >= 0x25FB && cp <= 0x25FE) ||
|
|
235
|
+
(cp >= 0x2600 && cp <= 0x27BF) ||
|
|
236
|
+
(cp >= 0x2934 && cp <= 0x2935) ||
|
|
237
|
+
(cp >= 0x2B05 && cp <= 0x2B55) ||
|
|
238
|
+
cp === 0x3030 || cp === 0x303D ||
|
|
239
|
+
cp === 0x3297 || cp === 0x3299
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function displayUnitAt(text, idx) {
|
|
244
|
+
const cp = text.codePointAt(idx);
|
|
245
|
+
if (cp == null) return { text: "", width: 0, length: 0 };
|
|
246
|
+
let length = cp > 0xFFFF ? 2 : 1;
|
|
247
|
+
let unit = String.fromCodePoint(cp);
|
|
248
|
+
let width = charWidth(unit);
|
|
249
|
+
const nextCp = text.codePointAt(idx + length);
|
|
250
|
+
if (nextCp === 0xFE0F && isEmojiVariationBase(cp)) {
|
|
251
|
+
unit += String.fromCodePoint(nextCp);
|
|
252
|
+
length += 1;
|
|
253
|
+
width = 2;
|
|
254
|
+
}
|
|
255
|
+
return { text: unit, width, length };
|
|
256
|
+
}
|
|
257
|
+
|
|
209
258
|
function displayWidth(text) {
|
|
210
259
|
let width = 0;
|
|
211
|
-
for (
|
|
260
|
+
for (let i = 0; i < text.length;) {
|
|
261
|
+
const unit = displayUnitAt(text, i);
|
|
262
|
+
if (unit.length <= 0) break;
|
|
263
|
+
width += unit.width;
|
|
264
|
+
i += unit.length;
|
|
265
|
+
}
|
|
212
266
|
return width;
|
|
213
267
|
}
|
|
214
268
|
|
|
@@ -260,6 +314,16 @@ function charIdxForScrollRight(line, cursorX, visibleCols) {
|
|
|
260
314
|
return i;
|
|
261
315
|
}
|
|
262
316
|
|
|
317
|
+
function normalizeCharBoundary(line, idx) {
|
|
318
|
+
idx = clamp(idx, 0, line.length);
|
|
319
|
+
if (idx > 0 && idx < line.length) {
|
|
320
|
+
const prev = line.charCodeAt(idx - 1);
|
|
321
|
+
const cur = line.charCodeAt(idx);
|
|
322
|
+
if (prev >= 0xD800 && prev <= 0xDBFF && cur >= 0xDC00 && cur <= 0xDFFF) return idx - 1;
|
|
323
|
+
}
|
|
324
|
+
return idx;
|
|
325
|
+
}
|
|
326
|
+
|
|
263
327
|
// --- Softwrap utilities (ported from Go internal/display/softwrap.go) ---
|
|
264
328
|
|
|
265
329
|
// Returns an array of code-unit indices where each visual row starts.
|
|
@@ -581,7 +645,7 @@ class BufferModel {
|
|
|
581
645
|
|
|
582
646
|
ensureCursor() {
|
|
583
647
|
this.cursor.y = clamp(this.cursor.y, 0, this.lines.length - 1);
|
|
584
|
-
this.cursor.x =
|
|
648
|
+
this.cursor.x = normalizeCharBoundary(this.line(), this.cursor.x);
|
|
585
649
|
}
|
|
586
650
|
|
|
587
651
|
invalidateHighlightFrom(lineNo = 0, options = {}) {
|
|
@@ -1038,6 +1102,13 @@ class BufferModel {
|
|
|
1038
1102
|
}
|
|
1039
1103
|
}
|
|
1040
1104
|
}
|
|
1105
|
+
const syntaxWords = this.syntaxDefinition?.autocompleteWords ?? [];
|
|
1106
|
+
for (const w of syntaxWords) {
|
|
1107
|
+
if (w.length > wordLen && w.startsWith(word) && !seen.has(w)) {
|
|
1108
|
+
seen.add(w);
|
|
1109
|
+
suggestions.push(w);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1041
1112
|
if (suggestions.length === 0) return false;
|
|
1042
1113
|
if (suggestions.length === 1) {
|
|
1043
1114
|
// Single match: insert suffix directly without entering cycling mode
|
|
@@ -1252,6 +1323,7 @@ class TerminalPane {
|
|
|
1252
1323
|
this.app = app;
|
|
1253
1324
|
this.proc = null;
|
|
1254
1325
|
this.vt = null;
|
|
1326
|
+
this.decoder = new TextDecoder();
|
|
1255
1327
|
}
|
|
1256
1328
|
|
|
1257
1329
|
open(cols, rows) {
|
|
@@ -1269,7 +1341,8 @@ class TerminalPane {
|
|
|
1269
1341
|
cols,
|
|
1270
1342
|
rows,
|
|
1271
1343
|
data: (_terminal, data) => {
|
|
1272
|
-
const text = decoder.decode(data);
|
|
1344
|
+
const text = this.decoder.decode(data, { stream: true });
|
|
1345
|
+
if (!text) return;
|
|
1273
1346
|
const responses = this.vt.feed(text);
|
|
1274
1347
|
for (const resp of responses) this.proc?.terminal?.write(resp);
|
|
1275
1348
|
this.app.render();
|
|
@@ -1464,9 +1537,10 @@ class App {
|
|
|
1464
1537
|
const resize = this.screen.updateSize();
|
|
1465
1538
|
this.rows = resize.rows;
|
|
1466
1539
|
this.cols = resize.cols;
|
|
1540
|
+
this.layoutEditorArea();
|
|
1467
1541
|
for (const tab of this.tabs)
|
|
1468
1542
|
for (const p of tab.panes())
|
|
1469
|
-
if (p.type === "term") p.terminal?.resize(p.w, Math.max(4, p.h));
|
|
1543
|
+
if (p.type === "term") p.terminal?.resize(p.w, Math.max(4, p.h - 1));
|
|
1470
1544
|
if (!this.shellRunning && !this._alertRunning) this.render();
|
|
1471
1545
|
});
|
|
1472
1546
|
process.on("SIGINT", () => {}); // Ctrl+C is handled as copy in handleEvent
|
|
@@ -1500,9 +1574,7 @@ class App {
|
|
|
1500
1574
|
process.exit(code);
|
|
1501
1575
|
}
|
|
1502
1576
|
|
|
1503
|
-
|
|
1504
|
-
if (!this.running) return;
|
|
1505
|
-
const tab = this.tab;
|
|
1577
|
+
layoutEditorArea() {
|
|
1506
1578
|
const promptHeight = this.prompt ? 1 : 0;
|
|
1507
1579
|
const tabBarHeight = this.tabs.length > 1 ? 1 : 0;
|
|
1508
1580
|
const keymenuHeight = this.keymenu ? KEYDISPLAY.length : 0;
|
|
@@ -1517,15 +1589,40 @@ class App {
|
|
|
1517
1589
|
const editorAreaH = Math.max(1, this.rows - 1 - promptHeight - tabBarHeight - keymenuHeight - infoHeight);
|
|
1518
1590
|
const statusRow = this.rows - promptHeight - 1;
|
|
1519
1591
|
|
|
1592
|
+
for (const tab of this.tabs) computeLayout(tab.root, 0, editorAreaTop, this.cols, editorAreaH);
|
|
1593
|
+
|
|
1594
|
+
return {
|
|
1595
|
+
tabBarHeight,
|
|
1596
|
+
keymenuHeight,
|
|
1597
|
+
activeSuggestions,
|
|
1598
|
+
activeSuggestionIdx,
|
|
1599
|
+
activeMessage,
|
|
1600
|
+
suggestionsHeight,
|
|
1601
|
+
messageHeight,
|
|
1602
|
+
statusRow,
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
render() {
|
|
1607
|
+
if (!this.running) return;
|
|
1608
|
+
const tab = this.tab;
|
|
1609
|
+
const {
|
|
1610
|
+
tabBarHeight,
|
|
1611
|
+
keymenuHeight,
|
|
1612
|
+
activeSuggestions,
|
|
1613
|
+
activeSuggestionIdx,
|
|
1614
|
+
activeMessage,
|
|
1615
|
+
suggestionsHeight,
|
|
1616
|
+
messageHeight,
|
|
1617
|
+
statusRow,
|
|
1618
|
+
} = this.layoutEditorArea();
|
|
1619
|
+
|
|
1520
1620
|
const defaultStyle = this.context.colorscheme?.defaultStyle ?? {};
|
|
1521
1621
|
this.screen.fill(" ", defaultStyle);
|
|
1522
1622
|
|
|
1523
1623
|
this.tabRects = [];
|
|
1524
1624
|
if (tabBarHeight) this.renderTabbar(defaultStyle);
|
|
1525
1625
|
|
|
1526
|
-
// Compute pane rects for this tab
|
|
1527
|
-
computeLayout(tab.root, 0, editorAreaTop, this.cols, editorAreaH);
|
|
1528
|
-
|
|
1529
1626
|
// Center scroll for any buffer restored from savecursor (deferred until layout is known)
|
|
1530
1627
|
for (const p of tab.panes()) {
|
|
1531
1628
|
if (p.buffer?._pendingCenterScroll) {
|
|
@@ -1649,8 +1746,9 @@ class App {
|
|
|
1649
1746
|
if (softwrap) {
|
|
1650
1747
|
const scrollSloc = { line: buf.scroll.y, row: buf.scroll.row ?? 0 };
|
|
1651
1748
|
const cursorLine = buf.lines[buf.cursor.y] ?? "";
|
|
1749
|
+
const cursorX = normalizeCharBoundary(cursorLine, buf.cursor.x);
|
|
1652
1750
|
const cursorBreaks = softwrapBreaks(cursorLine, bufW, wordwrap, tabsize);
|
|
1653
|
-
const cursorSubRow = softwrapRowOfCharIdx(cursorBreaks,
|
|
1751
|
+
const cursorSubRow = softwrapRowOfCharIdx(cursorBreaks, cursorX);
|
|
1654
1752
|
const cursorSloc = { line: buf.cursor.y, row: cursorSubRow };
|
|
1655
1753
|
const cursorAbove = cursorSloc.line < scrollSloc.line ||
|
|
1656
1754
|
(cursorSloc.line === scrollSloc.line && cursorSloc.row < scrollSloc.row);
|
|
@@ -1659,10 +1757,12 @@ class App {
|
|
|
1659
1757
|
: slocDiff(buf.lines, scrollSloc, cursorSloc, bufW, wordwrap, tabsize);
|
|
1660
1758
|
cursorRow = p.y + visualRowOffset;
|
|
1661
1759
|
const segStart = cursorBreaks[cursorSubRow] ?? 0;
|
|
1662
|
-
cursorCol = p.x + gutterW + displayWidth(cursorLine.slice(segStart,
|
|
1760
|
+
cursorCol = p.x + gutterW + displayWidth(cursorLine.slice(segStart, cursorX));
|
|
1663
1761
|
} else {
|
|
1762
|
+
const line = buf.line();
|
|
1763
|
+
const cursorX = normalizeCharBoundary(line, buf.cursor.x);
|
|
1664
1764
|
cursorRow = p.y + buf.cursor.y - buf.scroll.y;
|
|
1665
|
-
cursorCol = p.x + gutterW + displayWidth(
|
|
1765
|
+
cursorCol = p.x + gutterW + displayWidth(line.slice(buf.scroll.x, cursorX));
|
|
1666
1766
|
}
|
|
1667
1767
|
|
|
1668
1768
|
const cursorVisible = cursorRow >= p.y && cursorRow < p.y + p.h && cursorCol >= p.x && cursorCol < p.x + p.w;
|
|
@@ -1891,11 +1991,16 @@ class App {
|
|
|
1891
1991
|
for (let col = 0; col < Math.min(pane.w, vt.cols); col++) {
|
|
1892
1992
|
const cell = vtRow[col];
|
|
1893
1993
|
if (!cell) continue;
|
|
1894
|
-
|
|
1994
|
+
const style = {
|
|
1895
1995
|
fg: cell.fg, bg: cell.bg,
|
|
1896
1996
|
bold: cell.bold, italic: cell.italic,
|
|
1897
1997
|
underline: cell.underline, reverse: cell.reverse,
|
|
1898
|
-
}
|
|
1998
|
+
};
|
|
1999
|
+
if (cell.filler) {
|
|
2000
|
+
this.screen.setFillerContent(pane.x + col, pane.y + 1 + row, style);
|
|
2001
|
+
continue;
|
|
2002
|
+
}
|
|
2003
|
+
this.screen.setContent(pane.x + col, pane.y + 1 + row, cell.ch || " ", style, cell.combining ?? []);
|
|
1899
2004
|
}
|
|
1900
2005
|
}
|
|
1901
2006
|
// Show VT cursor only when live (not scrolled back) and active
|
|
@@ -2316,6 +2421,7 @@ class App {
|
|
|
2316
2421
|
switch (seq) {
|
|
2317
2422
|
case "escape": {
|
|
2318
2423
|
this.pane.selection = null;
|
|
2424
|
+
this._markSelStart = null;
|
|
2319
2425
|
if (buf) buf.searchPattern = "";
|
|
2320
2426
|
const count = forceRehighlightDirtyLongLines(buf, this);
|
|
2321
2427
|
if (count > 0) this.message = `Rehighlighted ${count} long line${count === 1 ? "" : "s"}`;
|
|
@@ -2620,6 +2726,20 @@ class App {
|
|
|
2620
2726
|
case "alt-down":
|
|
2621
2727
|
await runAction("MoveLinesDown", this);
|
|
2622
2728
|
break;
|
|
2729
|
+
case "alt-d": //DedentSelection
|
|
2730
|
+
await runAction("OutdentSelection", this);
|
|
2731
|
+
break;
|
|
2732
|
+
case "alt-s": { //Mark selection start / extend selection to mark
|
|
2733
|
+
if (!this._markSelStart) {
|
|
2734
|
+
this._markSelStart = { ...buf.cursor };
|
|
2735
|
+
this.message = "selectionStart, ESC:cancel";
|
|
2736
|
+
} else {
|
|
2737
|
+
this.pane.selection = { start: { ...this._markSelStart }, end: { ...buf.cursor } };
|
|
2738
|
+
buf.cursor = { ...buf.cursor };
|
|
2739
|
+
this.message = "selectionEnd, ESC:cancel";
|
|
2740
|
+
}
|
|
2741
|
+
break;
|
|
2742
|
+
}
|
|
2623
2743
|
case "alt-p": //PreviousTab
|
|
2624
2744
|
await runAction("PreviousTab", this);
|
|
2625
2745
|
break;
|
|
@@ -4898,12 +5018,12 @@ function detectTtsCmd() {
|
|
|
4898
5018
|
}
|
|
4899
5019
|
|
|
4900
5020
|
// Linux / Android fallback: espeak-ng / espeak
|
|
4901
|
-
//
|
|
5021
|
+
// Speed: -s <wpm> (175 = normal), Pitch: -p <n> (0-99, 50 = normal)
|
|
4902
5022
|
for (const bin of ["espeak-ng", "espeak"]) {
|
|
4903
5023
|
if (runSync(["sh", "-c", `command -v ${bin}`], { stdout: "ignore", stderr: "ignore" }).ok) {
|
|
4904
5024
|
const spd = Math.round(175 * speed);
|
|
4905
5025
|
const pit = Math.max(0, Math.min(99, Math.round(50 * pitch)));
|
|
4906
|
-
return { cmd: [bin,
|
|
5026
|
+
return { cmd: [bin, '-s', spd, '-p', pit], via: "arg" };
|
|
4907
5027
|
}
|
|
4908
5028
|
}
|
|
4909
5029
|
|
|
@@ -5285,8 +5405,11 @@ function renderHighlightedCells(buf, lineNo, scrollX, maxWidth, colorscheme, sel
|
|
|
5285
5405
|
let i = scrollX;
|
|
5286
5406
|
while (i < raw.length && width < maxWidth) {
|
|
5287
5407
|
const cp = raw.codePointAt(i);
|
|
5288
|
-
const
|
|
5289
|
-
const
|
|
5408
|
+
const unit = displayUnitAt(raw, i);
|
|
5409
|
+
const ch = unit.text;
|
|
5410
|
+
const charLen = unit.length;
|
|
5411
|
+
const w = unit.width;
|
|
5412
|
+
if (charLen <= 0) break;
|
|
5290
5413
|
while (changeIndex + 1 < changes.length && i >= changes[changeIndex + 1][0]) changeIndex++;
|
|
5291
5414
|
const group = changes[changeIndex]?.[1] ?? "default";
|
|
5292
5415
|
const syntaxStyle = colorscheme?.get(group) ?? colorscheme?.defaultStyle ?? {};
|
|
@@ -5311,13 +5434,12 @@ function renderHighlightedCells(buf, lineNo, scrollX, maxWidth, colorscheme, sel
|
|
|
5311
5434
|
if (selected) {
|
|
5312
5435
|
style = { ...style, reverse: !style.reverse };
|
|
5313
5436
|
}
|
|
5314
|
-
const w = charWidth(ch);
|
|
5315
5437
|
if (ch === "\t") {
|
|
5316
5438
|
const spaces = Math.min(DEFAULT_SETTINGS.tabsize, maxWidth - width);
|
|
5317
5439
|
for (let j = 0; j < spaces; j++) cells.push({ ch: " ", style });
|
|
5318
5440
|
width += spaces;
|
|
5319
5441
|
} else if (w > 0 && width + w <= maxWidth) {
|
|
5320
|
-
cells.push({ ch, style,
|
|
5442
|
+
cells.push({ ch, style, width: w });
|
|
5321
5443
|
width += w;
|
|
5322
5444
|
}
|
|
5323
5445
|
i += charLen;
|
|
@@ -5333,20 +5455,29 @@ function renderHighlightedCells(buf, lineNo, scrollX, maxWidth, colorscheme, sel
|
|
|
5333
5455
|
function putText(screen, x, y, text, style = null, maxWidth = Infinity) {
|
|
5334
5456
|
let col = x;
|
|
5335
5457
|
let width = 0;
|
|
5336
|
-
|
|
5458
|
+
const str = String(text);
|
|
5459
|
+
for (let i = 0; i < str.length;) {
|
|
5337
5460
|
if (width >= maxWidth) break;
|
|
5461
|
+
const unit = displayUnitAt(str, i);
|
|
5462
|
+
const ch = unit.text;
|
|
5463
|
+
const w = unit.width;
|
|
5464
|
+
if (unit.length <= 0) break;
|
|
5338
5465
|
if (ch === "\t") {
|
|
5339
5466
|
const spaces = Math.min(DEFAULT_SETTINGS.tabsize, maxWidth - width);
|
|
5340
5467
|
for (let i = 0; i < spaces; i++) screen.setContent(col++, y, " ", style);
|
|
5341
5468
|
width += spaces;
|
|
5469
|
+
i += unit.length;
|
|
5470
|
+
continue;
|
|
5471
|
+
}
|
|
5472
|
+
if (w <= 0 || width + w > maxWidth) {
|
|
5473
|
+
i += unit.length;
|
|
5342
5474
|
continue;
|
|
5343
5475
|
}
|
|
5344
|
-
const w = charWidth(ch);
|
|
5345
|
-
if (w <= 0 || width + w > maxWidth) continue;
|
|
5346
5476
|
screen.setContent(col, y, ch, style);
|
|
5347
5477
|
if (w === 2) screen.setFillerContent(col + 1, y, style);
|
|
5348
5478
|
col += w;
|
|
5349
5479
|
width += w;
|
|
5480
|
+
i += unit.length;
|
|
5350
5481
|
}
|
|
5351
5482
|
return col;
|
|
5352
5483
|
}
|
|
@@ -5356,7 +5487,7 @@ function putCells(screen, x, y, cells, maxWidth = Infinity) {
|
|
|
5356
5487
|
let width = 0;
|
|
5357
5488
|
for (const cell of cells) {
|
|
5358
5489
|
if (width >= maxWidth) break;
|
|
5359
|
-
const w = charWidth(cell.ch);
|
|
5490
|
+
const w = cell.width ?? charWidth(cell.ch);
|
|
5360
5491
|
if (w <= 0 || width + w > maxWidth) continue;
|
|
5361
5492
|
screen.setContent(col, y, cell.ch, cell.style);
|
|
5362
5493
|
if (w === 2) screen.setFillerContent(col + 1, y, cell.style);
|
package/src/plugins/js-bridge.js
CHANGED
|
@@ -180,6 +180,11 @@ function registerBuiltinActions() {
|
|
|
180
180
|
buf.modified = true;
|
|
181
181
|
}
|
|
182
182
|
});
|
|
183
|
+
// Aliases for OutdentSelection / OutdentLine
|
|
184
|
+
reg("DedentSelection", (app) => ACTIONS.get("OutdentSelection")(app));
|
|
185
|
+
reg("UnindentSelection", (app) => ACTIONS.get("OutdentSelection")(app));
|
|
186
|
+
reg("DedentLine", (app) => ACTIONS.get("OutdentLine")(app));
|
|
187
|
+
reg("UnindentLine", (app) => ACTIONS.get("OutdentLine")(app));
|
|
183
188
|
|
|
184
189
|
// Editing
|
|
185
190
|
reg("Backspace", (app) => app.buffer?.backspace());
|
package/src/screen/screen.js
CHANGED
|
@@ -59,7 +59,19 @@ export class Screen {
|
|
|
59
59
|
let out = "\x1b[?25l";
|
|
60
60
|
let activeStyleKey = null;
|
|
61
61
|
for (const { x, y, cell } of changes) {
|
|
62
|
-
if (cell.filler) continue; // right-half of a wide char; the
|
|
62
|
+
if (cell.filler) continue; // right-half of a wide char; the base cell covers this column
|
|
63
|
+
// If this is a wide char (next cell is its filler), clear the filler column with
|
|
64
|
+
// default style first. On narrow-emoji terminals this leaves a default-bg blank
|
|
65
|
+
// at the right-half column instead of stale cursor-line / syntax background, so
|
|
66
|
+
// the area next to the glyph doesn't look like a colored block "covering" it.
|
|
67
|
+
// On wide-emoji terminals the glyph's right half overwrites the blank harmlessly.
|
|
68
|
+
const nextCell = this.cells.getContent(x + 1, y);
|
|
69
|
+
if (nextCell?.filler) {
|
|
70
|
+
out += this.move(y + 1, x + 2);
|
|
71
|
+
out += styleToAnsi({});
|
|
72
|
+
activeStyleKey = "";
|
|
73
|
+
out += " ";
|
|
74
|
+
}
|
|
63
75
|
out += this.move(y + 1, x + 1);
|
|
64
76
|
if (cell.styleKey !== activeStyleKey) {
|
|
65
77
|
out += styleToAnsi(cell.style ?? {});
|