Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# luash
**Fork note: Powershell support is still very preliminary. Add-Assembly and calling managed assemblies is not yet supported. To call cmdlets, use verb__noun instead of verb-noun:**

```
local sh = require("sh")
write__host("Hello World.")
```

[![Build Status](https://travis-ci.org/zserge/luash.svg)](https://travis-ci.org/zserge/luash)

Expand Down
88 changes: 88 additions & 0 deletions bsh.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
--[[
Bootstrap shell

--]]


local function return_shell_output (cmd, pattern, debug)
if not cmd then io.stderr:write("cmd to pass to a shell was blank") return nil end
if debug then print(string.format("cmd: %s, pattern: %s", cmd, pattern)) end

local match = false
local handle = io.popen(cmd)
if not pattern then
match = handle:read("*a")
elseif type(pattern) == "string" or type(pattern) == "function"then
for v in handle:lines() do
if debug then print(v) end
match = string.match(v, pattern)
if match then
if debug then print(string.format("Found %s", match)) end
break
end
end
else
io.stderr:write("Pattern was of wrong type for command " .. cmd)
end
handle:close()
return match
end

local function return_os()
if package.config:sub(1,1) == "\\" then
return "WIN"
else
local ok = return_shell_output("uname -s")
if ok then
return ok
else
return "POSIX"
end
end
end


local function return_shell(os)
if os == "WIN" then
return "powershell"
else
return return_shell_output("echo $SHELL",trim)
end
end


local function test_path(os,location)
local cmd = ""
local pattern = ""
local ok = nil
assert(location)
--NOT string.match %s, this is replaced with the value of 'location'.
pattern = string.format("(%s)",location)
--check location exists
if os == WIN then
cmd = string.format("if($(test-path -path %s){echo %s}", location, location)
else
cmd = string.format("[ -d \'%s\' ] && echo \'%s\'", location, location)
end

if return_shell_output(cmd,pattern) then
return true
else
return false
end
end

local function return_home_dir(os)
local loc_data = "echo $HOME"
if os == "WIN" then
loc_data = "powershell $env:localappdata"
end
return return_shell_output(loc_data,trim)
end

return {
get_home_dir = return_home_dir,
get_os = return_os,
get_shell = return_shell,
get_shell_output = return_shell_output
}
37 changes: 37 additions & 0 deletions pwr_sh.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--[[
Powershell extensions for sh.lua
--]]

local funciton pwrsh_clean(str,pattern)
local pattern = pattern or "__"
return str::gsub(pattern,"-")
end

--[[
This is what I am attempting to achieve:
local unzip = '"Add-Type -assembly \'system.io.compression.filesystem\'; [io.compression.zipfile]::ExtractToDirectory(\'<uri>\',\'<destination>\')"'
--]]

local function net_params_format(one,two,three,four)
-- local function net_class_call(net_type, method,...)
--iterate and format according to resolved type.
return string.format("\'%s\','\%s\'",one,two)
end

local function net_class_call(net_type, method, one, two, three, four)
-- local function net_class_call(net_type, method,...)
local net_type_fmt = string.format("Add-Type -assembly \'%s\';",net_type)
local method_fmt = string.format("[%s]::%s(\%s))",net_type,method)
local net_call = string.format('"%s %s"',net_type_fmt,method_fmt)
-- return string.format('"%s%s %s"',add_type_fmt,net_type_fmt,method_fmt)
local net_call_fun = function (one,two,three,four)
return string.format(net_call,net_params_format(one,two)
end
return net_call_fun
end

local function sanitize_quotes(str)
-- sanitize quotes for powershell. Not sure what the means quite yet,
-- but I know that powershell uses quote escapes differently.
return str
end
27 changes: 27 additions & 0 deletions pwr_sh_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local sh = require("sh")

--print(ls("~"))
local name = "luarocks-2.4.3-win32"
local ext = ".zip"
local uri = "http://luarocks.github.io/luarocks/releases/"..name..ext
local dest_dir = "C:\\temp\\"
local destination = dest_dir..name..ext

--uri = "-Uri "..uri
local outfile = "-OutFile"--..destination
print("-uri",uri,outfile, destination)
print(Invoke__WebRequest ("-uri",uri,"-outfile", destination))
--(uri,outfile )

--cd("C:\\temp")
--print(ls())

--print(type(out))
--for i,v in pairs(out) do
-- print("i: "..i,"v: "..v)
--end
--print(out)
--ls = sh.command("ls")

--print(ls("~"))

71 changes: 65 additions & 6 deletions sh.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
--[[
lua-shell. Converts global scoped function calls into shell commands.
TODO: create lines co-routine iterator over result
TODO: create pipe() function to use lua memory as a buffer
TODO: investigate scope of shell invocation (once, many?).
follow up is how to preserve environment?
TODO: can we change global scope to prevent "pollution" of actual global scope?
--]]
local M = {}
local bootsrp = require("bsh")

--init...
local slash = package.config:sub(1,1)
local filename = '.shluainput'
local tmpfile = "/tmp/"..filename
local trim = "^%s*(.-)%s*$"
local _os = bootsrp.get_os()
local shell = bootsrp.get_shell(_os)
local home_dir = bootsrp.get_home_dir(_os)
tmpfile = string.format("%s%s%s",home_dir,slash,filename)

-- converts key and it's argument to "-k" or "-k=v" or just ""
local function arg(k, a)
Expand Down Expand Up @@ -46,24 +65,31 @@ local function command(cmd, ...)
return function(...)
local args = flatten({...})
local s = cmd
--TODO: Powershell requires quote sanitization. Only outer quotes of the command parameter can be double quotes
for _, v in ipairs(prearg) do
s = s .. ' ' .. v
end
for k, v in pairs(args.args) do
s = s .. ' ' .. v
end

if args.input == "" then args.input = false end
if args.input then
local f = io.open(M.tmpfile, 'w')
local f = io.open(tmpfile, 'w')
f:write(args.input)
f:close()
s = s .. ' <'..M.tmpfile
s = s .. ' <'..tmpfile
end
myt = {}
s= s:gsub("__","-")
s = string.format("%s %s",shell, s)
local p = io.popen(s, 'r')
local output = p:read('*a')
local _, exit, status = p:close()
os.remove(M.tmpfile)


if args.input then
os.remove(tmpfile)
end

local t = {
__input = output,
__exitcode = exit == 'exit' and status or 127,
Expand Down Expand Up @@ -94,9 +120,34 @@ mt.__index = function(t, cmd)
return command(cmd)
end

local function set_temp(location)
--This should be sanitized
if test_path(location) then
tmpfile = location
return true
else
return nil, "location not found"
end
end

local function get_temp()
return tmpfile
end
local function get_shell()
return shell
end

local function set_shell(sh_name)
--assert(false,"NOT IMPLEMENTED")
if not os == "WIN" then
local ok = return_shell_output("which "..sh_name,trim)
if ok then shell = sh_name return true end
end
return nil, "Not supported"
end

-- export command() function and configurable temporary "input" file
M.command = command
M.tmpfile = '/tmp/shluainput'

-- allow to call sh to run shell commands
setmetatable(M, {
Expand All @@ -105,4 +156,12 @@ setmetatable(M, {
end
})


M.get_temp = get_temp
M.set_temp = set_temp
M.get_shell = get_shell
M.set_shell = set_shell
M.slash = slash
M.os = _os

return M