lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Hisham once stated:
> 
> Shifting subjects a little, here's an idea that popped in my head
> yesterday and that may be a little controversial. I'd like to know
> everyone's opinions about this:
> 
>    -- typical sh.run invocation, nothing new
>    x = sh.out.grep("foo", "/usr")
> 
>    -- I expect us to use a lot of stuff like
>    -- some of these variations:
>    x = sh.out.sort("-n", 1, "file.txt")
>    x = sh.out.sort("-n1", "file.txt")
>    x = sh.out.sort("-n"..x, "file.txt")
>    -- in any case, writing arguments can get annoying fast.
> 
>    -- so how about this:
>    x = sh.out.sort({n=1}, "file.txt")
>    -- yes, table arguments get translated into -flags.
> 
>    if sh.ok.find("/etc", {name="*rc", ctime="+30"}) then ...
> 
>    -- Sub-proposal:
>    -- if the order of arguments doesn't matter, we could
>    -- even get more arguments from the array part
>    x = sh.out.sort {n=1, "file.txt"}
> 
>    -- Open issue: -flags vs. --flags.
>    -- For simplicity, I propose single-dash -flags only.
> 
> My first impression is that this could improve readability, and
> further reduce escaping/concatenations. OTOH it could bring confusion
> when argument order matters, and, in general, the whole thing may be
> overkill. Any impressions?

  Two functions, exec() and exec_bg().  exec() returns three values---status
(as a number), stdout (as a string) and stderr (again, as a string) by
default.  exec_bg() runs the command in the background and returns two
values---an error code (0 is okay), and a process id (so that you can wait
on it later).

  exec() takes up to four parameters:

  exec(
	"/path/to/exec",
	{ "cmd" , "line" , "options" },
	{ "ENV=variables" , "OFTHIS=form" }, -- or nil to use existing env
	{ 
	  stdin = source,
	  stdout = dest, -- if this, then exec() returns nil for this result
	  stderr = dest  -- if this, then exec() returns nil for this result
	}
  )

  exec_bg() takes the same paramaters.

  So, your example above becomes:

	x = exec("/bin/sort",{ "-n" , 1 , "file.txt" })

  as a minimum.  If you don't pass an absolute path as the first parameter,
then exec() should (at the very least) walk down $PATH, finding the
executable.  I have actually tested the following and it works fine:

	require "fsys"	-- extention I wrote, has access() function
	require "env"	-- creates a global table "env" with all the
			-- environment variables 
	require "split"	-- a split function

	local function findexec(t,k)
	  for _,path in pairs(split(env.PATH),"%:") do
	    if fsys.access(path .. "/" .. k,"x") then
	      t[k] = path .. "/" .. k
	      return t[k]
	    end
	  end
          return nil
	end

	paths = setmetatable({ } , { __index = findexec })

  That way, to pull the full path of say, firefox, it's:

	print(paths.firefox)

  And the result is cached as well.  With that, your examle now becomes:

	x = exec(paths.sort,{ "-n" , 1 , "file.txt" })

  or

	haystack = { "needles" }
	for file in dir(".") do
	  table.insert(haystack,file)
	end
	status,results = exec(paths.grep, haystack);

  Yes, you have to type out the parameters in a long fasion, but with enough
built-in functions, that isn't much of a chore, and you could always farm
that stuff out to another function (or one that returns a table of options
appended with filenames).

  -spc (At least, that's the approach I would take)