Skip to content

Commit 840f500

Browse files
committed
miniOS classic 0.6.5 - Tab completion
1 parent 228d2fc commit 840f500

File tree

3 files changed

+138
-30
lines changed

3 files changed

+138
-30
lines changed

miniOS/command.lua

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,7 @@ local function twoFileCommandHelper(run, parts)
162162
end
163163

164164
local function runline(line)
165-
--computer.beep()
166-
checkArg(1, line, "string")
165+
checkArg(1, line, "string", "nil")
167166
--print(line)
168167
line = text.trim(line)
169168
if line == "" then return true end
@@ -174,27 +173,7 @@ local function runline(line)
174173
if command == nil then return true end
175174
--drive selector
176175
if #command == 2 then if string.sub(command, 2, 2) == ":" then filesystem.drive.setcurrent(string.sub(command, 1, 1)) return true end end
177-
--external commands and programs
178-
command = parts[1]
179-
if filesystem.exists(command) then
180-
if not filesystem.isDirectory(command) then
181-
if text.endswith(command, ".lua") then runprog(command, parts) return true end
182-
if text.endswith(command, ".bat") then runbat(command, parts) return true end
183-
runprog(command, parts) return true
184-
end
185-
end
186-
if filesystem.exists(command .. ".lua") then
187-
if not filesystem.isDirectory(command .. ".lua") then
188-
runprog(command .. ".lua", parts)
189-
return true
190-
end
191-
end
192-
if filesystem.exists(command .. ".bat") then
193-
if not filesystem.isDirectory(command .. ".bat") then
194-
runbat(command .. ".bat", parts)
195-
return true
196-
end
197-
end
176+
198177
--internal commands
199178
if command == "exit" then history = {} return "exit" end
200179
if command == "cls" then term.clear(); term.gpu().setForeground(0xFFFFFF); term.gpu().setBackground(0x000000) return true end
@@ -218,13 +197,14 @@ local function runline(line)
218197
if command == "rename" then return twoFileCommandHelper(moveFile, parts) end
219198
if command == "ren" then return twoFileCommandHelper(moveFile, parts) end
220199
if command == "move" then return twoFileCommandHelper(moveFile, parts) end
200+
if command == "mkdir" then return filesystem.makeDirectory(fixPath(parts[2])) end
221201
if command == "cmds" then printPaged([[
222202
Internal Commands:
223203
exit --- Exit the command interpreter, Usually restarts it.
224204
cls ---- Clears the screen.
225205
ver ---- Outputs version information.
226206
mem ---- Outputs memory information.
227-
dir ---- Lists the files on the current disk.
207+
dir ---- Lists the files on the current disk or a path.
228208
cmds --- Lists the commands.
229209
intro -- Outputs the introduction message.
230210
drives - Lists the drives and their addresses.
@@ -238,7 +218,31 @@ touch -- Creates a file.
238218
del ---- Deletes a file.
239219
copy --- Copies a file.
240220
move --- Moves a file.
241-
ren ---- Renames a file.]]) print() return true end
221+
ren ---- Renames a file.
222+
mkdir -- Creates a directory.]]) printPaged() return true end
223+
224+
--external commands and programs
225+
command = parts[1]
226+
if filesystem.exists(command) then
227+
if not filesystem.isDirectory(command) then
228+
if text.endswith(command, ".lua") then runprog(command, parts) return true end
229+
if text.endswith(command, ".bat") then runbat(command, parts) return true end
230+
runprog(command, parts) return true
231+
end
232+
end
233+
if filesystem.exists(command .. ".lua") then
234+
if not filesystem.isDirectory(command .. ".lua") then
235+
runprog(command .. ".lua", parts)
236+
return true
237+
end
238+
end
239+
if filesystem.exists(command .. ".bat") then
240+
if not filesystem.isDirectory(command .. ".bat") then
241+
runbat(command .. ".bat", parts)
242+
return true
243+
end
244+
end
245+
242246
print("'" .. parts[1] .. "' is not an internal or external command, program or batch file.")
243247
return false
244248
end
@@ -255,6 +259,8 @@ end
255259

256260
if shell.runline(table.concat(tArgs, " ")) == "exit" then return end
257261

262+
local cmds = {"exit", "cls", "ver", "mem", "dir ", "cmds", "intro", "drives", "labels", "echo ", "type ", "more ", "touch", "del ", "copy ", "move ", "ren ", "mkdir "}
263+
258264
while true do
259265
if miniOS.cmdBat and #miniOS.cmdBat == 0 then
260266
miniOS.cmdBat = nil
@@ -276,7 +282,42 @@ while true do
276282
end
277283
else
278284
term.write(filesystem.drive.getcurrent() ..">")
279-
line = term.read(history)
285+
line = term.read(history, nil, function(line, pos)
286+
local filtered = {}
287+
288+
local space = string.match(line, '^.*() ')
289+
290+
if space == nil then
291+
for _,option in ipairs(cmds) do
292+
if string.sub(option, 1, #line) == line then
293+
filtered[#filtered + 1] = option
294+
end
295+
end
296+
end
297+
298+
local preline
299+
if space ~= nil then
300+
preline = string.sub(line, 1, space)
301+
line = string.sub(line, space + 1)
302+
else
303+
preline = ""
304+
end
305+
local path
306+
local dirsep = string.match(line, '^.*()/')
307+
if dirsep ~= nil then
308+
path = string.sub(line, 1, dirsep)
309+
else path = "" end
310+
311+
for file in fs.list(path) do
312+
file = path .. file
313+
if string.sub(file, 1, #line) == line and string.sub(file, -1) == '/' then
314+
filtered[#filtered + 1] = preline .. file
315+
elseif string.sub(file, 1, #line) == line and (string.sub(file, -4) == '.lua' or string.sub(file, -4) == '.bat') then
316+
filtered[#filtered + 1] = preline .. file .. ' '
317+
end
318+
end
319+
return filtered
320+
end)
280321
while #history > 10 do
281322
table.remove(history, 1)
282323
end

miniOS/miniOS.lua

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
_G._OSNAME = "miniOS classic"
2-
_G._OSVER = "0.6.4.3"
2+
_G._OSVER = "0.6.5"
33
_G._OSVERSION = _OSNAME .. " " .. _OSVER
44
_G._OSCREDIT = "miniOS classic by Skye, based off of OpenOS code from OpenComputers.\nminiOS code is under BSD 2-clause licence, OpenOS code is under the MIT licence."
55

@@ -767,12 +767,15 @@ function terminal_code()
767767
end
768768
end
769769

770-
function term.read(history, dobreak)
770+
function term.read(history, dobreak, hint)
771771
checkArg(1, history, "table", "nil")
772+
checkArg(3, hint, "table", "function", "nil")
772773
history = history or {}
773774
table.insert(history, "")
774775
local offset = term.getCursor() - 1
775776
local scrollX, scrollY = 0, #history - 1
777+
778+
local hints = { handler = hint }
776779

777780
local function getCursor()
778781
local cx, cy = term.getCursor()
@@ -783,7 +786,7 @@ function terminal_code()
783786
local cbx, cby = getCursor()
784787
return history[cby]
785788
end
786-
789+
787790
local function setCursor(nbx, nby)
788791
local w, h = component.gpu.getResolution()
789792
local cx, cy = term.getCursor()
@@ -830,6 +833,13 @@ function terminal_code()
830833
str = text.padRight(str, l)
831834
component.gpu.set(1 + offset, cy, str)
832835
end
836+
837+
local function setline(to)
838+
local cbx, cby = getCursor()
839+
history[cby] = to
840+
redraw()
841+
end
842+
833843

834844
local function home()
835845
local cbx, cby = getCursor()
@@ -911,8 +921,65 @@ function terminal_code()
911921
right(len)
912922
end
913923

924+
local function tab()
925+
if not hints.handler then return end
926+
local main_kb = term.keyboard()
927+
-- term may not have a keyboard
928+
-- in which case, we shouldn't be handling tab events
929+
if not main_kb then
930+
return
931+
end
932+
if not hints.cache then
933+
local data = hints.handler
934+
hints.handler = function(...)
935+
if type(data) == "table" then
936+
local args = {...}
937+
local filtered = {}
938+
for _,option in ipairs(data) do
939+
if string.sub(option, 1, #args[1]) == args[1] then
940+
filtered[#filtered + 1] = option
941+
--print(option)
942+
end
943+
end
944+
return filtered
945+
else
946+
return data(...) or {}
947+
end
948+
end
949+
hints.cache = hints.handler(line(), #line() + 1)
950+
hints.cache.i = -1
951+
end
952+
953+
local cache = hints.cache
954+
local cache_size = #cache
955+
956+
if cache_size == 1 and cache.i == 0 then
957+
-- there was only one solution, and the user is asking for the next
958+
hints.cache = hints.handler(cache[1], #line() + 1)
959+
hints.cache.i = -1
960+
cache = hints.cache
961+
cache_size = #cache
962+
end
963+
964+
local change = keyboard.isShiftDown(main_kb) and -1 or 1
965+
cache.i = (cache.i + change) % math.max(#cache, 1)
966+
local next = cache[cache.i + 1]
967+
if next then
968+
local tail = unicode.len(line()) - #line()
969+
setline(next)
970+
local cbx, cby = getCursor()
971+
setCursor(cbx + #line(), cby)
972+
end
973+
end
974+
914975
local function onKeyDown(char, code)
915976
term.setCursorBlink(false)
977+
978+
if code == keyboard.keys.tab then
979+
tab()
980+
else
981+
hints.cache = nil
982+
end
916983
if code == keyboard.keys.back then
917984
if left() then delete() end
918985
elseif code == keyboard.keys.delete then

miniOSNT

Submodule miniOSNT updated from dc1625b to 47b6dcf

0 commit comments

Comments
 (0)