char-slop/berry
multipurpose self-modifiable agentic harness
git clone https://git.t4t.associates/char-slop/berry
c5dd844
main
1import { highlight } from "@berry/api/web.ts" ; 2import { type Extension , type Range , StateEffect , StateField } from "@codemirror/state" ; 3import { 4Decoration , 5type DecorationSet , 6EditorView , 7ViewPlugin , 8type ViewUpdate , 9} from "@codemirror/view" ; 10 11export function highlighting ( path :string , render = highlight ) :Extension { 12const set = StateEffect . define < DecorationSet >(); 13const tokens = StateField . define < DecorationSet >({ 14create :() => Decoration . none , 15update ( value , transaction ) { 16for ( const effect of transaction . effects ) if ( effect . is ( set )) return effect . value ; 17return value . map ( transaction . changes ); 18}, 19provide :( field ) => EditorView . decorations . from ( field ), 20}); 21return [ 22tokens , 23ViewPlugin . fromClass ( 24class { 25timer :ReturnType < typeof setTimeout >; 26disposed = false ; 27constructor ( readonly view :EditorView ) { 28this . timer = setTimeout (() => void this . light (), 0 ); 29} 30update ( update :ViewUpdate ) { 31if ( ! update . docChanged ) return ; 32clearTimeout ( this . timer ); 33this . timer = setTimeout (() => void this . light (), 150 ); 34} 35async light () { 36const doc = this . view . state . doc ; 37const lines = await render ( doc . toString (), { path}). catch (() => null ); 38if ( ! lines || this . disposed || this . view . state . doc !== doc ) return ; 39const marks :Range < Decoration >[] = []; 40for ( let i = 0 ; i < Math . min ( lines . length , doc . lines ); i ++ ) { 41let at = doc . line ( i + 1 ). from ; 42const visit = ( node :Node ) => { 43const start = at ; 44if ( node . nodeType === 3 ) at += node . textContent ! . length ; 45else { 46for ( const child of node . childNodes ) visit ( child ); 47if ( node instanceof Element && / ^a-[a-z]+$ / . test ( node . localName ) && start < at ) { 48marks . push ( Decoration . mark ({ tagName :node . localName }). range ( start , at )); 49} 50} 51}; 52for ( const node of lines [ i ]) visit ( node ); 53} 54this . view . dispatch ({ effects :set . of ( Decoration . set ( marks , true )) }); 55} 56destroy () { 57this . disposed = true ; 58clearTimeout ( this . timer ); 59} 60}, 61), 62]; 63}