Welcome to Konilo! _| _| _| _| _| _| _|_| _|_|_| _| _|_| _|_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _|_| _| _| _| _| _|_| the tool for thinking For some starting points, try `catalogue` to browse the blocks or `tuhi` to start an editor. If your system includes the documentation blocks, load them with `* documentation` and use `manual` or `describe wordname` to access this. Please explore, and adapt the system to meet your needs. (startup) (set_blocks,_load_extensions) . You should setup the numbers of blocks in your system. #128 !Blocks . Load desired extensions. As Konilo uses a single shared . buffer for blocks, I wrap these in a quote, and make `call` . the last item in this block. This ensures proper behavior. [ @Blocks [ #128 !Blocks '(std) needs '(termina) needs '(tuhi) needs '(nonix) needs '(catalogue) needs '(rem) needs '(describe) needs '(man) needs ] dip !Blocks ] call(startup) (local_configuration) . You should adjust these to match your terminal settings if . using the (termina) based programs. #75 !ti:width #20 !ti:height . Set the preferred editor to use with `catalogue` [ (n-) set load tuhi ] !Editor . This will restrict `needs` to the first 8,192 blocks [ (s-) @Blocks [ #8,192 !Blocks needs ] dip !Blocks ] \needs . This will display the startup message in block 0 [ #0 set load list* nl ] gcCopyright (c) Charles Childers Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (std) (constants) . Constants for numeric range limits. :n:MIN #-2,147,483,647 ; :n:MAX #2,147,483,646 ; . Constants for flags. :TRUE #-1 ; :FALSE #0 ; . Constants for memory layout :sys:BUFFERS #60,000 ; :sys:EOM #65,535 ; (std) (s:) (constants) :s:DIGITS '0123456789ABCDEF ; :s:VOWELS 'aeiouAEIOU ; :s:ASCII-UPPERCASE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ; :s:ASCII-LOWERCASE 'abcdefghijklmnopqrstuvwxyz ; :s:ASCII-LETTERS 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ; 's:WHITESPACE d:create #4 comma #9 comma #10 comma #13 comma #32 comma :s:PUNCTUATION '_!"#$%&'()*+,-./:;<=>?@[\]^`{|}~ ; :s:CONSONANTS 'bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ ; (std) (c:) (classification) :c:consonant? (c-f) s:CONSONANTS swap s:contains? ; :c:vowel? (c-f) s:VOWELS swap s:contains? ; :c:letter? (c-f) s:ASCII-LETTERS swap s:contains? ; :c:digit? (c-f) s:DIGITS swap s:contains? ; :c:whitespace? (c-f) s:WHITESPACE swap s:contains? ; :c:visible? (c-f) #32 #126 n:between? ; :c:-consonant? (c-f) c:consonant? not ; :c:-vowel? (c-f) c:vowel? not ; :c:-letter? (c-f) c:letter? not ; :c:-digit? (c-f) c:digit? not ; :c:-whitespace? (c-f) c:whitespace? not ; :c:-uppercase? (c-f) c:uppercase? not ; :c:-lowercase? (c-f) c:lowercase? not ; :c:-visible? (c-f) c:visible? not ; (std) (c:) (conversions) :c:toggle-case dup c:lowercase? &c:to-upper &c:to-lower choose ; (std) (n:) (even,odd,sign,square,sqrt) :n:odd? (n-f) #1 and #1 eq? ; :n:even? (n-f) n:odd? not ; :n:negative? (n-f) #0 lt? ; :n:positive? (n-f) #0 gt? ; :n:strictly-positive? (n-f) #1 gteq? ; :n:square (n-n) dup n:mul ; :~guess dup-pair n:div over n:sub #2 n:div ; :n:sqrt (n-n) #1 [ ~guess &n:add sip ] while nip ; :n:sign (n-n) n:negative? [ #-1 ] [ #1 ] choose ; (std) (v:) (a:) :v:preserve (aq-) swap dup fetch [ &call dip ] dip swap store ; :v:inc-by (an-) [ fetch n:add ] sip store ; :v:dec-by (an-) [ fetch swap n:sub ] sip store ; :v:on (a-) #-1 swap store ; :v:off (a-) #0 swap store ; :v:update (aq-) swap [ fetch swap call ] sip store ; :v:limit (alu-) [ [ dup fetch ] dip ] dip n:limit swap store ; :a:new (ns-) d:create dup comma allot ; (std) (buffer:) {{ 'Start var 'Ptr var :at @Start @Ptr ; :update @Ptr @Start store ; ---reveal--- :buffer:size (-n) at nip ; :buffer:end (-a) at n:inc n:add ; :buffer:start (-a) @Start ; :buffer:empty (-) #0 !Ptr update ; :buffer:add (na-) at a:store &Ptr v:inc update ; :buffer:get (a-) &Ptr v:dec at a:fetch update ; :buffer:set (a-) !Start #0 !Ptr update ; }} (std) (s:) (begins-with,ends-with) :~prepare dup s:length &swap dip ; :s:begins-with? (ss-f) ~prepare s:left &s:hash bi@ eq? ; :s:ends-with? (ss-f) ~prepare s:right &s:hash bi@ eq? ; (std) (s:) (contains/s?) (index/s) (target) '~tar var '~tar.l var (source) '~src var '~src.l var :~setup s:keep [ s:length !~tar.l ] [ !~tar ] bi s:keep [ s:length !~src.l ] [ !~src ] bi ; :s:contains/s? (ss-f) [ ~setup #0 @~src.l @~tar.l n:sub n:inc [ @~src I @~tar.l s:middle @~tar s:eq? or ] indexed-times ] gc ; :s:index/s (ss-n) [ ~setup #65535 @~src.l @~tar.l n:sub n:inc [ @~src I @~tar.l s:middle @~tar s:eq? [ I n:min ] if ] indexed-times ] gc ; (std) (bit:) (bit-access) :bit:get (vi-b) [ #1 swap shift-left and ] sip shift-right ; :bit:set (vi-v) #1 swap shift-left or ; :bit:clear (vi-v) #1 swap shift-left not and ; (std) (b:) (byte-addressing) 'Byte var :byte-mask (xn-b) #255 swap #8 n:mul dup [ shift-left and ] dip shift-right ; [ drop @Byte ] [ [ drop @Byte ] dip ] [ [ [ drop @Byte ] dip ] dip ] [ [ [ [ drop @Byte ] dip ] dip ] dip ] 'replacements d:create comma comma comma comma :replace &replacements n:add fetch call ; (std) (b:) (byte-addressing) :b:to-byte-address (a-a) #4 n:mul ; :b:unpack (c-bbbb) dup #255 and swap dup #8 shift-right #255 and swap dup #16 shift-right #255 and swap #24 shift-right #255 and ; :b:pack (bbbb-c) #24 shift-left swap #16 shift-left n:add swap #8 shift-left n:add swap n:add ; (std) (b:) (byte-addressing) :b:fetch (a-b) #4 n:divmod swap #4 n:divmod rot n:add fetch swap byte-mask ; :b:store (ba-) swap !Byte #4 n:divmod swap [ dup fetch b:unpack ] dip replace b:pack swap store ; (std) (pali) (assembler) 'Instructions d:create #30 comma #5861473 comma #5863578 comma #5863326 comma #5863323 comma #5863823 comma #5863722 comma #5863716 comma #5863524 comma #5863273 comma #5863275 comma #5863282 comma #5863772 comma #5863355 comma #5863640 comma #5863589 comma #5863424 comma #5863376 comma #5863820 comma #5863210 comma #5863821 comma #5863623 comma #5863314 comma #5863220 comma #5863686 comma #5863980 comma #5863812 comma #5863818 comma #5863288 comma #5863297 comma #5863485 comma :inst s:hash &Instructions swap a:index ; (std) (pali) (assembler) :~split (s-nnnn) dup #2 s:left inst swap dup #2 #2 s:middle inst swap dup #4 #2 s:middle inst swap #2 s:right inst ; :assemble:opcode (s-n) ~split b:pack ; :i (s-) assemble:opcode comma ; &comma \d (n-) &comma \r (n-) :s (s-) dup s:length comma &comma s:for-each ; :code: ("-) 'liju.... i here #4 n:add comma s:get/token d:create ; &code: \label: ("-) (std) (reorder,_roll,_unroll) (restructuring-the-stack) {{ &sys:buffers/reserved \values :from s:length dup [ [ &values n:add store ] sip n:dec ] times drop ; :to &n:inc &s:length bi [ fetch-next $a n:sub n:inc &values n:add fetch swap ] times drop ; ---reveal--- :reorder (...ss-?) &from dip to ; }} :roll (abc-cab) swap &swap dip ; :unroll (cba-abc) roll roll ; (std) (reset) (quickly-empty-the-stack) :reset (...-) depth/data dup n:negative? [ n:abs [ #0 ] ] [ &drop ] choose times ; (std) (.s) (display-stack) :~gather depth/data dup &sys:buffers/reserved store-next swap &store-next times drop ; :~display &sys:buffers/reserved a:reverse [ n:put sp ] a:for-each ; :~restore &sys:buffers/reserved a:reverse [ ] a:for-each ; :.s (-) ~gather ~display ~restore ; (std) (debug/dump) {{ :to-digit (n-c) '0123456789ABCDEF swap s:fetch ; :h. (n-) #16 n:divmod swap [ to-digit c:put ] bi@ sp ; :order 'abcd 'dcba reorder ; :bytes (n-n) dup b:unpack order #4 &h. times ; :display (nn-n) bytes sp n:put nl ; ---reveal--- :dump (an-) [ dup n:put tab fetch-next display ] times drop ; }} (std) (random-number-generator) (xorshift) #1 'seed var-n :n:random (-n) @seed dup #13 shift-left xor dup #17 shift-right xor dup #5 shift-left xor dup !seed ; :n:random-mod (n-n) n:random n:abs swap n:mod ; . Note: this works well for small projects, but lacks some . range due to ilo's lack of unsigned numbers. (std) (block-tools) :block:empty? (n-f) @Block [ set load block:buffer n:dec s:hash #-967633659 eq? ] dip !Block load ; :block:for-each (q-) @Blocks [ [ I set load block:buffer swap call ] sip ] indexed-times drop ; :block:first-matching (s-n) @Blocks swap [ s:keep [ n:dec over s:begins-with? [ [ I n:min ] dip ] if ] block:for-each drop ] gc ; (std) (block-tools) :block:title (-s) block:buffer n:dec #64 over store ; :block:name (-s) block:title dup #32 s:index/c s:left ; 'block:Sets var :block:set:init (-) here !block:Sets #0 comma @Blocks #4 n:div allot ; :block:set:known? (-f) @block:Sets block:name s:hash a:contains? ; :block:set:add (-) block:name s:hash @block:Sets dup fetch a:store @block:Sets v:inc ; (std) (editor-ext) &sys:buffers/reserved #64 n:add \Line :e:copy (n-) e:to-line &Line #64 copy ; :e:paste (n-) e:to-line &Line swap #64 copy ; :e:cut (n-) dup e:copy #32 swap e:to-line #64 fill ; :~get '_ s:temp #64 over store [ n:inc #64 copy ] sip ; :~update n:inc swap #64 copy ; :~at e:to-line dup ~get ; :e:indent (n-) ~at #62 s:left '__ s:prepend ~update ; :e:unindent (n-) ~at #62 s:right '__ s:append ~update ; (std) (editor-ext) :e:for-each-line (q-) #16 [ block:buffer n:dec I #64 n:mul #64 s:middle swap &call sip ] indexed-times drop ; :n (-) next @e:Display call ; :p (-) prev @e:Display call ; [ @e:Display call ] \l (std) (fixed-point) #100 'f:scale var-n (ff-f) &n:add \f:add (ff-f) &n:sub \f:sub (ff-f) :f:mul n:mul @f:scale n:div ; (ff-f) :f:div [ @f:scale n:mul ] dip n:div ; (----) :~pad @f:scale n:to-s s:length n:dec over n:to-s s:length n:sub [ $0 c:put ] times ; (f-) :f:put @f:scale n:divmod n:put $. c:put ~pad n:put ; (std) (invoke,_*) :invoke (ss-) dup d:exists? &nip [ swap needs ] choose d:lookup d:address fetch call ; :~title ("-n) s:get/token '(LOAD: s:prepend ') s:append ; :* ("-) #0 set load ~title block:first-matching set load @Block @Blocks n:dec -eq? [ &[ n:abs call run &] n:abs call call ] if ; . `invoke` takes a block set and a word to run, if the word is . found, it will load the block set, then run the word . `*` takes the name of a LOAD: block. This will have a title of. `(LOAD:name)` and will contain a list of words that load the . dependencies and active block set. (std) (s:trim) :s:trim-right (s-s) s:temp [ dup v:dec [ s:last #32 lteq? ] sip swap ] while dup v:inc dup s:last #32 eq? [ dup v:dec ] if ; '~Start var '~End var '~Len var :~end dup s:length dup !~Len over n:add n:inc !~End n:inc ; :~size @~Start over swap n:sub @~Len swap n:sub ; :s:trim-left (s-s) s:dup dup #0 s:fetch #32 eq? [ dup !~Start ~end [ fetch-next #32 -eq? over @~End -eq? and ] while ~size (patch over store ) ] if ; :s:trim (s-s) s:trim-left s:trim-right ; nonix : a unix-inspired set of words for working with the blocks This provides: +--------+--------------+-------------------------------------+ | cp | src dest | copy block src to block dest | | mv | src dest | move block src to block dest | | rm | block | erase block | | cat | block | display contents of a block (text) | | locate | text | show blocks starting with text | | xcp | src dest num | copy num blocks from src to dest | | xmv | src dest num | move num blocks from src to dest | | xrm | start num | remove num blocks starting at start | | clear | | clear the screen | +--------+--------------+-------------------------------------+ (nonix) (basic-commands) :cp n:get set load n:get set save ; :rm n:get set new save ; :mv n:get dup set load n:get set save set new save ; :cat n:get set load list* ; :~to-title n:dec #64 over store ; :~match I n:put tab #60000 s:put nl ; :locate [ s:get/line s:keep [ ~to-title over s:contains/s? &~match if ] block:for-each ] gc drop ; :clear (-) vt:clear vt:home ; (nonix) (extended-commands) {{ :relocate over set load dup set save ; :erase over set new save ; :next &n:inc bi@ ; :args n:get n:get n:get ; ---reveal--- :xmv ("from,to,count") args [ relocate erase next ] times drop-pair ; :xcp ("from,to,count") args [ relocate next ] times drop-pair ; :xrm ("start,count") n:get n:get swap set [ new save next ] times ; }} (opt:nonix) (df:_summarize_block_usage) :~usage (-nn) #0 #0 @Blocks [ I block:empty? &n:inc [ &n:inc dip ] choose ] indexed-times ; :df (-) ~usage [ 'Used:___ s:put n:put nl ] [ 'Unused:_ s:put n:put nl ] bi* ; (opt:nonix) (block-map) 'Density var :~sym (-s) '.123456789ABCDEFG ; :~block# (-n) J #16 n:mul I n:add ; :~empty? (-f) ~block# block:empty? ; :~record (f-) [ &Density v:inc ] -if ; :~break I n:-zero? I #64 n:mod n:zero? and &nl if ; :~map ~break ~sym @Density s:fetch c:put ; :~collect #0 !Density #16 [ ~empty? ~record ] indexed-times ; :~pages (-n) @Blocks #16 n:div ; :block-map ~pages [ ~collect ~map ] indexed-times nl ; . This will generate a 64 column output of the block usage. It . counts the blocks used in each 16 block page, and displays a . value from 1-G to indicate the used blocks. . is used for nil.(opt:nonix) (full-block-search) :~to-title n:dec ; :~match I n:put sp ; :blocks-containing (s-) [ s:keep [ ~to-title over s:contains/s? &~match if ] block:for-each ] gc drop nl ; :blocks-containing: ("-) s:get/line blocks-containing ; (LOAD:opt:nonix) '(opt:nonix) needs (LOAD:documentation) '(describe) needs '(man) needs '------------------------------------------------- s:put nl 'For_glossary_lookups,_do: s:put nl nl '__describe_name s:put nl nl 'To_browse_the_manual,_run_`manual`. s:put nl '------------------------------------------------- s:put nl (opt:editor) (indention,_unindention) :~new d:create dup 'liliju.. i comma n:inc ; :~i ~new &e:indent comma ; :~u ~new &e:unindent comma ; #0 '0i ~i '1i ~i '2i ~i '3i ~i '4i ~i '5i ~i '6i ~i '7i ~i '8i ~i '9i ~i '10i ~i '11i ~i '12i ~i '13i ~i '14i ~i '15i ~i drop #0 '0u ~u '1u ~i '2u ~u '3u ~u '4u ~u '5u ~u '6u ~u '7u ~i '8u ~u '9u ~u '10u ~u '11u ~u '12u ~u '13u ~i '14u ~u '15u ~u drop (opt:editor) (cut,_copy,_paste) :~x ~new &e:cut comma ; (cut) :~c ~new &e:copy comma ; (copy) :~p ~new &e:paste comma ; (paste) #0 '0x ~x '1x ~x '2x ~x '3x ~x '4x ~x '5x ~x '6x ~x '7x ~x '8x ~x '9x ~x '10x ~x '11x ~x '12x ~x '13x ~x '14x ~x '15x ~x drop #0 '0c ~c '1c ~c '2c ~c '3c ~c '4c ~c '5c ~c '6c ~c '7c ~c '8c ~c '9c ~c '10c ~c '11c ~c '12c ~c '13c ~c '14c ~c '15c ~c drop #0 '0p ~p '1p ~p '2p ~p '3p ~p '4p ~p '5p ~p '6p ~p '7p ~p '8p ~p '9p ~p '10p ~p '11p ~p '12p ~p '13p ~p '14p ~p '15p ~p drop (LOAD:opt:editor) '(opt:editor) needs manual ========================================================= The manual is structured as a wiki, with blocks forming the datanodes. Links start with a *, and glossary data starts with a +. A manual browser is provided, as well as a vocabulary for doing lookups at the Listener. (man) (configuration,_helper_words) :man:START (-n) #8,192 ; (man) (locate-blocks) :~target (ss-s) s:temp swap s:prepend '_ s:append s:keep ; :~target/lower (ss-s) ~target s:to-lower s:keep ; :~title (-s) block:buffer n:dec #64 over store next ; :~match? (ss-sf) over s:begins-with? ; :~range (-n) man:START n:dec set load #2048 ; :man:locate (s-n) [ 'man:_ swap ~target/lower #0 swap ~range [ ~title ~match? [ [ I n:max ] dip ] if ] indexed-times drop man:START n:add ] gc ; :glossary:locate (s-n) [ 'Glossary:_ swap ~target #0 swap ~range [ ~title ~match? [ [ I n:max ] dip ] if ] indexed-times drop man:START n:add ] gc ; (man) (display-block,_find_and_display_block) :~display-char (c-) dup $* eq? &fg:red if dup $+ eq? &fg:cyan if dup #32 eq? &vt:reset if c:put ; :~line #64 [ fetch-next ~display-char ] times vt:reset nl ; :~title fg:white bg:blue #64 [ fetch-next c:put ] times vt:reset nl ; :~render block:buffer ~title #15 &~line times drop ; :man s:get/token man:locate set load ~render ; :man:list ~render ; (man) (exits?,_new,_edit) :man:exists? (s-f) man:locate n:-zero? ; :glossary:exists? (s-f) glossary:locate n:-zero? ; :man:new (-) 'start man:locate set load [ next @Block block:empty? ] until @Block @Editor call ; :man:edit (s-) [ s:keep dup man:exists? [ man:locate @Editor call ] [ drop man:new ] choose ] gc ; (man) (new,_with_prompt) :man:new/prompt (-) 'start man:locate set load [ next @Block block:empty? ] until @Block set load #0 e:erase/line &~Query 'New_page_name: ti:prompt #0 @~Query s:to-lower 'man:_ s:prepend e:replace save @Block @Editor call ; (man) (browser) :~man:prompt (s-s) &~Query swap ti:prompt @~Query s:keep ; :man:* [ 'Page_name: ~man:prompt dup man:exists? [ man:locate set load ] [ drop man:new ] choose ] gc ; :man:+ [ 'Word_name: ~man:prompt dup glossary:exists? [ glossary:locate set load ] [ drop man:new ] choose ] gc ; :man:1 'start man:locate set load ; :man:8 @Block @Editor call ; (man) (browser) (key-bindings) :man:actions (-) &man:1 $1 ti:set-action &man:8 $8 ti:set-action &man:* $* ti:set-action &man:+ $+ ti:set-action &man:new/prompt $3 ti:set-action [ #63 ti:help ] $? ti:set-action &ti:done $0 ti:set-action &prev $[ ti:set-action &next $] ti:set-action ; (man) (browser) :man:hints 'Start #1 ti:add-hint 'Edit #8 ti:add-hint 'New #3 ti:add-hint 'Quit #0 ti:add-hint 'manual ti:set-title ; :man:display (-) vt:clear vt:home man:list ; :man:browser 'start man:locate set load [ &man:actions &man:hints &man:display ] ti:application ; &man:browser \manual describe This adds a word, `describe`, that scans the blocks for glossarydata. It takes a word name from the input stream, and looks for a block with a title of `Glossary: wordname` In example, to display the glossary data for `s:put`, you would run: describe s:put The output strips blank lines. Note that as this requires one block per word it is not a space efficient tool. You will need around 250 blocks to cover the core language, and many more to cover everything. (describe) (glossary-lookups) :describe:word (s-) @Block roll [ s:prepend s:keep @Blocks [ I set load block:buffer n:dec over dup s:length &swap dip s:left &s:hash bi@ eq? &list* if ] indexed-times drop ] gc !Block load ; :describe (') s:get/token 'Glossary:_ describe:word ; man shortcuts ================================================== * enter *, then the man page name to jump to that page. this will start the editor if a page does not exist. 1 jump to *Start in the wiki 3 start the editor on a new page 8 edit the current page 0 quit the man browser ? bring up this help screen Termina : A Vocabulary for Terminal Applications =============== There are two parts to Termina. The first is a set of words for interacting with a DEC compatible terminal. The second builds onthese to provide a scaffold for building textual, keyboard centric programs. Termina : Notes on Memory Usage To store the hot key pointers and hints text, Termina makes use of part of the memory in sys:buffers/reserved. If using a non- standard image, you may need to update the addresses in the Termina source code. (termina) (terminal-config) . Variables used for some positioning calculations. I suggest . setting these in your startup blocks. #80 'ti:width var-n #24 'ti:height var-n #-1 'vt:EnableColors var-n :vt:colored &vt:EnableColors v:on ; :vt:mono &vt:EnableColors v:off ; (termina) (support;_cursor_movement;_clear_screen) . Helper words :vt:esc (-) #27 c:put ; :vt:csi (-) vt:esc $[ c:put ; . Words for moving the cursor :vt:home (-) vt:csi $H c:put ; :vt:row,col (nn-) vt:csi swap n:put $; c:put n:put $H c:put ; :vt:up (-) vt:csi n:put $A c:put ; :vt:down (-) vt:csi n:put $B c:put ; :vt:right (-) vt:csi n:put $C c:put ; :vt:left (-) vt:csi n:put $D c:put ; :vt:clear (-) vt:csi '2J s:put ; :vt:reset vt:csi '0m s:put ; (termina) (colors) :vt:set/color (n-) @vt:EnableColors [ vt:csi n:put $m c:put ] &drop choose ; :fg:black #30 vt:set/color ; :bg:black #40 vt:set/color ; :fg:red #31 vt:set/color ; :bg:red #41 vt:set/color ; :fg:green #32 vt:set/color ; :bg:green #42 vt:set/color ; :fg:yellow #33 vt:set/color ; :bg:yellow #43 vt:set/color ; :fg:blue #34 vt:set/color ; :bg:blue #44 vt:set/color ; :fg:magenta #35 vt:set/color ; :bg:magenta #45 vt:set/color ; :fg:cyan #36 vt:set/color ; :bg:cyan #46 vt:set/color ; :fg:white #37 vt:set/color ; :bg:white #47 vt:set/color ; (termina) (key-to-action-mapping) &sys:buffers/reserved #256 n:add \ti:Actions #128 !ti:Actions :ti:set-action (qc-) &ti:Actions swap a:store ; :ti:reset-actions (-) #128 [ #0 I ti:set-action ] indexed-times ; :ti:get-action (c-q) &ti:Actions swap a:fetch ; :ti:perform-action (c-) ti:get-action dup n:-zero? &call &drop choose ; :ti:input (-) c:get ti:perform-action ; (termina) (keyboard-hints) {{ &ti:Actions #130 n:add \ti:Hints :empty (-s) '____________ ; :constrain (s-s) dup s:length #12 gt? [ #12 s:left ] if ; :pad (s-s) #32 empty n:inc #12 fill empty &n:inc bi@ over n:dec fetch copy empty ; :start (n-a) #13 n:mul &ti:Hints n:add ; :display (-) I n:inc dup #10 eq? [ drop #0 ] if dup n:put sp start s:put sp ; :clean (-) '_ s:temp constrain pad I start #13 copy ; ---reveal--- :ti:add-hint (sn-) #13 n:mul &ti:Hints n:add [ constrain pad ] dip #13 copy ; :ti:reset-hints (-) #10 &clean indexed-times ; :ti:hints #10 [ display I #4 eq? &nl if ] indexed-times ; }} (termina) (display) 'ti:Title d:create #24 allot :ti:set-title &ti:Title s:copy ; :ti:display/none ; &ti:display/none 'ti:Display var-n :ti:set-display (a-) !ti:Display ; :ti:reset-display (-) &ti:display/none ti:set-display ; :ti:display (-) vt:home @ti:Display call @ti:height #3 n:sub #0 vt:row,col @ti:width [ $- c:put ] times nl ti:hints @ti:Title n:-zero? [ @ti:height #3 n:sub #0 vt:row,col '--[_ s:put &ti:Title s:put '_] s:put nl nl ] if nl ; (termina) (nested-applications-support) 'ti:ptrs d:create #0 comma #5 allot :ti:add-program (a-) &ti:ptrs v:inc &ti:ptrs @ti:ptrs a:store ; :ti:current (-a) &ti:ptrs @ti:ptrs a:fetch ; :ti:more? (-f) @ti:ptrs n:-zero? ; :ti:remove &ti:ptrs v:dec ; :ti:load (-) ti:current call #0 !ti:Title !ti:Display ti:reset-hints call ti:reset-actions call ; (termina) (application-loop) 'ti:Done var :ti:done #-1 !ti:Done vt:reset nl ; :ti:done? @ti:Done ; :ti:application/run (-) [ #0 !ti:Done ti:display ti:input ti:done? ] until ti:remove ti:more? [ ti:load #0 !ti:Done ] if ; :ti:application (q-) ti:add-program ti:load ti:application/run ; (termina) (prompt) . This implements a pop-up prompt frame for use with Termina . programs. . #7 'FrameRow var-n #5 'FrameCol var-n &bg:white '~PopupBG var-n &fg:black '~TextColor var-n &fg:blue '~InputColor var-n (termina) (prompt) :~bar (rc-) vt:row,col @~PopupBG call @~TextColor call #64 [ $- c:put ] times vt:reset ; :~mid (rc-) vt:row,col @~PopupBG call @~TextColor call $| c:put #62 &sp times $| c:put vt:reset ; :~frame (-) @FrameRow @FrameCol ~bar @FrameRow n:inc @FrameCol ~mid @FrameRow #2 n:add @FrameCol ~mid @FrameRow #3 n:add @FrameCol ~mid @FrameRow #4 n:add @FrameCol ~bar ; (termina) (prompt) :~prompt (as"-) @FrameRow #2 n:add @FrameCol #2 n:add vt:row,col @~PopupBG call @~TextColor call s:put sp @~InputColor call s:get/line swap store vt:reset ; :ti:prompt (as-) ~frame ~prompt ; (termina) (ti:help) {{ 'ti:Help var 'ti:Help/Prior var :ti:help/actions &ti:done $0 ti:set-action ; :ti:help/hints 'Quit #0 ti:add-hint 'help ti:set-title ; :ti:help/display vt:clear vt:home @ti:Help set load list* ; ---reveal--- :ti:help (n-) @Block !ti:Help/Prior !ti:Help [ &ti:help/actions &ti:help/hints &ti:help/display ] ti:application @ti:Help/Prior set load ; }} catalogue : block browser ====================================== The catalogue is a program for exploring the blocks. It divides blocks into pages of 16 blocks, and allows flipping through the pages, listing the titles to provide some insight into what eachblock contains. Shortcut keys are provided to jump directly to the page holding a specific block (4), or leaping to the page with the first block matching a specified title (9). It also includes a quick viewer for blocks, support for renaming blocks (changing the title line), and loading the blocks into the Tuhi editor. (catalogue) (block-viewer) :~hints 'Previous #1 ti:add-hint 'Next #2 ti:add-hint 'Quit #0 ti:add-hint 'block_viewer ti:set-title ; :~actions &prev $1 ti:set-action &next $2 ti:set-action &ti:done $0 ti:set-action ; :~display clear list# ; :block-viewer [ &~actions &~hints &~display ] ti:application ; (catalogue) (variables,_actions) #0 'Page var-n &edit 'Editor var-n '~Query var :constrain @Page #0 @Blocks #16 n:div n:dec n:limit !Page ; :action (n-) ti:done @Page #16 n:mul n:add @Editor call ; :catalogue:rename &~Query 'Block_ID_(a-p): ti:prompt @~Query #0 s:fetch $a n:sub @Page #16 n:mul n:add set load &~Query 'New_title: ti:prompt #0 e:erase/line #0 @~Query e:replace save ; (catalogue) (actions,_continued) :catalogue:jump &~Query 'Block_Number: ti:prompt @~Query s:to-n #16 n:div !Page constrain ; :catalogue:leap [ &~Query 'First_part_of_block_title: ti:prompt @~Query s:keep #0 set load [ block:buffer n:dec over s:begins-with? next @Block @Blocks n:dec eq? or ] until drop prev ] gc @Block #16 n:div !Page constrain ; :catalogue:list &~Query 'Block_ID_(a-p): ti:prompt @~Query #0 s:fetch $a n:sub @Page #16 n:mul n:add set load block-viewer ; (catalogue) (key-bindings) :catalogue:actions/a-i [ #0 action ] $a ti:set-action [ #1 action ] $b ti:set-action [ #2 action ] $c ti:set-action [ #3 action ] $d ti:set-action [ #4 action ] $e ti:set-action [ #5 action ] $f ti:set-action [ #6 action ] $g ti:set-action [ #7 action ] $h ti:set-action [ #8 action ] $i ti:set-action ; (catalogue) (key-bindings) :catalogue:actions/j-p [ #9 action ] $j ti:set-action [ #10 action ] $k ti:set-action [ #11 action ] $l ti:set-action [ #12 action ] $m ti:set-action [ #13 action ] $n ti:set-action [ #14 action ] $o ti:set-action [ #15 action ] $p ti:set-action ; (catalogue) (key-bindings) :catalogue:actions catalogue:actions/a-i catalogue:actions/j-p &ti:done $0 ti:set-action [ &Page v:dec constrain ] $1 ti:set-action [ &Page v:inc constrain ] $2 ti:set-action &catalogue:list $3 ti:set-action &catalogue:jump $4 ti:set-action &catalogue:rename $8 ti:set-action &catalogue:leap $9 ti:set-action [ #95 ti:help ] $? ti:set-action ; (catalogue) (hints) :catalogue:hints 'Previous #1 ti:add-hint 'Next #2 ti:add-hint 'Display #3 ti:add-hint 'Rename #8 ti:add-hint 'Quit #0 ti:add-hint 'Jump #4 ti:add-hint 'Leap #9 ti:add-hint 'catalogue ti:set-title ; (catalogue) (display) {{ :sep '_|_ s:put ; :key I $a n:add c:put ; :entry @Page #16 n:mul I n:add ; :title entry set load block:buffer n:dec #64 over store s:put ; :num entry n:put nl ; ---reveal--- :catalogue:display vt:clear vt:home #16 [ key sep title sep num ] indexed-times ; }} (catalogue) (top-level) :catalogue (-) [ &catalogue:actions &catalogue:hints &catalogue:display ] ti:application ; &catalogue \catalog catalogue shortcuts ============================================ 1 Display previous page of blocks 2 Display next page of blocks 3 Display a block. Enter this, then the block letter. 8 Rename a block. Press this, the block letter, then enter the new name. End with enter. 4 Leap to a new page. Enter this, then the block number. 9 Leap to a new page. Enter this, then the first part of the block title. 5 Run the code in a block. Enter this, then the block letter. 0 Quit the catalogue and return to the listener. ? Displays this help screen Enter a block letter (a-p) to load it in the editor. tuhi : termina block editor ==================================== This is designed to be similar in spirit to the basic editor in Konilo, but makes use of the (termina) words to present a hotkeydriven interface for editing. Tuhi has two display modes: - plain text shown as a single color - source code shown with syntax highlighting Syntax mode will be used if the block starts with a "(" and `tuhi:cfg/syntax` is set to true (non-zero). In other cases the plain text mode is used. (tuhi) (configuration) &fg:cyan 'tuhi:cfg/colors,line# var-n &bg:black 'tuhi:cfg/colors,bg var-n &fg:green 'tuhi:cfg/colors,fg var-n #-1 'tuhi:cfg/syntax var-n #0 'tuhi:cfg/status var-n #-1 'tuhi:cfg/bar var-n (tuhi) (list:syntax) (default-colors) :~colon bg:black fg:red ; (: :~immed bg:black fg:yellow ; (word:_[_]_; :~number bg:black fg:cyan ; (# :~char bg:black fg:blue ; ($ :~string bg:black fg:white ; (' :~pointer bg:black fg:magenta ; (& :~comment bg:blue fg:white ; (( :~var bg:black fg:magenta ; (@_or_! :~normal bg:black fg:green ; '~SigilColors d:create #9 comma &~colon comma &~number comma &~char comma &~string comma &~pointer comma &~comment comma &~var comma &~var comma &~immed comma (tuhi) (list:syntax) (helpers) ':#$'&(@! s:keep \~Sigils '~last var :~sigil? (c-cf) &~Sigils over s:contains? ; :~color-sigil (c-c) &~Sigils over s:index/c &~SigilColors swap a:fetch call ; :~immed? (c-cf) dup [ $[ eq? ] [ $] eq? ] [ $; eq? ] tri or or @~last #32 eq? and ; :~space? (c-cf) dup #32 eq? ; :~prepare (n-an) #64 n:mul block:buffer n:add #64 #32 !~last ; :~comment? (an-anf) over fetch $. eq? ; (tuhi) (list:syntax) (display) :e:line/syntax (n-) ~prepare ~comment? [ ~comment [ fetch-next c:put ] times ] [ [ fetch-next ~sigil? [ @~last #32 eq? &~color-sigil if ] if ~space? [ @~last #32 -eq? &~normal if ] if ~immed? &~immed if dup !~last c:put ] times ] choose vt:reset @tuhi:cfg/bar [ sp $| c:put ] if nl drop ; :~line# I dup #10 lt? &sp if n:put sp ; :list:syntax (-) &tuhi:cfg/bar v:off #16 [ ~line# I e:line/syntax ] indexed-times &tuhi:cfg/bar v:on ; (tuhi) (display) {{ :status @tuhi:cfg/status &sys:info if ; :line# @tuhi:cfg/colors,line# call I $a n:add c:put ; :sep vt:reset '_|_ s:put ; :text @tuhi:cfg/syntax block:buffer fetch $( eq? and [ I e:line/syntax ] [ @tuhi:cfg/colors,bg @tuhi:cfg/colors,fg &call bi@ I e:to-line #64 [ fetch-next c:put ] times drop vt:reset sp $| c:put nl ] choose ; :reset @tuhi:cfg/syntax [ bg:black fg:white ] if ; ---reveal--- :tuhi:display (-) vt:clear vt:home #16 [ line# sep text reset ] indexed-times status 'tuhi_# @Block n:to-s s:append ti:set-title ; }} (tuhi) (key-actions) (lines) :tuhi:a #1 #5 vt:row,col 0 ; :tuhi:b #2 #5 vt:row,col 1 ; :tuhi:c #3 #5 vt:row,col 2 ; :tuhi:d #4 #5 vt:row,col 3 ; :tuhi:e #5 #5 vt:row,col 4 ; :tuhi:f #6 #5 vt:row,col 5 ; :tuhi:g #7 #5 vt:row,col 6 ; :tuhi:h #8 #5 vt:row,col 7 ; :tuhi:i #9 #5 vt:row,col 8 ; :tuhi:j #10 #5 vt:row,col 9 ; :tuhi:k #11 #5 vt:row,col 10 ; :tuhi:l #12 #5 vt:row,col 11 ; :tuhi:m #13 #5 vt:row,col 12 ; :tuhi:n #14 #5 vt:row,col 13 ; :tuhi:o #15 #5 vt:row,col 14 ; :tuhi:p #16 #5 vt:row,col 15 ; :tuhi:4 &~Query 'Block_number: ti:prompt @~Query s:to-n !Block load ; :tuhi:9 &~Query 'First_part_of_block_title: ti:prompt @~Query block:first-matching !Block load ; (tuhi) (key-actions) :tuhi:[ c:get $a n:sub e:unindent ; :tuhi:] c:get $a n:sub e:indent ; :tuhi:C c:get $a n:sub e:copy ; :tuhi:V c:get $a n:sub e:paste ; :tuhi:X c:get $a n:sub e:cut ; :tuhi:? #111 ti:help ; :tuhi:R @Block [ block:name needs ] dip !Block load ; :tuhi:Q @tuhi:cfg/status not !tuhi:cfg/status ; :tuhi:N new ; :tuhi:+ &tuhi:cfg/syntax v:on ; :tuhi:- &tuhi:cfg/syntax v:off ; (tuhi) (key-actions) (tuhi) (setup-key-actions-part-1) :tuhi:actions/1 (-) &prev $1 ti:set-action &next $2 ti:set-action &tuhi:4 $4 ti:set-action &run $5 ti:set-action &save $6 ti:set-action &load $7 ti:set-action &tuhi:9 $9 ti:set-action &ti:done $0 ti:set-action &tuhi:a $a ti:set-action &tuhi:b $b ti:set-action &tuhi:c $c ti:set-action &tuhi:d $d ti:set-action &tuhi:e $e ti:set-action &tuhi:f $f ti:set-action &tuhi:g $g ti:set-action &tuhi:h $h ti:set-action &tuhi:i $i ti:set-action &tuhi:j $j ti:set-action &tuhi:k $k ti:set-action &tuhi:l $l ti:set-action &tuhi:m $m ti:set-action &tuhi:n $n ti:set-action &tuhi:o $o ti:set-action &tuhi:p $p ti:set-action ; (tuhi) (setup-key-actions-part-2) :tuhi:actions/2 (-) &tuhi:[ $[ ti:set-action &tuhi:] $] ti:set-action &tuhi:C $C ti:set-action &tuhi:V $V ti:set-action &tuhi:X $X ti:set-action &tuhi:Q $Q ti:set-action &tuhi:? $? ti:set-action &tuhi:N $N ti:set-action &tuhi:+ $+ ti:set-action &tuhi:- $- ti:set-action &tuhi:R $R ti:set-action ; :tuhi:actions (-) tuhi:actions/1 tuhi:actions/2 ; (tuhi) (hints,_main_loop) :tuhi:hints (-) 'Previous #1 ti:add-hint 'Next #2 ti:add-hint 'Jump #4 ti:add-hint 'Run #5 ti:add-hint 'Save #6 ti:add-hint 'Load #7 ti:add-hint 'Leap #9 ti:add-hint 'Quit #0 ti:add-hint 'tuhi ti:set-title ; :tuhi (-) [ &tuhi:actions &tuhi:hints &tuhi:display ] ti:application ; tuhi shortcuts ================================================= Editing ========================================================a - p line entry [ un-indent line N erase block contents ] indent line X cut C copy V paste R run all blocks in the current set Display ========================================================Q toggle status line ? display this help screen + enable syntax highlighting - disable syntax highlighting rem : visual block editor ====================================== rem is a block editor. It builds on the basic editor and tuhi, but presents a more visual editing model. In rem you move a cursor around the block, and enter code at the point where the cursor appears. Edits do not erase the entire line. qwertyuiop ',.pyfgcrl -------#-- Movement is performed by asdfghjkl; aoeuidhtns ------###- the ijkl or chtk keys, to zxcvbnm,./ ;qjkxbmwvz ---------- support qwerty & dvorak a -> enter code N -> erase block contents R -> run blocks in set < -> unindent r -> run current block > -> indent rem will display the block number as part of the title text. (rem) (display) 'Col var 'Row var :~cursor @Row n:inc @Col #4 n:add dup-pair vt:row,col bg:red fg:white $* c:put vt:row,col vt:reset ; :~redraw vt:home block:buffer fetch $( eq? &list:syntax &list# choose ; :rem:display ~redraw ~cursor 'rem_# @Block n:to-s s:append ti:set-title ; (rem) (hints) :rem:hints 'Previous #1 ti:add-hint 'Next #2 ti:add-hint 'Enter #5 ti:add-hint 'Save #6 ti:add-hint 'Load #7 ti:add-hint 'Quit #0 ti:add-hint 'Jump #4 ti:add-hint 'Leap #9 ti:add-hint ; (rem) (editing,movement) :~constrain @Row #0 #15 n:limit !Row @Col #0 #63 n:limit !Col ; :~up &Row v:dec ~constrain ; :~dn &Row v:inc ~constrain ; :~lf &Col v:dec ~constrain ; :~rt &Col v:inc ~constrain ; :~enter @Row @Col ~cursor bg:blue fg:white s:get/line e:replace-at vt:reset clear ; (rem) (keymap) :~edit &~enter $5 ti:set-action &~enter $a ti:set-action [ @Row e:indent ] $> ti:set-action [ @Row e:unindent ] $< ti:set-action [ @Row e:cut ] $X ti:set-action [ @Row e:copy ] $C ti:set-action [ @Row e:paste ] $V ti:set-action &tuhi:N $N ti:set-action &tuhi:R $R ti:set-action &tuhi:r $r ti:set-action &save $6 ti:set-action &load $7 ti:set-action &ti:done $0 ti:set-action [ #127 ti:help ] $? ti:set-action ; (rem) (keymap) :~cursor-nav &~up $i ti:set-action &~lf $j ti:set-action &~dn $k ti:set-action &~rt $l ti:set-action &~up $c ti:set-action &~lf $h ti:set-action &~dn $t ti:set-action &~rt $n ti:set-action ; :~block-nav &prev $1 ti:set-action &next $2 ti:set-action &tuhi:9 $9 ti:set-action (leap) &tuhi:4 $4 ti:set-action (jump) ; :rem:actions ~cursor-nav ~block-nav ~edit ; (rem) (top-level) :rem clear [ &rem:actions &rem:hints &rem:display ] ti:application ; rem ============================================================ +---------------+--------+--------+ | Action | Qwerty | Dvorak | +===============+========+========+ | Up | i | c | | Down | k | t | | Left | j | h | | Right | l | s | +---------------+--------+--------+----------------+---+ | Indent Line | > | Run Block | r | | Unindent Line | < | Run Set | R | | Cut Line | X | Erase Contents | N | | Copy Line | C | Enter Text | a | | Paste Line | V | | | +---------------+-----------------+----------------+---+