mad_repl.erl 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. -module(mad_repl).
  2. -copyright('Maxim Sokhatsky').
  3. -compile(export_all).
  4. disabled() -> [].
  5. system() -> [compiler,syntax_tools,sasl,tools,mnesia,reltool,xmerl,crypto,kernel,stdlib,
  6. wx,webtool,ssl,runtime_tools,public_key,observer,inets,asn1,et,eunit,hipe,os_mon].
  7. local_app() ->
  8. case filename:basename(filelib:wildcard("ebin/*.app"),".app") of
  9. [] -> [];
  10. A -> [list_to_atom(A)] end.
  11. applist() ->
  12. Name = ".applist",
  13. case file:read_file(Name) of
  14. {ok,Binary} -> parse_applist(Binary);
  15. {error,_} ->
  16. case mad_repl:load_file(Name) of
  17. {error,_} -> mad_plan:main([]);
  18. {ok,Plan} -> parse_applist(Plan) end end.
  19. wildcards(List) -> lists:concat([filelib:wildcard(X)||X<-List]).
  20. parse_applist(AppList) ->
  21. Res = string:tokens(string:strip(string:strip(binary_to_list(AppList),right,$]),left,$[),","),
  22. [ list_to_atom(R) || R <-Res ] -- disabled().
  23. load_config() ->
  24. Config = wildcards(["sys.config"]),
  25. Apps = case Config of
  26. [] -> case mad_repl:load_file("sys.config") of
  27. {error,_} -> [];
  28. {ok,Bin} -> parse(binary_to_list(Bin)) end;
  29. File -> case file:consult(File) of
  30. {error,_} -> [];
  31. {ok,[A]} -> A end end,
  32. [ begin [ application:set_env(App,K,V) || {K,V} <- Cfg ], {App,Cfg} end || {App,Cfg} <- Apps ].
  33. acc_start(A,Acc) ->
  34. case application:start(A) of
  35. {error,{already_started,_}} -> Acc;
  36. {error,{_,{{M,F,_},Ret}}} -> [M|Acc];
  37. {error,{_Reason,Name}} when is_atom(_Reason) -> [Name|Acc];
  38. ok -> Acc;
  39. _ -> Acc end.
  40. load_apps([],_,Acc) ->
  41. Res = lists:foldl(fun(A,Acc) -> case lists:member(A,system()) of
  42. true -> acc_start(A,Acc);
  43. _ -> case load_config(A) of
  44. [] -> acc_start(A,Acc);
  45. _E -> acc_start(_E,Acc) end end end,[], applist()),
  46. case Res of
  47. [] -> ok;
  48. _ -> io:format("\r\nApps couldn't be loaded: ~p~n\n\r",[Res]) end;
  49. load_apps(["applist"],Config,Acc) -> load_apps([],Config,Acc);
  50. load_apps(Params,_,Acc) -> [ application:ensure_all_started(list_to_atom(A))||A<-Params].
  51. cwd() -> {ok, Cwd} = file:get_cwd(), Cwd.
  52. main(Params,RebarConfig) ->
  53. SystemPath = filelib:wildcard(code:root_dir() ++
  54. "/lib/{"++ string:join([atom_to_list(X)||X<-mad_repl:system()],",") ++ "}-*/ebin"),
  55. UserPath = wildcards(["{apps,deps}/*/ebin","ebin"]),
  56. code:set_path(SystemPath++UserPath),
  57. code:add_path(filename:join([cwd(),filename:basename(escript:script_name())])),
  58. load(),
  59. Config = load_config(),
  60. Driver = mad_utils:get_value(shell_driver,RebarConfig,user_drv),
  61. pre(Driver),
  62. case os:type() of
  63. {win32,nt} -> shell:start();
  64. _ -> Driver:start() end,
  65. post(Driver),
  66. load_apps(Params,Config,[]),
  67. case Params of
  68. ["applist"] -> skip;
  69. _ -> timer:sleep(infinity) end.
  70. load() ->
  71. ets_created(),
  72. {ok,Sections} = escript:extract(escript:script_name(),[]),
  73. [Bin] = [B||{archive,B}<-Sections],
  74. unfold_zips(Bin).
  75. unfold_zips(Bin) ->
  76. {ok,Unzip} = zip:unzip(Bin,[memory]),
  77. [ begin
  78. ets:insert(filesystem,{U,FileBin}),
  79. case U of
  80. "static.gz" -> unfold_zips(FileBin);
  81. _ -> skip end
  82. end || {U,FileBin} <- Unzip].
  83. ets_created() ->
  84. case ets:info(filesystem) of
  85. undefined -> ets:new(filesystem,[set,named_table,{keypos,1},public]);
  86. _ -> skip end.
  87. load_file(Name) ->
  88. ets_created(),
  89. case ets:lookup(filesystem,Name) of
  90. [{Name,Bin}] -> {ok,Bin};
  91. _ -> {error,etsfs} end.
  92. load_config(A) when is_atom(A) -> load_config(atom_to_list(A));
  93. load_config(A) when is_list(A) ->
  94. AppFile = A ++".app",
  95. Name = wildcards(["{apps,deps}/*/ebin/"++AppFile,"ebin/"++AppFile]),
  96. case file:read_file(Name) of
  97. {ok,Bin} -> parse(binary_to_list(Bin));
  98. {error,_} -> case ets:lookup(filesystem,AppFile) of
  99. [{Name,Bin}] -> parse(binary_to_list(Bin));
  100. _ -> [] end end.
  101. parse(String) ->
  102. {ok,Tokens,_EndLine} = erl_scan:string(String),
  103. {ok,AbsForm} = erl_parse:parse_exprs(Tokens),
  104. {value,Value,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()),
  105. Value.
  106. % we need to call printing before starting driver for user_drv
  107. % but for start_kjell we should call after, that's why we have pre and post here.
  108. pre(start_kjell) -> [];
  109. pre(user_drv) -> unregister(user), appconfig(user_drv);
  110. pre(Driver) -> appconfig(Driver).
  111. post(start_kjell) -> appconfig(start_kjell);
  112. post(_) -> [].
  113. print(Label,Value,start_kjell) -> io:requests([{put_chars,Label ++ normalize(length(Label)+1,Value) ++ "\n\r"}]);
  114. print(Label,Value,_) -> io:format("~s~p~n",[Label,Value]).
  115. normalize(Padding,V) -> [ case X of 10 -> [13,10]; E -> E end || X <- lists:flatten(pp(Padding,V) )].
  116. pp(Padding,V) -> k_io_lib_pretty:print(V, Padding, 80, 30, 60, fun(_,_)-> no end).
  117. appconfig(Driver) ->
  118. print("Configuration: ", load_config(), Driver),
  119. print("Applications: ", applist(), Driver).