Ver código fonte

代码优化

master
AICells 5 anos atrás
pai
commit
929578d464
5 arquivos alterados com 137 adições e 89 exclusões
  1. +22
    -8
      erlSync.sample.config
  2. +1
    -1
      src/erlSync.app.src
  3. +13
    -19
      src/erlSync.erl
  4. +56
    -57
      src/sync/esScanner.erl
  5. +45
    -4
      src/sync/esUtils.erl

sync.sample.config → erlSync.sample.config Ver arquivo

@ -1,11 +1,25 @@
%% vim: ts=4 sw=4 et ft=erlang
[
{sync, [
{erlSync, [
{moduleTime, 10000},
%% growl: Desktop notifications
%% valid values: all | none | [success | warning | error]
%% default: all
{growl, all},
{srcDirTime, 10000},
{srcFileTime, 5000},
{compareBeamTime, 2000},
{compareSrcFileTime, 1000},
{file_variables, "-*- mode: compilation; mode: auto-revert; buffer-read-only: true; auto-revert-interval: 0.5 -*-\n\n"},
%% Temp file to write output messages.
{out_file, "/tmp/erlSync.out"},
%% List of modules to be excluded from scanning. While using rebar
%% it's not very useful to specify the excludes here as every
%% get/update-deps will override the settings. Instead specify
%% excluded stuff in the node's config file.
{excluded_modules, []},
%% log: Console notifications
%% valid values: all | none | [success | warnings | errors]
@ -24,7 +38,7 @@
%% default: fix
{non_descendants, fix},
%% whitelisted_modules: Sync only these modules
%% whitelisted_modules: erlSync only these modules
%% default: []
{whitelisted_modules, []},
@ -34,7 +48,7 @@
%% executable: Identify the program that you want run by the "growl" notifications
%% valid values: auto | notifu | 'notify-send' | growlnotify | emacsclient | notification_center
%% * auto = allow sync to autodetect which program to run
%% * auto = allow erlSync to autodetect which program to run
%% * growlnotify = Use Growl for Mac
%% * notification_center = Use OSX Notification Center
%% * 'notify-send' = Use libnotify for Linux

+ 1
- 1
src/erlSync.app.src Ver arquivo

@ -13,7 +13,7 @@
%% http://www.gnu.org/software/emacs/manual/html_node/emacs/File-Variables.html#File-Variables
{file_variables, "-*- mode: compilation; mode: auto-revert; buffer-read-only: true; auto-revert-interval: 0.5 -*-\n\n"},
%% Temp file to write output messages.
{out_file, "/tmp/sync.out"},
{out_file, "/tmp/erlSync.out"},
%% List of modules to be excluded from scanning. While using rebar
%% it's not very useful to specify the excludes here as every
%% get/update-deps will override the settings. Instead specify

+ 13
- 19
src/erlSync.erl Ver arquivo

@ -5,18 +5,14 @@
stop/0,
run/0,
pause/0,
unpause/0,
patch/0,
info/0,
log/1,
log/0,
onsync/0,
onsync/1
onsync/1,
swSyncNode/1
]).
-include_lib("kernel/include/file.hrl").
-define(SERVER, ?MODULE).
-define(PRINT(Var), io:format("DEBUG: ~p:~p - ~p~n~n ~p~n~n", [?MODULE, ?LINE, ??Var, Var])).
-define(VALID_GROWL_OR_LOG(X), is_boolean(X); is_list(X); X == all; X == none; X == skip_success).
start() ->
@ -28,37 +24,35 @@ stop() ->
run() ->
case start() of
{ok, _Started} ->
esScanner:unpause(),
esScanner:rescan(),
ok;
{error, _Reason} ->
esScanner:unpause(),
esScanner:rescan()
io:format("Err")
end.
patch() ->
run(),
esScanner:enable_patching(),
ok.
pause() ->
esScanner:pause().
unpause() ->
esScanner:unpause().
swSyncNode(IsSync) ->
run(),
esScanner:swSyncNode(IsSync),
ok.
info() ->
esScanner:info().
log(Val) when ?VALID_GROWL_OR_LOG(Val) ->
esScanner:set_log(Val).
esScanner:setLog(Val).
log() ->
esScanner:get_log().
esScanner:getLog().
onsync(Fun) ->
esOptions:set_onsync(Fun).
esScanner:setOnsync(Fun).
onsync() ->
esOptions:get_onsync().
esScanner:getOnsync().

+ 56
- 57
src/sync/esScanner.erl Ver arquivo

@ -1,18 +1,21 @@
-module(esScanner).
-behaviour(gen_ipc).
-compile([export_all, nowarn_export_all]).
-compile(inline).
-compile({inline_size, 128}).
%% API
-export([
start_link/0,
rescan/0,
info/0,
enable_patching/0,
swSyncNode/1,
pause/0,
unpause/0,
set_log/1,
get_log/0
getOnsync/0,
setOnsync/1,
setLog/1,
getLog/0
]).
%% gen_ipc callbacks
@ -30,11 +33,17 @@
-define(LOG_OR_GROWL_ON(Val), Val == true;Val == all;Val == skip_success;is_list(Val), Val =/= []).
-define(LOG_OR_GROWL_OFF(Val), Val == false;F == none;F == []).
-define(gTimeout(Type, Time), {{gTimeout, Type}, Time, Type}).
-define(esCfgSync, esCfgSync).
-define(Log, log).
-define(moduleTime, moduleTime).
-define(srcDirTime, srcDirTime).
-define(srcFileTime, srcFileTime).
-define(compareBeamTime, compareBeamTime).
-define(compareSrcFileTime, compareSrcFileTime).
-define(CfgList, [{?Log, all}, {?moduleTime, 30000}, {?srcDirTime, 5000}, {?srcFileTime, 5000}, {?compareBeamTime, 3000}, {?compareSrcFileTime, 3000}]).
-type timestamp() :: file:date_time() | 0.
@ -66,35 +75,37 @@ unpause() ->
ok.
pause() ->
esUtils:log_success("Pausing Sync. Call sync:go() to restart~n"),
esUtils:log_success("Pausing erlSync. Call sync:go() to restart~n"),
gen_ipc:cast(?SERVER, miPause),
ok.
info() ->
io:format("Sync Info...~n"),
gen_ipc:cast(?SERVER, info),
io:format("erlSync Info...~n"),
gen_ipc:call(?SERVER, miInfo),
ok.
set_log(T) when ?LOG_OR_GROWL_ON(T) ->
setLog(T) when ?LOG_OR_GROWL_ON(T) ->
esUtils:setEnv(log, T),
loadCfg(),
esUtils:log_success("Console Notifications Enabled~n"),
ok;
set_log(F) when ?LOG_OR_GROWL_OFF(F) ->
esUtils:log_success("Console Notifications Disabled~n"),
setLog(F) when ?LOG_OR_GROWL_OFF(F) ->
esUtils:setEnv(log, none),
loadCfg(),
esUtils:log_success("Console Notifications Disabled~n"),
ok.
get_log() ->
esUtils:getEnv(log, all).
getLog() ->
?esCfgSync:getv(log).
enable_patching() ->
gen_ipc:cast(?SERVER, enable_patching),
swSyncNode(IsSync) ->
gen_ipc:cast(?SERVER, {miSyncNode, IsSync}),
ok.
get_onsync() ->
getOnsync() ->
gen_ipc:call(?SERVER, miGetOnsync).
set_onsync(Fun) ->
setOnsync(Fun) ->
gen_ipc:call(?SERVER, {miSetOnsync, Fun}).
@ -107,6 +118,7 @@ init([]) ->
erlang:process_flag(trap_exit, true),
rescan(),
startup(),
loadCfg(),
{ok, running, #state{}}.
handleCall(miGetOnsync, _, State, _From) ->
@ -115,13 +127,16 @@ handleCall(miGetOnsync, _, State, _From) ->
handleCall({miSetOnsync, Fun}, _, State, _From) ->
State2 = State#state{onsyncFun = Fun},
{reply, ok, State2};
handleCall(miInfo, _, State, _Form) ->
{reply, {erlang:get(), State}, State};
handleCall(_Request, _, _State, _From) ->
keepStatusState.
handleCast(miPause, _, State) ->
{nextStatus, pause, State};
handleCast(miUnpause, _, State) ->
%% TODO restart
rescan(),
{nextStatus, running, State};
handleCast(miCollMods, running, State) ->
% Get a list of all loaded non-system modules.
@ -131,9 +146,8 @@ handleCast(miCollMods, running, State) ->
CollModules = collMods(AllModules),
%% Schedule the next interval...
Time = esUtils:getEnv(?moduleTime, 30000),
{keepStatus, State#state{modules = CollModules}, [{{gTimeout, miCollMods}, Time, miCollMods}]};
Time = ?esCfgSync:getv(?moduleTime),
{keepStatus, State#state{modules = CollModules}, [?gTimeout(miCollMods, Time)]};
handleCast(miCollSrcDirs, running, State) ->
{USortedSrcDirs, USortedHrlDirs} =
@ -145,8 +159,9 @@ handleCast(miCollSrcDirs, running, State) ->
{ok, {replace, DirsAndOpts}} ->
collSrcDirs(State, [], dirs(DirsAndOpts))
end,
Time = esUtils:getEnv(?srcDirTime, 30000),
{keepStatus, State#state{srcDirs = USortedSrcDirs, hrlDirs = USortedHrlDirs}, [{{gTimeout, miCollSrcDirs}, Time, miCollSrcDirs}]};
Time = ?esCfgSync:getv(?srcDirTime),
{keepStatus, State#state{srcDirs = USortedSrcDirs, hrlDirs = USortedHrlDirs}, [?gTimeout(miCollSrcDirs, Time)]};
handleCast(miCollSrcFiles, running, State) ->
%% For each source dir, get a list of source files...
@ -164,9 +179,9 @@ handleCast(miCollSrcFiles, running, State) ->
HrlFiles = lists:usort(lists:foldl(FHrl, [], State#state.hrlDirs)),
%% Schedule the next interval...
Time = esUtils:getEnv(?srcFileTime, 5000),
Time = ?esCfgSync:getv(?srcFileTime),
%% Return with updated files...
{keepStatus, State#state{srcFiles = ErlFiles, hrlFiles = HrlFiles}, [{{gTimeout, miCollSrcFiles}, Time, miCollSrcFiles}]};
{keepStatus, State#state{srcFiles = ErlFiles, hrlFiles = HrlFiles}, [?gTimeout(miCollSrcFiles, Time)]};
handleCast(miCompareBeams, running, #state{onsyncFun = OnsyncFun} = State) ->
%% Create a list of beam file lastmod times, but filter out modules not having
@ -190,8 +205,8 @@ handleCast(miCompareBeams, running, #state{onsyncFun = OnsyncFun} = State) ->
%% the beam...
reloadChangedMod(State#state.beamTimes, NewBeamLastMod, State#state.patching, OnsyncFun, []),
Time = esUtils:getEnv(?compareBeamTime, 2000),
{keepStatus, State#state{beamTimes = NewBeamLastMod}, [{{gTimeout, miCompareBeams}, Time, miCompareBeams}]};
Time = ?esCfgSync:getv(?compareBeamTime),
{keepStatus, State#state{beamTimes = NewBeamLastMod}, [?gTimeout(miCompareBeams, Time)]};
handleCast(miCompareSrcFiles, running, State) ->
%% Create a list of file lastmod times...
@ -207,8 +222,8 @@ handleCast(miCompareSrcFiles, running, State) ->
%% Schedule the next interval...
Time = esUtils:getEnv(?compareSrcFileTime, 2000),
{keepStatus, State#state{srcFileTimes = NewSrcFileLastMod}, [{{gTimeout, miCompareSrcFiles}, Time, miCompareSrcFiles}]};
Time = ?esCfgSync:getv(?compareSrcFileTime),
{keepStatus, State#state{srcFileTimes = NewSrcFileLastMod}, [?gTimeout(miCompareSrcFiles, Time)]};
handleCast(miCompareHrlFiles, running, State) ->
%% Create a list of file lastmod times...
@ -223,18 +238,16 @@ handleCast(miCompareHrlFiles, running, State) ->
recompileChangeHrlFile(State#state.hrlFileTimes, NewHrlFileLastMod, State#state.srcFiles, State#state.patching),
%% Schedule the next interval...
Time = esUtils:getEnv(?compareSrcFileTime, 2000),
{keepStatus, State#state{hrlFileTimes = NewHrlFileLastMod}, [{{gTimeout, miCompareHrlFiles}, Time, miCompareHrlFiles}]};
handleCast(info, _, State) ->
io:format("Modules: ~p~n", [State#state.modules]),
io:format("Source Dirs: ~p~n", [State#state.srcDirs]),
io:format("Source Files: ~p~n", [State#state.srcFiles]),
{noreply, State};
Time = ?esCfgSync:getv(?compareSrcFileTime),
{keepStatus, State#state{hrlFileTimes = NewHrlFileLastMod}, [?gTimeout(miCompareHrlFiles, Time)]};
handleCast(enable_patching, _, State) ->
NewState = State#state{patching = true},
{noreply, NewState};
handleCast({miSyncNode, IsSync}, _, State) ->
case IsSync of
true ->
{keepStatus, State#state{patching = true}};
_ ->
{keepStatus, State#state{patching = false}}
end;
handleCast(_Msg, _, _State) ->
keepStatusState.
@ -263,29 +276,11 @@ dirs(DirsAndOpts) ->
Dir
end || {Dir, Opts} <- DirsAndOpts].
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _Status, _State) ->
ok.
%%% PRIVATE FUNCTIONS %%%
schedule_cast(Msg, Default, Timers) ->
%% Cancel the old timer...
TRef = proplists:get_value(Msg, Timers),
timer:cancel(TRef),
%% Lookup the interval...
IntervalKey = list_to_atom(atom_to_list(Msg) ++ "_interval"),
Interval = esUtils:getEnv(IntervalKey, Default),
%% Schedule the call...
{ok, NewTRef} = timer:apply_after(Interval, gen_ipc, cast, [?SERVER, Msg]),
%% Return the new timers structure...
lists:keystore(Msg, 1, Timers, {Msg, NewTRef}).
reloadChangedMod([{Module, LastMod} | T1], [{Module, LastMod} | T2], EnablePatching, OnsyncFun, Acc) ->
%% Beam hasn't changed, do nothing...
reloadChangedMod(T1, T2, EnablePatching, OnsyncFun, Acc);
@ -756,5 +751,9 @@ setOptions(SrcDir, Options) ->
startup() ->
io:format("Growl notifications disabled~n").
loadCfg() ->
KVs = [{Key, esUtils:getEnv(Key, DefVal)} || {Key, DefVal} <- ?CfgList],
esUtils:load(?esCfgSync, KVs).
%% ***********************************misc fun end *********************************************

+ 45
- 4
src/sync/esUtils.erl Ver arquivo

@ -1,5 +1,8 @@
-module(esUtils).
-compile(inline).
-compile({inline_size, 128}).
-export([
getSrcDirFromMod/1,
getOptionsFromMod/1,
@ -8,6 +11,7 @@
wildcard/2,
getEnv/2,
setEnv/2,
load/2,
getSystemModules/0
]).
@ -181,7 +185,6 @@ normalizeCaseWindowsDir(Dir) ->
{unix, _} -> Dir
end.
%% @private This is an attempt to intelligently fix paths in modules when a
%% release is moved. Essentially, it takes a module name and its original path
%% from Module:module_info(compile), say
@ -250,7 +253,7 @@ getEnv(Var, Default) ->
Default
end.
%% @private Set a sync environment variable.
%% @private Set a erlSync environment variable.
setEnv(Var, Val) ->
ok = application:set_env(erlSync, Var, Val).
@ -269,8 +272,8 @@ log_warnings(Message) ->
can_we_log(MsgType) ->
can_we_notify(log, MsgType).
can_we_notify(GrowlOrLog, MsgType) ->
case esUtils:getEnv(GrowlOrLog, all) of
can_we_notify(_GrowlOrLog, MsgType) ->
case esScanner:getLog() of
true -> true;
all -> true;
none -> false;
@ -335,3 +338,41 @@ getSystemModules() ->
end
end,
lists:flatten([F(X) || X <- Apps]).
%% map类型的数据不能当做key
-type key() :: atom() | binary() | bitstring() | float() | integer() | list() | tuple().
-type value() :: atom() | binary() | bitstring() | float() | integer() | list() | tuple() | map().
-spec load(term(), [{key(), value()}]) -> ok.
load(Module, KVs) ->
Forms = forms(Module, KVs),
{ok, Module, Bin} = compile:forms(Forms),
code:soft_purge(Module),
{module, Module} = code:load_binary(Module, atom_to_list(Module), Bin),
ok.
forms(Module, KVs) ->
%% -module(Module).
Mod = erl_syntax:attribute(erl_syntax:atom(module), [erl_syntax:atom(Module)]),
%% -export([getv/0]).
ExportList = [erl_syntax:arity_qualifier(erl_syntax:atom(getv), erl_syntax:integer(1))],
Export = erl_syntax:attribute(erl_syntax:atom(export), [erl_syntax:list(ExportList)]),
%% getv(K) -> V
Function = erl_syntax:function(erl_syntax:atom(getv), lookup_clauses(KVs, [])),
[erl_syntax:revert(X) || X <- [Mod, Export, Function]].
lookup_clause(Key, Value) ->
Var = erl_syntax:abstract(Key),
Body = erl_syntax:abstract(Value),
erl_syntax:clause([Var], [], [Body]).
lookup_clause_anon() ->
Var = erl_syntax:variable("_"),
Body = erl_syntax:atom(undefined),
erl_syntax:clause([Var], [], [Body]).
lookup_clauses([], Acc) ->
lists:reverse(lists:flatten([lookup_clause_anon() | Acc]));
lookup_clauses([{Key, Value} | T], Acc) ->
lookup_clauses(T, [lookup_clause(Key, Value) | Acc]).

Carregando…
Cancelar
Salvar