PRAGMA OPTIONS -O2 -march=native -s
SPLIT ARGUMENT$ BY " " TO arg$ SIZE dim
IF dim < 2 THEN
PRINT "Usage: editor <file>"
END
END IF
Src_File$ = arg$[1]
IF RIGHT$(Src_File$, 4) != ".bac" THEN Src_File$ = Src_File$ & ".bac"
IF NOT(FILEEXISTS(Src_File$)) THEN
OPEN arg$[1] FOR WRITING AS tmp
CLOSE FILE tmp
END IF
CONST Stat$ = "ALARM|ALIAS|APPENDING|AS|ASSOC|BACK|BASE|BG|BLACK|BLUE|BREAK|BROADCAST|" & \
"BY|CALL|CASE|CATCH|CHANGEDIR|CHUNK|CLEAR|CLOSE|COLLAPSE|COLOR|CONST|COMPARE|COMPILER|" & \
"CONTINUE|COPY|CURRENT|CURSOR|CYAN|DATA|DECLARE|DECR|DEFAULT|DEF|DELETE|DIRECTORY|DO|" & \
"DOWN|ELIF|ELSE|ENDFUNCTION|ENDIF|END|ENDSELECT|ENDSUB|ENDUSEC|ENDWITH|EPRINT|EQ|EXIT|FG|FI|" & \
"FILE|LDFLAGS|FN|FOR|FORMAT|FORWARD|FREE|FROM|FUNCTION|GE|GETBYTE|GETFILE|GETLINE|GLOBAL|" & \
"GOSUB|GOTO|GOTOXY|GREEN|GT|IF|IMPORT|IN|INCLUDE|INCR|INPUT|INTENSE|INTERNATIONAL|IS|ISNOT|" & \
"JOIN|LABEL|LE|LET|LOCAL|LOOKUP|LT|MAGENTA|MAKEDIR|MEMREWIND|MEMSTREAM|MEMTYPE|MULTICAST|" & \
"NE|NETWORK|NEXT|NORMAL|OFF|OFFSET|ON|OPEN|OPTION|OPTIONS|POKE|PRAGMA|PRINT|PROTO|PULL|" & \
"PUSH|PUTBYTE|PUTLINE|READING|READ|READLN|READWRITE|RECEIVE|RECORD|RECURSIVE|RED|REDIM|" & \
"RELATE|RENAME|REPEAT|RESET|RESIZE|RESTORE|RESUME|RETURN|REWIND|SCROLL|SCTP|SEED|SEEK|" & \
"SELECT|SEND|SERVER|SETENVIRON|SIZE|SLEEP|SOCKET|SORT|SPLIT|START|STARTPOINT|STEP|STOP|SUB|SWAP|" & \
"SYSTEM|TCP|TEXTDOMAIN|THEN|TO|TRACE|TRAP|TYPE|UDP|UNTIL|UP|USEC|USEH|VAR|WEND|WHENCE|WHILE|" & \
"WHITE|WITH|WRITELN|WRITING|YELLOW"
CONST Stat_Col = 2
CONST Stat_Check$ = " " & REPLACE$(Stat$, "|", " ") & " "
CONST Func$ = "ABS|ACOS|ADDRESS|AND|ASC|ASIN|ATN|COLUMNS|COS|DAY|DEC|ENDFILE|EQUAL|ERROR|EVEN|EXP|" & \
"FILEEXISTS|FILELEN|FILETIME|FILETYPE|FLOOR|FP|GETKEY|GETX|GETY|HOUR|INSTR|INSTRREV|INT|" & \
"ISFALSE|ISTRUE|LEN|LOG|MEMCHECK|MEMORY|MEMTELL|MINUTE|MOD|MONTH|NOT|NOW|ODD|OR|PEEK|POW|" & \
"RANDOM|REGEX|RND|ROUND|ROWS|SEARCH|SECOND|SGN|SIN|SIZEOF|SQR|TAN|TELL|TIMER|TIMEVALUE|" & \
"VAL|WAIT|WEEK|YEAR|ARGUMENT\\$|CHOP\\$|CHR\\$|CONCAT\\$|CURDIR\\$|ERR\\$|EXEC\\$|EXTRACT\\$|" & \
"FILL\\$|GETENVIRON\\$|GETPEER\\$|HEX\\$|HOST\\$|INTL\\$|LCASE\\$|LEFT\\$|MID\\$|MONTH\\$|NNTL\\$|" & \
"OS\\$|REPLACE\\$|REVERSE\\$|RIGHT\\$|SPC\\$|STR\\$|TAB\\$|UCASE\\$|WEEKDAY\\$"
CONST Func_Col = 6
CONST Func_Check$ = " " & REPLACE$(EXTRACT$(Func$, "\\"), "|", " ") & " "
CONST Num$ = "0|1|2|3|4|5|6|7|8|9"
CONST Num_Col = 1
CONST Num_Check$ = " " & REPLACE$(Num$, "|", " ") & " "
CONST Var$ = "PI|TRUE|FALSE|REGLEN|RETVAL|MAXRANDOM|NL\\$|VERSION\\$"
CONST Var_Col = 3
CONST Var_Check$ = " " & REPLACE$(EXTRACT$(Var$, "\\"), "|", " ") & " "
CONST Comm$ = "REM|'"
CONST Comm_Col = 4
CONST Comm_Check$ = " " & REPLACE$(Comm$, "|", " ") & " "
CONST Quot_Col = 5
CONST Dimension = 10240
LET Rows = ROWS
LET Columns = COLUMNS
LET Spos = 1
Tmp_File$ = Src_File$ & ".tmp"
DECLARE Xpos, Ypos, Total_Lines, curline
Xpos = 1
Ypos = 1
Insert_Mode = 0
compile = FALSE
OPEN Src_File$ FOR READING AS prog
OPEN Tmp_File$ FOR WRITING AS tmp
WHILE NOT(ENDFILE(prog))
READLN line$ FROM prog
IF NOT(ENDFILE(prog)) THEN
WRITELN REPLACE$(line$, CHR$(9), SPC$(4)) TO tmp
INCR Total_Lines
END IF
WEND
CLOSE FILE tmp
CLOSE FILE prog
DELETE FILE Src_File$
RENAME Tmp_File$ TO Src_File$
CALL Show_Lines(0)
GOTOXY Xpos, Ypos
REPEAT
refresh = TRUE
key = WAIT(STDIN_FILENO, 40)
SELECT key
CASE 0
CONTINUE
CASE 27
curs = WAIT(STDIN_FILENO, 10)
SELECT curs
CASE 113
BREAK
CASE 99
compile = TRUE
BREAK
CASE 97
message$ = " KEYS " & NL$ \
" ALT Q / ESC = quit " & NL$ \
" ALT C = compile and quit " & NL$ \
" ALT A = show help " & NL$ \
" Insert = toggle insert mode" & NL$
CALL Show_Message(message$, Columns/2, Rows/2-5, 2000)
key = -1
CASE 91
curs = WAIT(STDIN_FILENO, 10)
SELECT curs
CASE 66
IF Ypos = Rows THEN
IF curline < Total_Lines-Rows THEN:INCR curline:FI
ELSE
IF Ypos < Total_Lines THEN INCR Ypos
refresh = FALSE
END IF
CASE 65
IF Ypos = 1 THEN
IF curline > 0 THEN:DECR curline:FI
ELSE
DECR Ypos
refresh = FALSE
END IF
CASE 67
IF Xpos = Columns THEN
IF Spos < Columns THEN:INCR Spos:FI
ELSE
INCR Xpos
refresh = FALSE
END IF
CASE 68
IF Xpos = 1 THEN
IF Spos > 1 THEN:DECR Spos:FI
ELSE
DECR Xpos
refresh = FALSE
END IF
CASE 50
curs = WAIT(STDIN_FILENO, 10)
IF curs = 126 THEN Insert_Mode = 1 - Insert_Mode
IF Insert_Mode THEN
CALL Show_Message("INSERT mode: OFF", Columns/2, Rows/2, 500)
ELSE
CALL Show_Message("INSERT mode: ON", Columns/2, Rows/2, 500)
ENDIF
CASE 51
curs = WAIT(STDIN_FILENO, 10)
CASE 53
curs = WAIT(STDIN_FILENO, 10)
IF curs = 126 THEN
IF curline > Rows THEN
DECR curline, Rows
ELSE
curline = 0
END IF
END IF
CASE 54
curs = WAIT(STDIN_FILENO, 10)
IF curs = 126 THEN
IF curline < Total_Lines-2*Rows THEN
INCR curline, Rows
ELSE
curline = Total_Lines-Rows
END IF
END IF
END SELECT
key = -1
CASE 79
curs = WAIT(STDIN_FILENO, 10)
SELECT curs
CASE 72
Xpos = 1
CASE 70
Xpos = Columns
END SELECT
key = -1
refresh = FALSE
END SELECT
DEFAULT
OPEN Src_File$ FOR READING AS prog
OPEN Tmp_File$ FOR WRITING AS tmp
count = 0
WHILE count < curline+Ypos-1
READLN line$ FROM prog
WRITELN line$ TO tmp
INCR count
WEND
READLN line$ FROM prog
IF key = 127 THEN
IF LEN(line$) > 0 THEN
IF Xpos > 1 THEN
WRITELN LEFT$(line$, Xpos-2+Spos-1), MID$(line$, Xpos+Spos-1) TO tmp
ELSE
WRITELN line$ TO tmp
ENDIF
ENDIF
IF Xpos > 1 THEN:DECR Xpos:FI
ELIF key = 10 THEN
IF Xpos = 1 THEN
WRITELN "" TO tmp
ELSE
WRITELN line$ TO tmp
FI
IF Xpos = 1 THEN
WRITELN line$ TO tmp
ELSE
WRITELN "" TO tmp
FI
IF Ypos < Rows THEN
INCR Ypos
ELSE
IF curline < Total_Lines-Rows THEN:INCR curline:FI
END IF
Xpos = 1
ELSE
IF key = 9 THEN
ch$ = SPC$(4)
ELSE
ch$ = CHR$(key)
FI
IF LEN(line$) >= Xpos THEN
WRITELN LEFT$(line$, Xpos-1+Spos-1), ch$, MID$(line$, Xpos+Spos-1+Insert_Mode) TO tmp
ELSE
WRITELN line$, SPC$(Xpos-1-LEN(line$)), ch$ TO tmp
FI
IF Xpos < Columns THEN
IF key = 9 THEN
INCR Xpos, 4
ELSE
INCR Xpos
FI
FI
ENDIF
WHILE NOT(ENDFILE(prog))
READLN line$ FROM prog
IF NOT(ENDFILE(prog)) THEN WRITELN line$ TO tmp
WEND
DELETE FILE Src_File$
RENAME Tmp_File$ TO Src_File$
CLOSE FILE tmp
CLOSE FILE prog
END SELECT
IF refresh THEN CALL Show_Lines(curline)
GOTOXY Xpos, Ypos
UNTIL key = 27
OPEN Src_File$ FOR READING AS prog
OPEN Tmp_File$ FOR WRITING AS tmp
WHILE NOT(ENDFILE(prog))
READLN line$ FROM prog
IF NOT(ENDFILE(prog)) THEN WRITELN REPLACE$(line$, SPC$(4), CHR$(9)) TO tmp
WEND
CLOSE FILE tmp
CLOSE FILE prog
DELETE FILE Src_File$
RENAME Tmp_File$ TO Src_File$
CURSOR ON
PRINT
GOTOXY 1, Rows
IF compile THEN SYSTEM "bacon " & CURDIR$ & "/" & Src_File$
END
SUB Show_Lines(NUMBER where)
LOCAL fp[Dimension]
LOCAL txt$
LOCAL pos, col, padding, len, total
GOTOXY 1,1
CURSOR OFF
OPEN Src_File$ FOR READING AS prog
Total_Lines = 0
WHILE NOT(ENDFILE(prog))
fp[Total_Lines] = TELL(prog)
READLN txt$ FROM prog
INCR Total_Lines
WEND
REWIND prog
SEEK prog OFFSET fp[where]
FOR x = 1 TO Rows
PUSH Spos
READLN txt$ FROM prog
txt$ = REPLACE$(txt$, CHR$(9), SPC$(4))
padding = Columns - LEN(txt$)
REPEAT
pos = REGEX(MID$(txt$, Spos), Stat$ & "|" & Func$ & "|" & Num$ & "|" & Var$ & "|" & Comm$ & "|\"[^\"]+\"")
IF pos > 0 THEN
len = REGLEN
IF INSTR(Stat_Check$, " " & MID$(MID$(txt$, Spos), pos, REGLEN) & " ") THEN
col = Stat_Col
ELIF INSTR(Num_Check$, " " & MID$(MID$(txt$, Spos), pos, REGLEN) & " ") THEN
col = Num_Col
ELIF INSTR(Func_Check$, " " & MID$(MID$(txt$, Spos), pos, REGLEN) & " ") THEN
col = Func_Col
ELIF INSTR(Var_Check$, " " & MID$(MID$(txt$, Spos), pos, REGLEN) & " ") THEN
col = Var_Col
ELIF INSTR(Comm_Check$, " " & MID$(MID$(txt$, Spos), pos, REGLEN) & " ") THEN
col = Comm_Col
len = LEN(MID$(txt$, Spos)) - pos+1
ELSE
col = Quot_Col
FI
PRINT MID$(txt$, Spos, pos-1);
COLOR FG TO col
PRINT MID$(txt$, Spos+pos-1, len);
COLOR RESET
txt$ = MID$(txt$, Spos+pos-1+len)
Spos = 1
ELSE
PRINT MID$(txt$, Spos, Columns), SPC$(padding);
PULL Spos
IF x < Rows THEN PRINT
END IF
UNTIL pos = 0
NEXT
CLOSE FILE prog
CURSOR ON
END SUB
SUB Show_Message(STRING txt$, NUMBER x, NUMBER y, NUMBER delay)
LOCAL l$
LOCAL len
FOR l$ IN txt$ STEP NL$
IF LEN(l$) > len THEN len = LEN(l$)
NEXT
COLOR FG TO GREEN
GOTOXY x-len/2-1, y
PRINT "+", FILL$(len+2, ASC("-")), "+"
FOR l$ IN txt$ STEP NL$
INCR y
GOTOXY x-len/2-1, y
PRINT "| ", l$, " |"
NEXT
GOTOXY x-len/2-1, y+1
PRINT "+", FILL$(len+2, ASC("-")), "+"
CURSOR OFF
COLOR RESET
SLEEP delay
END SUB