/
editor.fs
1371 lines (1026 loc) · 28.2 KB
/
editor.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\ MIT/X11 License
\ Copyright (c) 2012-2015 Sean Pringle <sean.pringle@gmail.com>
\
\ Permission is hereby granted, free of charge, to any person obtaining
\ a copy of this software and associated documentation files (the
\ "Software"), to deal in the Software without restriction, including
\ without limitation the rights to use, copy, modify, merge, publish,
\ distribute, sublicense, and/or sell copies of the Software, and to
\ permit persons to whom the Software is furnished to do so, subject to
\ the following conditions:
\
\ The above copyright notice and this permission notice shall be
\ included in all copies or substantial portions of the Software.
\
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
\ OR IMPLIED, ADD1LUDING BUT NOT LIMITED TO THE WARRANTIES OF
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
\ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
\ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
\ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
\ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ Reforth Editor -- re
\
\ Sean Pringle <sean.pringle@gmail.com>, Jan 2013:
\
\ This editor is influenced by vi(m) but much simplified and designed to
\ take advantage of the Forth shell. It's also small and easy to hack!
\
\ I was never a vim power-user but did become attached to some of the
\ basic command-mode controls. The subset supported here allow me to
\ move between here and vim without tripping up... much. YMMV.
: help ( -- )
macro
\ Compile a comment as a string, and type it.
: \ ( -- )
sys:source @ dup "\n" match drop at! 0 c!+ dup at 1- <>
if 1+ end string, 'type word, 'cr word, at sys:source ! ;
normal
\ Usage: re [file]
\
\ COMMAND mode uses macro editing controls and word-based navigation.
\
\ ------------------------------------------------------------
\ | i | Enter INSERT mode at the caret |
\ | o | Insert a blank line and enter INSERT mode |
\ | m | Mark the current line |
\ | c | Add a virtual cursor |
\ | s | Remove virtual cursors |
\ | y | Copy from mark to current line |
\ | / | Search for text by posix regex |
\ | \ | Set replacement text |
\ | n | Search for next occurrence |
\ | r | Replace current search match |
\ | d | Copy and delete from mark to current line |
\ | p | Paste copied text after current line |
\ | g | Go to the marked line |
\ | u | Undo last change |
\ | : | Access the Forth shell |
\ | Insert | Enter INSERT mode (same as 'i') |
\ ------------------------------------------------------------
\
\ COMMAND mode keys can be modified with prefixes:
\
\ ------------------------------------------------------------
\ | 10g | Go to line 10 |
\ | $g | Go to last line (end of file) |
\ | 5d | Delete 5 lines after the cursor |
\ ------------------------------------------------------------
\
\ Convenient Forth shorthand words:
\
\ ------------------------------------------------------------
\ | w | Save the file |
\ | q | Exit the editor |
\ | wq | w q |
\ | ? | Wait for a key stroke |
\ ------------------------------------------------------------
\
\ INSERT Mode uses "normal" text editing controls and navigation.
\
\ ------------------------------------------------------------
\ | Escape | Exit INSERT mode |
\ | Insert | Exit INSERT mode |
\ ------------------------------------------------------------
\
\ An example status line:
\
\ (0) -- INSERT -- 77,35 s[alpha] r[beta] c[20] editor.fs
\
\ ------------------------------------------------------------
\ | (0) | Forth Stack (zero items) |
\ | -- INSERT -- | Editor mode |
\ | 77 | Current line |
\ | 35 | Current column |
\ | n[alpha] | Current search regex is "alpha" |
\ | r[beta] | Current replace string is "beta" |
\ | c[20] | Current command mode key modifier |
\ | <path> | Current file |
\ ------------------------------------------------------------
;
0 value file
0 value caret
0 value size
0 value mode
-1 value marker
4 value tabsize
create name 100 allot
create tmp 100 allot
create cmd 100 allot
"HOME" getenv "%s/.reclip"
format string clipboard
stack undos
stack redos
: bounds? ( n -- n' )
dup 0 < swap size >= or ;
: bounds ( n -- n' )
size min 0 max ;
: ncopy ( a n -- b )
dup my! 1+ allocate dup at! my cmove 0 at my + c! at ;
: fcopy ( -- a )
file size ncopy ;
: copy ( a -- b )
dup count ncopy ;
: white? ( c -- f )
dup \s = swap \t = or ;
: cscan ( a c -- a' )
my! begin dup c@ dup my = swap 0= or until 1+ end ;
: cskip ( a c -- a' )
my! begin dup c@ my = while 1+ end ;
: rows ( -- n )
max-xy nip ;
: cols ( -- n )
max-xy drop ;
: undo! ( -- )
undos.top file 0 compare if caret undos.push fcopy undos.push end ;
: redo! ( -- )
redos.top file 0 compare if caret redos.push fcopy redos.push end ;
: expand ( -- )
size 1+ to size file size 1+ resize to file ;
: shrink ( -- )
size 1- to size caret bounds to caret ;
: point ( -- a )
file caret + ;
: char ( -- c )
point c@ ;
: line ( -- n )
0 file at! caret for c@+ \n = if 1+ end end ;
: lines ( -- n )
1 file at! size for c@+ \n = if 1+ end end ;
: insert ( c -- )
expand point dup 1+ place point c! ;
: remove ( -- c )
char caret size < if point dup 1+ swap place shrink end ;
: left ( -- )
caret 1- 0 max to caret ;
: right ( -- )
caret 1+ size min to caret ;
: home ( -- )
caret for left char right \n = until left end ;
: away ( -- )
point \n cscan file - to caret ;
: position ( -- n )
caret home caret over to caret - ;
: reposition ( n -- )
home for caret size < while char \n = until right end ;
: up ( -- )
position home left reposition ;
: down ( -- )
position away right reposition ;
: pgup ( -- )
rows 2/ for up end ;
: pgdown ( -- )
rows 2/ for down end ;
: goto ( l -- )
0 to caret for away right end ;
: inserts ( text -- )
at! caret begin c@+ dup while insert right end drop to caret ;
: mark ( -- )
caret home caret to marker to caret ;
: unmark ( -- )
-1 to marker ;
: remark ( -- )
marker 0< if mark end marker ;
: range ( -- n )
remark away right caret over over min to caret - abs unmark ;
: clip ( s -- )
clipboard blurt drop ;
: yank ( -- )
caret here dup at! range for char c!+ right end 0 c!+ clip to caret ;
: paste ( -- )
away right clipboard slurp dup inserts free ;
: delete ( -- )
here dup at! range for remove c!+ end 0 c!+ clip ;
: rename ( name -- )
name place name basename "\e]0;%s\a" print ;
: close ( -- )
0 to caret unmark 0 to size 0 file c! ;
: read ( -- )
name slurp dup at! if at inserts end ;
: open ( name -- )
close rename read ;
: reopen ( -- )
close read ;
: write ( -- )
file name blurt drop ;
: revert ( s -- )
caret swap close inserts size min to caret ;
: undo ( -- )
redo! undos.pop dup if revert undos.pop to caret else drop end ;
: redo ( -- )
undo! redos.pop dup if revert redos.pop to caret else drop end ;
create srch 100 allot
create repl 100 allot
: stringlit ( s -- a )
sys:source @ swap "/%s/" format sys:source ! sys:sparse swap sys:source ! ;
: search ( -- )
: forward ( a -- )
file - bounds to caret ;
srch stringlit tmp place
right
point tmp match if forward exit end drop
file tmp match if forward exit end drop
left ;
: replace ( -- )
point srch stringlit match swap point = and
if
point dup srch stringlit split
drop swap place repl stringlit inserts
end ;
: blat ( s -- )
here swap place, create , does @ type ;
"\e[K" blat erase
"\e[?25h" blat cursor-on
"\e[?25l" blat cursor-off
"\e7" blat cursor-save
"\e8" blat cursor-back
"\e[?7h" blat wrap-on
"\e[?7l" blat wrap-off
\ Default 16 color mode
"\e[39;22m" blat fg-normal
"\e[34;22m" blat fg-comment
"\e[35;22m" blat fg-string
"\e[36;22m" blat fg-number
"\e[33;22m" blat fg-keyword
"\e[39;22m" blat fg-coreword
"\e[39;22m" blat fg-variable
"\e[39;22m" blat fg-constant
"\e[31;22m" blat fg-define
"\e[39;22m" blat fg-status
"\e[49;22m" blat bg-normal
"\e[49;1m" blat bg-active
"\e[47;22m" blat bg-marked
"\e[49;1m" blat bg-status
: colors ( -- )
: xterm-color ( r g b -- n )
: xcolor? ( n -- f )
dup 0= over 5Eh > or swap 55 - 0 max 40 mod 0= and ;
: color? ( r g b -- r g b f )
dup xcolor? push rot
dup xcolor? push rot
dup xcolor? push rot
pop pop pop and and ;
: grey? ( r g b -- r g b f )
push over over = my! pop over over = my and ;
: scale ( n -- n' )
55 - 0 max 20 + 40 / ;
: to-color ( r g b -- n )
scale swap scale 6 * + swap scale 36 * + 16 + ;
: to-grey ( r g b -- n )
swap 8 shl or swap 16 shl or 657930 / 232 + ;
grey? push color? 0= pop and
if to-grey else to-color end
0 max 255 min ;
: escseq ( n -- s )
"\e[%d;5;%dm" format here swap place, ;
: fg-256 ( r g b -- a )
xterm-color 38 escseq ;
: bg-256 ( r g b -- a )
xterm-color 48 escseq ;
\ xterm 256-color mode
"TERM" getenv "256color" match?
"COLORTERM" getenv "gnome-terminal" match? or
if
: re ( s xt -- )
sys:xt-body @ @ ! ;
D8h D8h D8h fg-256 'fg-normal re
66h 66h 66h fg-256 'fg-comment re
\ 82h AAh 8Ch fg-256 'fg-comment re
82h AAh 8Ch fg-256 'fg-string re
8Ch C8h C8h fg-256 'fg-number re
F0h DCh AFh fg-256 'fg-keyword re
FFh FFh FFh fg-256 'fg-coreword re
C0h BEh D0h fg-256 'fg-variable re
C8h 91h 91h fg-256 'fg-constant re
F0h F0h 8Ch fg-256 'fg-define re
FFh FFh FFh fg-256 'fg-status re
30h 30h 30h bg-256 'bg-normal re
40h 40h 40h bg-256 'bg-active re
40h 40h 40h bg-256 'bg-marked re
00h 00h 00h bg-256 'bg-status re
end ;
: status ( -- )
fg-status bg-status 0 rows at-xy ;
create input 100 allot
: menu ( options -- item )
static locals
0 value select
0 value options
end
to options 0 to select 0 input !
: eol ( a -- a' )
\n cscan ;
: sol ( a -- a' )
\n cskip ;
: hit? ( a -- f )
input dup count compare 0= ;
: hit+ ( a -- a' )
input c@ if begin dup c@ while dup hit? until eol sol end end ;
: input! ( a n -- )
my! input my cmove 0 input my + c! ;
: hit! ( -- )
options hit+ select for eol hit+ end dup at! eol at - dup my! if at my input! end ;
: sel! ( -- )
options select for eol sol end dup eol over - input! ;
: hits ( -- n )
0 options begin hit+ dup at! c@ while 1+ at eol sol end ;
: items ( -- n )
0 options begin dup at! c@ while 1+ at eol sol end ;
: item. ( a i -- )
select = if bg-active end space dup at! eol at - for c@+ emit end space bg-status ;
: draw ( -- n )
space space options begin hit+ dup c@ while dup i item. eol sol end drop ;
: select+ ( n -- )
select + input c@ if hits else items end 1- min 0 max to select ;
input 100 edit:start
begin
status "menu> " type edit:show
cursor-save draw cursor-back
edit:step my!
my \e =
if
edit:escseq dup count 1- + c@ my!
my \e = if 0 edit:input ! leave end
edit:away
my `C = if 1 select+ next end
my `D = if -1 select+ next end
next
end
my \n =
if
input c@ 0<> hits 0> and if hit! leave end
input c@ 0= if sel! leave end
leave
end
end
edit:stop drop input ;
: accept ( buf lim -- f )
"\e7" type
edit:start
begin
"\e8" type
edit:show
edit:step my!
my 27 =
"" edit:escseq? and
if
0 edit:input !
false leave
end
my 10 =
if
true leave
end
end
edit:stop drop ;
: listen ( s -- f )
status type 0 input ! input 100 accept ;
: command ( -- )
"> " listen if wrap-on space input evaluate drop end ;
: srch! ( -- )
"search> " listen if input srch place end ;
: repl! ( -- )
"replace> " listen if input repl place end ;
: put ( c -- )
drop ;
\ Hooks
: huh ( -- ) ;
: indent ( -- ) ;
: complete ( -- a ) "notags!" ;
: syntax ( -- ) ;
: clean ( -- ) ;
: gap? ( c -- f ) white? ;
: default ( -- )
: syn ( -- )
char put right ;
: ind ( -- )
caret up home tmp at!
begin char white? while char c!+ right end
0 c!+ to caret tmp at!
begin c@+ dup while insert right end drop ;
: rtrim ( -- )
caret
0 to caret
begin
char while away 0
begin left char white? while 1+ end
right dup my! for remove drop end
caret over < if my - end right
end
to caret ;
: rtabs ( -- )
caret
0 to caret
begin
char while
char \t =
if
remove drop
tabsize for \s insert end
caret over < if tabsize 1- + end
end
right
end
to caret ;
: cln ( -- )
rtrim ;
: com ( -- a )
static locals
stack words
end
: keep ( s -- )
at! words.depth
for
i cells words.base + @ at at count compare 0=
exit?
end
at copy words.push ;
begin
words.depth while
words.pop free
end
file copy dup at!
begin
at c@ while
at "\s+" split
at keep swap at! while
end
free
: cmp ( s1 s2 -- f )
dup count compare 0< ;
'cmp words.base words.depth sort
here
words.depth
for
i cells words.base + @
dup count push over place pop +
at! \n c!+ at
end
drop here ;
'ind is indent
'cln is clean
'com is complete
'syn is syntax ;
: reforth ( -- )
: syn ( -- )
: shunt ( -- )
char put right ;
: cword? ( c -- )
point at! c@+ = c@+ space? and ;
: whites ( -- )
begin char while char space? while shunt end ;
: comment ( -- )
whites begin char while char shunt `) = until end ;
: comment2 ( -- )
begin char while char \n = until shunt end ;
: word ( -- )
whites begin char while char space? until shunt end ;
: string ( -- )
shunt begin char dup my! while shunt my `" = until my `\ = if shunt end end ;
whites char 0= exit?
`( cword?
if fg-comment comment exit end
`\ cword?
if fg-comment comment2 exit end
`" char =
if fg-string string exit end
point "^:\s+[^[:blank:]]+" match?
if fg-keyword word fg-define word exit end
point "^(if|else|end|for|i|begin|while|until|exit[?]?|leave[?]?|next[?]?|value|variable|create|does|record|field|static|to|is|;)\s" match?
if fg-keyword word exit end
point "^[-]?[0-9a-fA-F]+[hb]?\s" match?
if fg-number word exit end
fg-normal word ;
default
'syn is syntax ;
: php ( -- )
: syn ( -- )
: shunt ( -- )
char put right ;
: name? ( c -- f )
dup my! alpha? my digit? my `_ = or or ;
: whites ( -- )
begin char while char space? while shunt end ;
: comment ( -- )
begin char while char \n = until shunt end ;
: comment2 ( -- )
begin char while point shunt "^\*/" match? if shunt leave end end ;
: word ( -- )
whites begin char name? while shunt end ;
: string ( delim -- )
char shunt begin char dup my! while shunt my over = until my `\ = if shunt end end drop ;
whites char 0= exit?
point at! c@+ my!
my `/ = at c@ `/ = and
if fg-comment comment exit end
my `/ = at c@ `* = and
if fg-comment comment2 exit end
my `" = my `' = or
if fg-string string exit end
my `$ =
if fg-variable shunt word exit end
point "^(function|class)\s+[^[:blank:]]+" match?
if fg-keyword word fg-define word exit end
point "^(if|else|elsif|switch|case|for|foreach|while|function|class|return|var|new|public|private|static|const)[^a-zA-Z0-9_]" match?
if fg-keyword word exit end
point "^[-]{0,1}(0x|[0-9]){1}[0-9a-fA-F]*" match?
if fg-number shunt word exit end
fg-normal
my name?
if word exit end
shunt ;
: gap ( c -- f )
dup my! white? my `, = or my `. = or my `( = or my `) = or ;
: cln ( -- )
default:rtrim default:rtabs ;
default
'gap is gap?
'cln is clean
'syn is syntax ;
: c99 ( -- )
: syn ( -- )
: shunt ( -- )
char put right ;
: name? ( c -- f )
dup my! alpha? my digit? my `_ = or or ;
: whites ( -- )
begin char while char space? while shunt end ;
: comment ( -- )
begin char while char \n = until shunt end ;
: comment2 ( -- )
begin char while point shunt "^\*/" match? if shunt leave end end ;
: word ( -- )
whites begin char name? while shunt end ;
: string ( delim -- )
char shunt begin char dup my! while shunt my over = until my `\ = if shunt end end drop ;
whites char 0= exit?
point at! c@+ my!
my `/ = at c@ `/ = and
if fg-comment comment exit end
my `/ = at c@ `* = and
if fg-comment comment2 exit end
my `" = my `' = or
if fg-string string exit end
my `# =
if fg-define shunt word exit end
point "^(if|else|elsif|for|while|return|int|char|void|typedef|struct|unsigned)[^a-zA-Z0-9_]" match?
if fg-keyword word exit end
point "^[-]{0,1}(0x|[0-9]){1}[0-9a-fA-F]*" match?
if fg-number shunt word exit end
fg-normal
my name?
if word exit end
shunt ;
: gap ( c -- f )
dup my! white? my `, = or my `. = or my `( = or my `) = or ;
default
'gap is gap?
'syn is syntax ;
: html ( -- )
: syn ( -- )
: shunt ( -- )
char put right ;
: whites ( -- )
begin char while char space? while shunt end ;
: tag ( -- )
whites begin char alpha? char digit? or while shunt end ;
: string ( delim -- )
char shunt begin char dup my! while shunt my over = until my `\ = if shunt end end drop ;
whites char my!
my 0= exit?
my `" = my `' = or
if fg-string string exit end
my `< =
if
point "^<[a-zA-Z]+.*>" match?
if shunt fg-keyword tag exit end
point "^</[a-zA-Z]+>" match?
if shunt shunt fg-keyword tag exit end
end
point "^[a-zA-Z]+=" match?
if fg-variable tag exit end
fg-normal shunt ;
: gap ( c -- f )
dup my! white? my `> = or my `< = or my `= = or ;
: cln ( -- )
default:rtrim name "corvus" match? 0= if default:rtabs end ;
default
'gap is do-gap?
'cln is do-clean
'syn is do-syntax ;
: markdown ( -- )
: syn ( -- )
: shunt ( -- )
char put right ;
: whites ( -- )
begin char while char space? while shunt end ;
: heading ( -- )
begin char while char \n = until shunt end ;
whites char 0= exit?
point at! c@+ my!
my `# =
if fg-keyword heading exit end
fg-normal
shunt ;
: gap ( c -- f )
white? ;
: cln ( -- )
default:rtrim default:rtabs ;
default
'gap is gap?
'cln is clean
'syn is syntax ;
: puppet ( -- )
: syn ( -- )
: shunt ( -- )
char put right ;
: name? ( c -- f )
dup my! alpha? my digit? my `_ = or or ;
: whites ( -- )
begin char while char space? while shunt end ;
: comment ( -- )
begin char while char \n = until shunt end ;
: comment2 ( -- )
begin char while point shunt "^\*/" match? if shunt leave end end ;
: word ( -- )
whites begin char name? while shunt end ;
: string ( delim -- )
char shunt begin char dup my! while shunt my over = until my `\ = if shunt end end drop ;
whites char 0= exit?
point at! c@+ my!
my `# =
if fg-comment comment exit end
my `/ = at c@ `* = and
if fg-comment comment2 exit end
my `" = my `' = or
if fg-string string exit end
my `$ =
if fg-variable shunt word exit end
point "^[-]{0,1}(0x|[0-9]){1}[0-9a-fA-F]*" match?
if fg-number shunt word exit end
point "^([a-zA-Z0-9_]+)[[:space:]]*=>" match?
if fg-variable word exit end
point "^(node|file|exec|augeas|include|class|define|require|if|unless|else|case)[[:space:]]" match?
if fg-keyword word exit end
point "^(template|file|hiera|fail)[[:space:]]*[(]" match?
if fg-coreword word exit end
point "^(exists|present|latest|file|directory|root|undef|true|false|default)[[:space:]:,{(]+" match?
if fg-constant word exit end
point "^[A-Z][a-zA-Z0-9_]+[\\[]" match?
if fg-define word exit end
fg-normal
my name?
if word exit end
shunt ;
: gap ( c -- f )
dup my! white? my `, = or my `. = or my `( = or my `) = or ;
: cln ( -- )
default:rtrim default:rtabs ;
default
'gap is gap?
'cln is clean
'syn is syntax ;
: yaml ( -- )
: syn ( -- )
: shunt ( -- )
char put right ;
: name? ( c -- f )
dup my! alpha? my digit? my `_ = or or ;
: whites ( -- )
begin char while char space? while shunt end ;
: comment ( -- )
begin char while char \n = until shunt end ;
: comment2 ( -- )
begin char while point shunt "^\*/" match? if shunt leave end end ;
: word ( -- )
whites begin char name? while shunt end ;
: string ( delim -- )
char shunt begin char dup my! while shunt my over = until my `\ = if shunt end end drop ;
whites char 0= exit?
point at! c@+ my!
my `# =
if fg-comment comment exit end
my `/ = at c@ `* = and
if fg-comment comment2 exit end
my `" = my `' = or
if fg-string string exit end
point "^[-]{0,1}(0x|[0-9]){1}[0-9a-fA-F]*" match?
if fg-number shunt word exit end
point "^[a-zA-Z0-9_]+[[:space:]]*:" match?
if fg-variable word exit end
fg-normal
my name?
if word exit end
shunt ;
: gap ( c -- f )
dup my! white? my `, = or my `. = or my `( = or my `) = or ;
: cln ( -- )
default:rtrim default:rtabs ;
default
'gap is gap?
'cln is clean
'syn is syntax ;
: detect ( -- )
name "\.fs$" match? if reforth exit end
name "\.php$" match? if php exit end
name "\.c$" match? if c99 exit end
name "\.html?$" match? if html exit end
name "\.md$" match? if markdown exit end
name "\.pp$" match? if puppet exit end
name "\.yaml$" match? if yaml exit end
default ;
: display ( -- )