Hi April,
Congratulations, you're the lucky winner of ... a code
review! But I am not reviewing the JobQueue itself.
Instead I will focus on how the SciTE Tools Menu and the
Extensions interface with the new job system. (Mainly
because I worked on the Tools Menu and on the Extensions, so
I have a personal interest in those parts. But also because
multithreaded code is hard to review, and I am lazy.)
1) As Neil pointed out, the correct model for setting up the
function is like Open, not like SendEditor. SendEditor and
SendOutput are closures so that they can share the same
code. (A closure is just a function with some associated
data: in this case, the extra data is a string that says
where to send the message.)
lua_pushliteral(luaState, "Open");
lua_pushcfunction(luaState, cf_scite_open);
lua_rawset(luaState, -3);
lua_pushliteral(luaState, "Execute");
lua_pushcfunction(luaState, cf_scite_execute);
lua_rawset(luaState, -3);
The Lua API is stack-based, so it takes a bit of getting
used to. First you push the arguments, then you call the
function. The function call may reference other stack items
by index; that's what the -3 is. So here, if this were a
normal C-style API, it would look something like this
(pseudocode):
sciteTable = newTable()
rawSet(sciteTable, "SendEditor", wrapClosure(cf_scite_send,
"editor"))
rawSet(sciteTable, "SendOutput", wrapClosure(cf_scite_send,
"output"))
rawSet(sciteTable, "Open", wrapFunction(cf_scite_open))
rawSet(sciteTable, "Execute",
wrapFunction(cf_scite_execute))
rawSet(globalVars, "scite", sciteTable)
2) If it is necessary to add new methods to the
ExtensionAPI, I would try to keep them at a high level so
that other extensions (e.g. Director) can also use them
without having to copy boilerplate code from LuaExtension.
To that end, you might consider removing DecodeCommandMode
from ExtensionAPI, and changing AddJob to do that work.
AddJob could have this signature:
virtual bool AddJob(const char *jobCommand, const char
*jobDirectory, const char *jobMode, const char
*jobInput=0)=0;
The implementation of AddJob would decode the mode string to
get the subsystem, save-before option, and flags. Pass a
non-NULL for jobInput (even an empty string) and that means
jobHasInput gets added to the flags after the mode string is
decoded. (Also, since the raw flags are not passed in to
AddJob, there is no need to mask out the flags that are
disallowed from extensions.)
With this change, cf_scite_execute would become much
simpler, and would look something like this:
static int cf_scite_execute(lua_State *L) {
const char *cmd = luaL_checkstring(L, 1); // cannot return
NULL
const char *dir = luaL_optstring(L, 2, NULL);
const char *mode = luaL_optstring(L, 3, NULL);
const char *input = luaL_optstring(L, 4, NULL);
if (!host->AddJob(cmd, dir, mode, input)) {
lua_pushfstring(L, "failed to add %s to the SciTE command
queue", cmd);
raise_error(L);
}
return 0;
}
3) It was good to factor out code that is used by both the
new job subsystem and the tools menu. Much better than copy
/ paste. But in the process, you had to invent some new
workarounds, to shoehorn all the command properties into
flags so they could be passed around more easily; and to
continue supporting the old-style command properties
(command.quiet, command.save.before, etc).
I think the solution is to factor out even more of the code.
What if the old-style command properties are handled just by
appending them to the command.mode? What if ToolsMenu just
reads the properties, and delegates to another method to
interpret them and submit the command to the queue? (It
could delegate to AddJob, or to a method that is called from
both ToolsMenu and AddJob.)
Well, I had to give it a try. A sample implementation (that
does not depend on the new job system) is uploaded here:
http://users.hfx.eastlink.ca/~gisdev/SciTE_ToolsMenu_sample.zip
I am not clear on what AddJob does exactly, what the return
value means, why some job subsystems are disallowed, etc.,
so I didn't try to integrate that in my sample code.
4) Since I peeked at AddJob, I suppose I should mention that
SaveIfUnsure prompts the user with a modal dialog. If
AddJob is called from a thread other than the main UI
thread, the dialog would probably appear non-modal. Might
be worth testing. (You won't be able to test it from Lua,
because Lua code always executes in the main thread.)
Best regards,
Bruce
"April White" <[EMAIL PROTECTED]> wrote in message
news:[EMAIL PROTECTED]
>I have uploaded to
>http://www.scintilla.org/aprilw/scite-april-2006-01-26.zip
>my latest changes to the job system.
>
> The Changelog.txt file contains more information. A brief
> list is:
> - an interface between Lua and the job system has been
> added as scite.execute()
> - Lua jobs can use 'command.mode' settings, though there
> are some exclusions
> - to facilitate the decoding of 'command.mode' strings, an
> extender method has been added
> - the code that replaces the current selection with the
> results of the job has been moved out of the tool thread
>
> April
>
> --
> Behind every successful woman... is a substantial amount
> of coffee.
> Stephanie Piro
_______________________________________________
Scite-interest mailing list
[email protected]
http://mailman.lyra.org/mailman/listinfo/scite-interest