mirror of https://github.com/LDDestroier/CC/
Update ed.lua
Added some commands: p - print line from buffer "," - modify commands to use whole buffer "w" - write buffer to file path Added read/write to and from files (no input mode yet) Added invoking of "!" shell evaluation (but no shell evaluation logic... until later) Added hacky bullshit code for determining file path validity Spite of GNU ed rising steadily
This commit is contained in:
parent
2a762acfc1
commit
3dc3bea86b
179
ed.lua
179
ed.lua
|
@ -1,15 +1,16 @@
|
||||||
-- ed text editor
|
-- ed text editor
|
||||||
-- Port to ComputerCraft by LDDestroier
|
-- Port to ComputerCraft by LDDestroier
|
||||||
-- wget https://raw.githubusercontent.com/LDDestroier/CC/master/ed.lua
|
|
||||||
|
|
||||||
local state = {
|
local state = {
|
||||||
output = 0,
|
output = 0,
|
||||||
halt = false,
|
halt = false,
|
||||||
debug = true,
|
debug = false,
|
||||||
|
|
||||||
mode = "command", -- command or input
|
mode = "command", -- command or input
|
||||||
|
|
||||||
buffer = {},
|
buffer = {},
|
||||||
|
line = 1,
|
||||||
|
filepath = nil,
|
||||||
|
|
||||||
show_help = false,
|
show_help = false,
|
||||||
show_version = false,
|
show_version = false,
|
||||||
|
@ -275,6 +276,8 @@ state.strip_trailing_cr = t_options_list.strip_trailing_cr.value or state.strip_
|
||||||
state.show_help = t_options_list.help.value and (t_options_list.help.order < t_options_list.version.order)
|
state.show_help = t_options_list.help.value and (t_options_list.help.order < t_options_list.version.order)
|
||||||
state.show_version = t_options_list.version.value and (t_options_list.version.order < t_options_list.help.order)
|
state.show_version = t_options_list.version.value and (t_options_list.version.order < t_options_list.help.order)
|
||||||
|
|
||||||
|
state.filepath = shell.resolve(n_args[1])
|
||||||
|
|
||||||
if state.halt then
|
if state.halt then
|
||||||
return state.output
|
return state.output
|
||||||
end
|
end
|
||||||
|
@ -388,30 +391,166 @@ local function fn_input()
|
||||||
return text, interrupt
|
return text, interrupt
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function fn_check_valid_path(path, ignore_nonexist)
|
||||||
|
local good, err = true, ""
|
||||||
|
|
||||||
|
if not path then
|
||||||
|
good, err = false, ""
|
||||||
|
|
||||||
|
elseif not fs.exists(path) then
|
||||||
|
good, err = false, "No such file or directory"
|
||||||
|
if ignore_nonexist then
|
||||||
|
good = true
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif fs.isDir(path) then
|
||||||
|
good, err = false, "Is a directory"
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return good, err
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fn_file_read(path)
|
||||||
|
-- reads file and puts each line in a table
|
||||||
|
|
||||||
|
local valid = true
|
||||||
|
local err = ""
|
||||||
|
|
||||||
|
if not path then
|
||||||
|
return {}, false, "", 0
|
||||||
|
else
|
||||||
|
valid, err = fn_check_valid_path(path)
|
||||||
|
if not valid then
|
||||||
|
return {}, false, err, 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local output = {}
|
||||||
|
local size = fs.getSize(path)
|
||||||
|
local file = fs.open(path, "r")
|
||||||
|
local line
|
||||||
|
repeat
|
||||||
|
line = file.readLine()
|
||||||
|
if line then
|
||||||
|
output[#output + 1] = line
|
||||||
|
end
|
||||||
|
until not line
|
||||||
|
|
||||||
|
return output, true, err, size
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fn_file_write(path, buffer)
|
||||||
|
if not fn_check_valid_path(path, true) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local file = fs.open(path, "w")
|
||||||
|
for i = 1, #buffer do
|
||||||
|
file.write(buffer[i])
|
||||||
|
if i < #buffer then
|
||||||
|
file.write("\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
return fs.getSize(path)
|
||||||
|
end
|
||||||
|
|
||||||
local function fn_shell_resolve(command)
|
local function fn_shell_resolve(command)
|
||||||
-- TODO: make dynamically resizing window object
|
-- TODO: make dynamically resizing window object
|
||||||
-- set every pixel of window to black-on-black, then always make window draw white-on-white text to mark written regions
|
-- set every pixel of window to black-on-black, then always make window draw white-on-white text to mark written regions
|
||||||
-- then, return a table of lines from the window that are just as long as needed to represent the "marked" portions
|
-- then, return a table of lines from the window that are just as long as needed to represent the "marked" portions
|
||||||
|
-- ... or, I could figure out how to use lua's stdout functionality
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function fn_command_parse(text)
|
local function fn_command_parse(text)
|
||||||
local valid = false
|
local valid = false
|
||||||
|
text = text:sub(text:find("[^%s]") or 0, -1) -- strip leading spaces
|
||||||
|
local command = text:match("^[^%s]+") or "" -- first word
|
||||||
|
local argument = text:sub(text:find("[^%s]", #command + 1) or (#text + 1), -1) -- rest of sentence
|
||||||
|
|
||||||
if text == "P" then
|
local whole = false
|
||||||
|
local program_output
|
||||||
|
|
||||||
|
-- TODO: add every command and every subcommand
|
||||||
|
-- TODO: implement Regex somehow (or settle on Lua patterns)
|
||||||
|
|
||||||
|
if #command == 0 then
|
||||||
|
if state.line < #state.buffer then
|
||||||
|
state.line = state.line + 1
|
||||||
|
valid = true
|
||||||
|
print(state.buffer[state.line])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if command:sub(1, 1) == "!" then -- shell evaluate
|
||||||
|
program_output = fn_shell_resolve(command:sub(2))
|
||||||
|
for i = 1, #program_output do
|
||||||
|
print(program_output[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif command:sub(1, 1) == "," then
|
||||||
|
whole = true
|
||||||
|
command = command:match("[^,]+.*")
|
||||||
|
end
|
||||||
|
|
||||||
|
if tonumber(command) then -- set edit line number
|
||||||
|
if state.buffer[tonumber(command)] then
|
||||||
|
state.line = tonumber(command)
|
||||||
|
print(state.buffer[state.line])
|
||||||
|
valid = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if command == "p" then -- print
|
||||||
|
if whole then
|
||||||
|
for i = 1, #state.buffer do
|
||||||
|
print(state.buffer[i])
|
||||||
|
end
|
||||||
|
state.line = #state.buffer
|
||||||
|
else
|
||||||
|
print(state.buffer[state.line])
|
||||||
|
end
|
||||||
|
valid = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if command == "w" then -- write to file
|
||||||
|
local p_valid, err
|
||||||
|
|
||||||
|
if #argument > 0 then
|
||||||
|
state.filepath = shell.resolve(argument)
|
||||||
|
end
|
||||||
|
|
||||||
|
if state.filepath then
|
||||||
|
p_valid, err = fn_check_valid_path(state.filepath, true)
|
||||||
|
if p_valid then
|
||||||
|
if fs.isReadOnly(state.filepath) then
|
||||||
|
print(state.filepath .. ": Permission denied")
|
||||||
|
else
|
||||||
|
print(fn_file_write(state.filepath, state.buffer)) -- print size of written
|
||||||
|
valid = true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(state.filepath .. ": " .. err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if command == "P" then -- toggle prompt
|
||||||
valid = true
|
valid = true
|
||||||
state.show_prompt = not state.show_prompt
|
state.show_prompt = not state.show_prompt
|
||||||
end
|
end
|
||||||
if text == "q" then
|
if command == "q" then -- get the fuck outta heeereeeee
|
||||||
valid = true
|
valid = true
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if text == "i" then
|
if command == "i" then -- enter input mode
|
||||||
valid = true
|
valid = true
|
||||||
state.mode = "input"
|
state.mode = "input"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: inplement every command
|
|
||||||
|
|
||||||
if not valid then
|
if not valid then
|
||||||
print("?")
|
print("?")
|
||||||
|
@ -422,7 +561,7 @@ end
|
||||||
|
|
||||||
local function fn_input_parse(text, interrupt)
|
local function fn_input_parse(text, interrupt)
|
||||||
if interrupt then
|
if interrupt then
|
||||||
state.mode == "command"
|
state.mode = "command"
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
print("WIP")
|
print("WIP")
|
||||||
|
@ -434,6 +573,23 @@ local function main()
|
||||||
state.mode = "command"
|
state.mode = "command"
|
||||||
local running = true
|
local running = true
|
||||||
local text, interrupt
|
local text, interrupt
|
||||||
|
|
||||||
|
if state.filepath then
|
||||||
|
local valid, err, size
|
||||||
|
state.buffer, valid, err, size = fn_file_read(state.filepath)
|
||||||
|
if valid then
|
||||||
|
if state.filepath then
|
||||||
|
print(size)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(state.filepath .. ": " .. err)
|
||||||
|
if fs.isDir(state.filepath) then
|
||||||
|
print("?") -- ed does it, I do it
|
||||||
|
end
|
||||||
|
state.filepath = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
while running do
|
while running do
|
||||||
text, interrupt = fn_input()
|
text, interrupt = fn_input()
|
||||||
if interrupt then
|
if interrupt then
|
||||||
|
@ -452,8 +608,9 @@ local function main()
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return state.output
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
main()
|
return main()
|
||||||
|
|
||||||
return state.output
|
|
||||||
|
|
Loading…
Reference in New Issue