203 lines
5.1 KiB
Erlang
203 lines
5.1 KiB
Erlang
%%% @doc
|
|
%%% GSC CLI: explorer/harness for sfc iteration
|
|
%%% @end
|
|
|
|
-module(gsc_cli).
|
|
-vsn("0.1.0").
|
|
-author("Peter Harpending <peterharpending@qpq.swiss>").
|
|
-copyright("Peter Harpending <peterharpending@qpq.swiss>").
|
|
-license("GPL-3.0-only").
|
|
|
|
-export([start/1]).
|
|
|
|
-include("$gsc_include/gsc.hrl").
|
|
-include("ansi.hrl").
|
|
|
|
do_help() ->
|
|
io:format("~ts", [help_screen()]).
|
|
|
|
help_screen() ->
|
|
["you can't help people who refuse to help themsleves\n"].
|
|
|
|
-spec start(ArgV) -> ok
|
|
when ArgV :: [string()].
|
|
|
|
start([]) ->
|
|
do_eshell(),
|
|
ok;
|
|
start(["shell"]) ->
|
|
do_eshell(),
|
|
ok;
|
|
start(["eshell"]) ->
|
|
do_eshell(),
|
|
ok;
|
|
start(ArgV) ->
|
|
%io:format("ArgV: ~p~n", [ArgV]),
|
|
do(ArgV),
|
|
zx:silent_stop().
|
|
|
|
do(["list"]) ->
|
|
do_tlist();
|
|
do(["list", "tests"]) ->
|
|
do_tlist();
|
|
do(["run", "tests"]) ->
|
|
io:format("TestModules = ~p~n", [known_modules_with_prefix("ts")]),
|
|
do_runall_tests();
|
|
do(["tokenizers_agree", Foo]) ->
|
|
io:format("~p~n", [tokenizers_agree(Foo)]);
|
|
% slowly phasing out shitty names like lctokens
|
|
% tokens = native sfc token representation
|
|
do(["tokens", Foo]) -> do_tokens(Foo);
|
|
do(["color_tokens", Foo]) -> do_color_tokens(Foo);
|
|
do(["ctokens", Foo]) -> do_color_tokens(Foo);
|
|
do(["colour_tokens" | _]) -> do_doi();
|
|
% so_tokens = so_scan tokens
|
|
do(["so", "tokens", Foo]) -> do_so_tokens(Foo);
|
|
do(["so_tokens", Foo]) -> do_so_tokens(Foo);
|
|
% gso_tokens = our mockery
|
|
do(["gso", "tokens", Foo]) -> do_gso_tokens(Foo);
|
|
do(["gso_tokens", Foo]) -> do_gso_tokens(Foo);
|
|
% print source file to screen with token boundaries highlighted
|
|
% script utility
|
|
do(["rmm", Foo]) ->
|
|
do_rmm(Foo);
|
|
do(Args) ->
|
|
io:format("bad args: ~p~n", [Args]),
|
|
do_help().
|
|
|
|
do_doi() ->
|
|
FP = zx:get_home() ++ "/priv/doi.txt",
|
|
Cmd = "less " ++ FP,
|
|
io:format("~s~n", [Cmd]).
|
|
|
|
|
|
do_runall_tests() ->
|
|
lists:foreach(fun run_mod_main/1, test_mods()).
|
|
|
|
test_mods() ->
|
|
known_modules_with_prefix("gt_").
|
|
|
|
known_modules_with_prefix(Pfx) ->
|
|
ModsZipBeamsZipLoaded = code:all_available(),
|
|
kmp(Pfx, ModsZipBeamsZipLoaded, []).
|
|
|
|
kmp(_Pfx, [], Acc) ->
|
|
lists:sort(Acc);
|
|
kmp(Pfx, [{ModStr, _BeamPath, _Loaded} | Rest], Acc) ->
|
|
case lists:prefix(Pfx, ModStr) of
|
|
false -> kmp(Pfx, Rest, Acc);
|
|
true -> kmp(Pfx, Rest, [list_to_atom(ModStr) | Acc])
|
|
end.
|
|
|
|
run_mod_main(Mod) ->
|
|
io:format("========================================\n"
|
|
"~p:main()\n"
|
|
"========================================\n",
|
|
[Mod]),
|
|
try
|
|
Mod:main()
|
|
catch
|
|
Err:ErrType:Trace ->
|
|
io:format("~p: ~p~n", [Err, ErrType]),
|
|
io:format("Trace:~n~p~n", [Trace])
|
|
end.
|
|
|
|
do_tlist() ->
|
|
lists:foreach(
|
|
fun(ModName) ->
|
|
io:format("~s~n", [ModName])
|
|
end,
|
|
test_mods()
|
|
).
|
|
|
|
|
|
-spec do_eshell() -> ok.
|
|
% @doc start an erlang shell
|
|
|
|
do_eshell() ->
|
|
io:format("Welcome to the GSC shell!~n", []),
|
|
case shell:start_interactive() of
|
|
ok -> ok;
|
|
{error, already_started} -> ok;
|
|
{error, Reason} -> error(Reason)
|
|
end.
|
|
|
|
tokenizers_agree(File) ->
|
|
so_tokens(File) =:= tokens(File).
|
|
|
|
|
|
do_tokens(FilePath) ->
|
|
[io:format("~p~n", [Tk]) || Tk <- tokens(FilePath)].
|
|
|
|
do_so_tokens(FilePath) ->
|
|
[io:format("~p~n", [Tk]) || Tk <- so_tokens(FilePath)].
|
|
|
|
do_gso_tokens(FilePath) ->
|
|
[io:format("~p~n", [Tk]) || Tk <- gso_tokens(FilePath)].
|
|
|
|
|
|
% rmm = run module:main() with our context loaded
|
|
% useful for prototyping
|
|
do_rmm(FilePath) ->
|
|
case compile:file(FilePath) of
|
|
{ok, Mod} -> Mod:main();
|
|
Error -> error(Error)
|
|
end.
|
|
|
|
|
|
so_tokens(FilePath) ->
|
|
{ok, FileBytes} = file:read_file(FilePath),
|
|
FileStr = unicode:characters_to_nfc_list(FileBytes),
|
|
{ok, Tokens} = so_scan:scan(FileStr),
|
|
Tokens.
|
|
|
|
gso_tokens(FilePath) ->
|
|
{ok, FileBytes} = file:read_file(FilePath),
|
|
FileStr = unicode:characters_to_nfc_list(FileBytes),
|
|
{ok, Tokens} = gso_scan:scan(FileStr),
|
|
Tokens.
|
|
|
|
|
|
tokens(FilePath) ->
|
|
{ok, Tokens} = gsc:tokens_from_file(FilePath),
|
|
Tokens.
|
|
|
|
|
|
do_color_tokens(File) ->
|
|
case gsc:tokens_from_file(File) of
|
|
{ok, Tokens} ->
|
|
ColorizedSrcStr = colorize_tokens(chunk_color_wheel(), Tokens, ""),
|
|
Full = [?ANSI_INVERT, ColorizedSrcStr, ?ANSI_UNINVERT],
|
|
io:format("~s", [Full]);
|
|
Error ->
|
|
io:format("~p~n", [Error])
|
|
end.
|
|
|
|
chunk_color_wheel() ->
|
|
%[yellow, blue].
|
|
[red, green, yellow, blue, magenta, cyan].
|
|
|
|
|
|
|
|
colorize_tokens(Wheel, [T | Ts], Acc) ->
|
|
{Color, NewWheel} = rotate(Wheel),
|
|
NewAcc = [Acc, colorize_token_str(Color, T)],
|
|
colorize_tokens(NewWheel, Ts, NewAcc);
|
|
colorize_tokens(_, [], Acc) ->
|
|
Acc.
|
|
|
|
rotate([A | Rest]) ->
|
|
{A, Rest ++ [A]}.
|
|
|
|
colorize_token_str(Color, #tk{str = Str}) ->
|
|
{Pfx, Sfx} = color_fixes(Color),
|
|
[Pfx, Str, Sfx].
|
|
|
|
color_fixes(red) -> {?ANSI_FG_RED, ?ANSI_FG_RESET};
|
|
color_fixes(green) -> {?ANSI_FG_GREEN, ?ANSI_FG_RESET};
|
|
color_fixes(yellow) -> {?ANSI_FG_YELLOW, ?ANSI_FG_RESET};
|
|
color_fixes(blue) -> {?ANSI_FG_BLUE, ?ANSI_FG_RESET};
|
|
color_fixes(magenta) -> {?ANSI_FG_MAGENTA, ?ANSI_FG_RESET};
|
|
color_fixes(cyan) -> {?ANSI_FG_CYAN, ?ANSI_FG_RESET}.
|
|
|