1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-16 01:59:54 +00:00

Add documentation for shell and multishell

Heh, one place we're more complete than cc.cc :p.
This commit is contained in:
Jonathan Coates 2020-04-22 14:39:39 +01:00
parent f3de97d67f
commit 2f42a4e85b
No known key found for this signature in database
GPG Key ID: D6D4CB5BFBBB5CB8
8 changed files with 339 additions and 84 deletions

View File

@ -23,7 +23,7 @@ body {
"Droid Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; "Droid Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
} }
code, pre, .parameter, .type, .definition-name, .reference { code, pre, .parameter, .type, .definition-name, .reference-code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
} }

View File

@ -2,8 +2,8 @@
(sources (sources
/doc/stub/ /doc/stub/
/src/main/resources/assets/computercraft/lua/bios.lua /src/main/resources/*/computercraft/lua/bios.lua
/src/main/resources/assets/computercraft/lua/rom/ /src/main/resources/*/computercraft/lua/rom/
/src/test/resources/test-rom) /src/test/resources/test-rom)
@ -15,13 +15,13 @@
(library-path (library-path
/doc/stub/ /doc/stub/
/src/main/resources/assets/computercraft/lua/rom/apis /src/main/resources/*/computercraft/lua/rom/apis
/src/main/resources/assets/computercraft/lua/rom/apis/command /src/main/resources/*/computercraft/lua/rom/apis/command
/src/main/resources/assets/computercraft/lua/rom/apis/turtle /src/main/resources/*/computercraft/lua/rom/apis/turtle
/src/main/resources/assets/computercraft/lua/rom/modules/main /src/main/resources/*/computercraft/lua/rom/modules/main
/src/main/resources/assets/computercraft/lua/rom/modules/command /src/main/resources/*/computercraft/lua/rom/modules/command
/src/main/resources/assets/computercraft/lua/rom/modules/turtle)) /src/main/resources/*/computercraft/lua/rom/modules/turtle))
(at / (at /
(linters (linters
@ -35,9 +35,7 @@
;; be good to find a compromise in the future, but this works for now. ;; be good to find a compromise in the future, but this works for now.
-var:unused-arg -var:unused-arg
;; Suppress a couple of documentation comments warnings for now. We'll ;; Some APIS (keys, colour and os mainly) are incomplete right now.
;; hopefully be able to remove them in the future.
-doc:undocumented -doc:undocumented-arg -doc:unresolved-reference
-var:unresolved-member) -var:unresolved-member)
(lint (lint
(bracket-spaces (bracket-spaces
@ -50,8 +48,8 @@
;; We disable the unused global linter in bios.lua and the APIs. In the future ;; We disable the unused global linter in bios.lua and the APIs. In the future
;; hopefully we'll get illuaminate to handle this. ;; hopefully we'll get illuaminate to handle this.
(at (at
(/src/main/resources/assets/computercraft/lua/bios.lua (/src/main/resources/*/computercraft/lua/bios.lua
/src/main/resources/assets/computercraft/lua/rom/apis/) /src/main/resources/*/computercraft/lua/rom/apis/)
(linters -var:unused-global) (linters -var:unused-global)
(lint (allow-toplevel-global true))) (lint (allow-toplevel-global true)))
@ -60,19 +58,27 @@
(linters -var:unused-global) (linters -var:unused-global)
(lint (allow-toplevel-global true))) (lint (allow-toplevel-global true)))
;; Ensure any fully documented modules stay fully documented. ;; Suppress warnings for currently undocumented modules.
(at (at
(/src/main/resources/assets/computercraft/lua/rom/apis/colors.lua (/doc/stub/commands.lua
/src/main/resources/assets/computercraft/lua/rom/apis/colours.lua /doc/stub/fs.lua
/src/main/resources/assets/computercraft/lua/rom/apis/disk.lua /doc/stub/http.lua
/src/main/resources/assets/computercraft/lua/rom/apis/gps.lua /doc/stub/os.lua
/src/main/resources/assets/computercraft/lua/rom/apis/help.lua /doc/stub/redstone.lua
/src/main/resources/assets/computercraft/lua/rom/apis/keys.lua /doc/stub/term.lua
/src/main/resources/assets/computercraft/lua/rom/apis/paintutils.lua /doc/stub/turtle.lua
/src/main/resources/assets/computercraft/lua/rom/apis/parallel.lua /src/main/resources/*/computercraft/lua/rom/apis/command/commands.lua
/src/main/resources/assets/computercraft/lua/rom/apis/peripheral.lua /src/main/resources/*/computercraft/lua/rom/apis/io.lua
/src/main/resources/assets/computercraft/lua/rom/apis/rednet.lua /src/main/resources/*/computercraft/lua/rom/apis/window.lua
/src/main/resources/assets/computercraft/lua/rom/apis/settings.lua /src/main/resources/*/computercraft/lua/rom/modules/main/cc/shell/completion.lua)
/src/main/resources/assets/computercraft/lua/rom/apis/texutils.lua
/src/main/resources/assets/computercraft/lua/rom/apis/vector.lua) (linters -doc:undocumented -doc:undocumented-arg))
(linters doc:undocumented doc:undocumented-arg))
;; These currently rely on unknown references.
(at
(/src/main/resources/*/computercraft/lua/rom/apis/textutils.lua
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/completion.lua
/src/main/resources/*/computercraft/lua/rom/modules/main/cc/shell/completion.lua
/src/main/resources/*/computercraft/lua/rom/programs/advanced/multishell.lua
/src/main/resources/*/computercraft/lua/rom/programs/shell.lua)
(linters -doc:unresolved-reference))

View File

@ -521,14 +521,11 @@ function os.run(_tEnv, _sPath, ...)
expect(1, _tEnv, "table") expect(1, _tEnv, "table")
expect(2, _sPath, "string") expect(2, _sPath, "string")
local tArgs = table.pack(...)
local tEnv = _tEnv local tEnv = _tEnv
setmetatable(tEnv, { __index = _G }) setmetatable(tEnv, { __index = _G })
local fnFile, err = loadfile(_sPath, nil, tEnv) local fnFile, err = loadfile(_sPath, nil, tEnv)
if fnFile then if fnFile then
local ok, err = pcall(function() local ok, err = pcall(fnFile, ...)
fnFile(table.unpack(tArgs, 1, tArgs.n))
end)
if not ok then if not ok then
if err and err ~= "" then if err and err ~= "" then
printError(err) printError(err)

View File

@ -106,7 +106,7 @@ end
-- This generally returns the same as @{disk.getLabel} for records. -- This generally returns the same as @{disk.getLabel} for records.
-- --
-- @tparam string name The name of the disk drive. -- @tparam string name The name of the disk drive.
-- @treturn string|false|nil The track title, `false` if there is not a music -- @treturn string|false|nil The track title, @{false} if there is not a music
-- record in the drive or `nil` if no drive is present. -- record in the drive or `nil` if no drive is present.
function getAudioTitle(name) function getAudioTitle(name)
if isDrive(name) then if isDrive(name) then

View File

@ -32,7 +32,7 @@ for _, v in ipairs(valid_types) do valid_types[v] = true end
-- you to provide defaults and additional metadata. -- you to provide defaults and additional metadata.
-- --
-- @tparam string name The name of this option -- @tparam string name The name of this option
-- @tparam[opt] { description? = string, default? = value, type? = string } options -- @tparam[opt] { description? = string, default? = any, type? = string } options
-- Options for this setting. This table accepts the following fields: -- Options for this setting. This table accepts the following fields:
-- --
-- - `description`: A description which may be printed when running the `set` program. -- - `description`: A description which may be printed when running the `set` program.
@ -127,7 +127,7 @@ end
--- Get details about a specific setting. --- Get details about a specific setting.
-- --
-- @tparam string name The name of the setting to get. -- @tparam string name The name of the setting to get.
-- @treturn { description? = string, default? = value, type? = string, value? = value } -- @treturn { description? = string, default? = any, type? = string, value? = any }
-- Information about this setting. This includes all information from @{settings.define}, -- Information about this setting. This includes all information from @{settings.define},
-- as well as this setting's value. -- as well as this setting's value.
function getDetails(name) function getDetails(name)

View File

@ -16,7 +16,7 @@ local completion = require "cc.completion"
--- Complete the name of a file relative to the current working directory. --- Complete the name of a file relative to the current working directory.
-- --
-- @tparam shell shell The shell we're completing in -- @tparam table shell The shell we're completing in
-- @tparam { string... } choices The list of choices to complete from. -- @tparam { string... } choices The list of choices to complete from.
-- @treturn { string... } A list of suffixes of matching files. -- @treturn { string... } A list of suffixes of matching files.
local function file(shell, text) local function file(shell, text)
@ -25,7 +25,7 @@ end
--- Complete the name of a directory relative to the current working directory. --- Complete the name of a directory relative to the current working directory.
-- --
-- @tparam shell shell The shell we're completing in -- @tparam table shell The shell we're completing in
-- @tparam { string... } choices The list of choices to complete from. -- @tparam { string... } choices The list of choices to complete from.
-- @treturn { string... } A list of suffixes of matching directories. -- @treturn { string... } A list of suffixes of matching directories.
local function dir(shell, text) local function dir(shell, text)
@ -35,7 +35,7 @@ end
--- Complete the name of a file or directory relative to the current working --- Complete the name of a file or directory relative to the current working
-- directory. -- directory.
-- --
-- @tparam shell shell The shell we're completing in -- @tparam table shell The shell we're completing in
-- @tparam { string... } choices The list of choices to complete from. -- @tparam { string... } choices The list of choices to complete from.
-- @tparam { string... } previous The shell arguments before this one. -- @tparam { string... } previous The shell arguments before this one.
-- @tparam[opt] boolean add_space Whether to add a space after the completed item. -- @tparam[opt] boolean add_space Whether to add a space after the completed item.
@ -61,9 +61,10 @@ end
--- Complete the name of a program. --- Complete the name of a program.
-- --
-- @tparam shell shell The shell we're completing in -- @tparam table shell The shell we're completing in
-- @tparam { string... } choices The list of choices to complete from. -- @tparam { string... } choices The list of choices to complete from.
-- @treturn { string... } A list of suffixes of matching programs. -- @treturn { string... } A list of suffixes of matching programs.
-- @see shell.completeProgram
local function program(shell, text) local function program(shell, text)
return shell.completeProgram(text) return shell.completeProgram(text)
end end

View File

@ -1,3 +1,21 @@
--- Multishell allows multiple programs to be run at the same time.
--
-- When multiple programs are running, it displays a tab bar at the top of the
-- screen, which allows you to switch between programs. New programs can be
-- launched using the `fg` or `bg` programs, or using the @{shell.openTab} and
-- @{multishell.launch} functions.
--
-- Each process is identified by its ID, which corresponds to its position in
-- the tab list. As tabs may be opened and closed, this ID is _not_ constant
-- over a program's run. As such, be careful not to use stale IDs.
--
-- As with @{shell}, @{multishell} is not a "true" API. Instead, it is a
-- standard program, which launches a shell and injects its API into the shell's
-- environment. This API is not available in the global environment, and so is
-- not available to @{os.loadAPI|APIs}.
--
-- @module[module] multishell
local expect = dofile("rom/modules/main/cc/expect.lua").expect local expect = dofile("rom/modules/main/cc/expect.lua").expect
-- Setup process switching -- Setup process switching
@ -190,12 +208,26 @@ local function setMenuVisible(bVis)
end end
end end
local multishell = {} local multishell = {} --- @export
--- Get the currently visible process. This will be the one selected on
-- the tab bar.
--
-- Note, this is different to @{getCurrent}, which returns the process which is
-- currently executing.
--
-- @treturn number The currently visible process's index.
-- @see setFocus
function multishell.getFocus() function multishell.getFocus()
return nCurrentProcess return nCurrentProcess
end end
--- Change the currently visible process.
--
-- @tparam number n The process index to switch to.
-- @treturn boolean If the process was changed successfully. This will
-- return @{false} if there is no process with this id.
-- @see getFocus
function multishell.setFocus(n) function multishell.setFocus(n)
expect(1, n, "number") expect(1, n, "number")
if n >= 1 and n <= #tProcesses then if n >= 1 and n <= #tProcesses then
@ -206,6 +238,13 @@ function multishell.setFocus(n)
return false return false
end end
--- Get the title of the given tab.
--
-- This starts as the name of the program, but may be changed using
-- @{multishell.setTitle}.
-- @tparam number n The process index.
-- @treturn string|nil The current process title, or @{nil} if the
-- process doesn't exist.
function multishell.getTitle(n) function multishell.getTitle(n)
expect(1, n, "number") expect(1, n, "number")
if n >= 1 and n <= #tProcesses then if n >= 1 and n <= #tProcesses then
@ -214,19 +253,45 @@ function multishell.getTitle(n)
return nil return nil
end end
function multishell.setTitle(n, sTitle) --- Set the title of the given process.
--
-- @tparam number n The process index.
-- @tparam string title The new process title.
-- @see getTitle
-- @usage Change the title of the current process
--
-- multishell.setTitle(multishell.getCurrent(), "Hello")
function multishell.setTitle(n, title)
expect(1, n, "number") expect(1, n, "number")
expect(2, sTitle, "string") expect(2, title, "string")
if n >= 1 and n <= #tProcesses then if n >= 1 and n <= #tProcesses then
setProcessTitle(n, sTitle) setProcessTitle(n, title)
redrawMenu() redrawMenu()
end end
end end
--- Get the index of the currently running process.
--
-- @treturn number The currently running process.
function multishell.getCurrent() function multishell.getCurrent()
return nRunningProcess return nRunningProcess
end end
--- Start a new process, with the given environment, program and arguments.
--
-- The returned process index is not constant over the program's run. It can be
-- safely used immediately after launching (for instance, to update the title or
-- switch to that tab). However, after your program has yielded, it may no
-- longer be correct.
--
-- @tparam table tProgramEnv The environment to load the path under.
-- @tparam string sProgramPath The path to the program to run.
-- @param ... Additional arguments to pass to the program.
-- @treturn number The index of the created process.
-- @see os.run
-- @usage Run the "hello" program, and set its title to "Hello!"
-- local id = multishell.launch({}, "/rom/programs/fun/hello.lua")
-- multishell.setTitle(id, "Hello!")
function multishell.launch(tProgramEnv, sProgramPath, ...) function multishell.launch(tProgramEnv, sProgramPath, ...)
expect(1, tProgramEnv, "table") expect(1, tProgramEnv, "table")
expect(2, sProgramPath, "string") expect(2, sProgramPath, "string")
@ -238,6 +303,9 @@ function multishell.launch(tProgramEnv, sProgramPath, ...)
return nResult return nResult
end end
--- Get the number of processes within this multishell.
--
-- @treturn number The number of processes.
function multishell.getCount() function multishell.getCount()
return #tProcesses return #tProcesses
end end

View File

@ -1,3 +1,15 @@
--- The shell API provides access to CraftOS's command line interface.
--
-- It allows you to @{run|start programs}, @{setCompletionFunction|add
-- completion for a program}, and much more.
--
-- @{shell} is not a "true" API. Instead, it is a standard program, which its
-- API into the programs that it launches. This allows for multiple shells to
-- run at the same time, but means that the API is not available in the global
-- environment, and so is unavailable to other @{os.loadAPI|APIs}.
--
-- @module[module] shell
local expect = dofile("rom/modules/main/cc/expect.lua").expect local expect = dofile("rom/modules/main/cc/expect.lua").expect
local multishell = multishell local multishell = multishell
@ -15,7 +27,7 @@ local tAliases = parentShell and parentShell.aliases() or {}
local tCompletionInfo = parentShell and parentShell.getCompletionInfo() or {} local tCompletionInfo = parentShell and parentShell.getCompletionInfo() or {}
local tProgramStack = {} local tProgramStack = {}
local shell = {} local shell = {} --- @export
local function createShellEnv(sDir) local function createShellEnv(sDir)
local tEnv = {} local tEnv = {}
tEnv.shell = shell tEnv.shell = shell
@ -172,6 +184,18 @@ local function tokenise(...)
end end
-- Install shell API -- Install shell API
--- Run a program with the supplied arguments.
--
-- All arguments are concatenated together and then parsed as a command line. As
-- a result, `shell.run("program a b")` is the same as `shell.run("program",
-- "a", "b")`.
--
-- @tparam string ... The program to run and its arguments.
-- @treturn boolean Whether the program exited successfully.
-- @usage Run `paint my-image` from within your program:
--
-- shell.run("paint", "my-image")
function shell.run(...) function shell.run(...)
local tWords = tokenise(...) local tWords = tokenise(...)
local sCommand = tWords[1] local sCommand = tWords[1]
@ -181,38 +205,83 @@ function shell.run(...)
return false return false
end end
--- Exit the current shell.
--
-- This does _not_ terminate your program, it simply makes the shell terminate
-- after your program has finished. If this is the toplevel shell, then the
-- computer will be shutdown.
function shell.exit() function shell.exit()
bExit = true bExit = true
end end
--- Return the current working directory. This is what is displayed before the
-- `> ` of the shell prompt, and is used by @{shell.resolve} to handle relative
-- paths.
--
-- @treturn string The current working directory.
-- @see setDir To change the working directory.
function shell.dir() function shell.dir()
return sDir return sDir
end end
function shell.setDir(_sDir) --- Set the current working directory.
expect(1, _sDir, "string") --
if not fs.isDir(_sDir) then -- @tparam string dir The new working directory.
-- @throws If the path does not exist or is not a directory.
-- @usage Set the working directory to "rom"
--
-- shell.setDir("rom")
function shell.setDir(dir)
expect(1, dir, "string")
if not fs.isDir(dir) then
error("Not a directory", 2) error("Not a directory", 2)
end end
sDir = fs.combine(_sDir, "") sDir = fs.combine(dir, "")
end end
--- Set the path where programs are located.
--
-- The path is composed of a list of directory names in a string, each separated
-- by a colon (`:`). On normal turtles will look in the current directory (`.`),
-- `/rom/programs` and `/rom/programs/turtle` folder, making the path
-- `.:/rom/programs:/rom/programs/turtle`.
--
-- @treturn string The current shell's path.
-- @see setPath To change the current path.
function shell.path() function shell.path()
return sPath return sPath
end end
function shell.setPath(_sPath) --- Set the @{path|current program path}.
expect(1, _sPath, "string") --
sPath = _sPath -- Be careful to prefix directories with a `/`. Otherwise they will be searched
-- for from the @{shell.dir|current directory}, rather than the computer's root.
--
-- @tparam string path The new program path.
function shell.setPath(path)
expect(1, path, "string")
sPath = path
end end
function shell.resolve(_sPath) --- Resolve a relative path to an absolute path.
expect(1, _sPath, "string") --
local sStartChar = string.sub(_sPath, 1, 1) -- The @{fs} and @{io} APIs work using absolute paths, and so we must convert
-- any paths relative to the @{dir|current directory} to absolute ones. This
-- does nothing when the path starts with `/`.
--
-- @tparam string path The path to resolve.
-- @usage Resolve `startup.lua` when in the `rom` folder.
--
-- shell.setDir("rom")
-- print(shell.resolve("startup.lua"))
-- -- => rom/startup.lua
function shell.resolve(path)
expect(1, path, "string")
local sStartChar = string.sub(path, 1, 1)
if sStartChar == "/" or sStartChar == "\\" then if sStartChar == "/" or sStartChar == "\\" then
return fs.combine("", _sPath) return fs.combine("", path)
else else
return fs.combine(sDir, _sPath) return fs.combine(sDir, path)
end end
end end
@ -226,16 +295,25 @@ local function pathWithExtension(_sPath, _sExt)
return _sPath .. "." .. _sExt return _sPath .. "." .. _sExt
end end
function shell.resolveProgram(_sCommand) --- Resolve a program, using the @{path|program path} and list of @{aliases|aliases}.
expect(1, _sCommand, "string") --
-- @tparam string command The name of the program
-- @treturn string|nil The absolute path to the program, or @{nil} if it could
-- not be found.
-- @usage Locate the `hello` program.
--
-- shell.resolveProgram("hello")
-- -- => rom/programs/fun/hello.lua
function shell.resolveProgram(command)
expect(1, command, "string")
-- Substitute aliases firsts -- Substitute aliases firsts
if tAliases[_sCommand] ~= nil then if tAliases[command] ~= nil then
_sCommand = tAliases[_sCommand] command = tAliases[command]
end end
-- If the path is a global path, use it directly -- If the path is a global path, use it directly
if _sCommand:find("/") or _sCommand:find("\\") then if command:find("/") or command:find("\\") then
local sPath = shell.resolve(_sCommand) local sPath = shell.resolve(command)
if fs.exists(sPath) and not fs.isDir(sPath) then if fs.exists(sPath) and not fs.isDir(sPath) then
return sPath return sPath
else else
@ -249,7 +327,7 @@ function shell.resolveProgram(_sCommand)
-- Otherwise, look on the path variable -- Otherwise, look on the path variable
for sPath in string.gmatch(sPath, "[^:]+") do for sPath in string.gmatch(sPath, "[^:]+") do
sPath = fs.combine(shell.resolve(sPath), _sCommand) sPath = fs.combine(shell.resolve(sPath), command)
if fs.exists(sPath) and not fs.isDir(sPath) then if fs.exists(sPath) and not fs.isDir(sPath) then
return sPath return sPath
else else
@ -264,7 +342,15 @@ function shell.resolveProgram(_sCommand)
return nil return nil
end end
function shell.programs(_bIncludeHidden) --- Return a list of all programs on the @{shell.path|path}.
--
-- @tparam[opt] boolean include_hidden Include hidden files. Namely, any which
-- start with `.`.
-- @treturn { string } A list of available programs.
-- @usage textutils.tabulate(shell.programs())
function shell.programs(include_hidden)
expect(1, include_hidden, "boolean", "nil")
local tItems = {} local tItems = {}
-- Add programs from the path -- Add programs from the path
@ -275,7 +361,7 @@ function shell.programs(_bIncludeHidden)
for n = 1, #tList do for n = 1, #tList do
local sFile = tList[n] local sFile = tList[n]
if not fs.isDir(fs.combine(sPath, sFile)) and if not fs.isDir(fs.combine(sPath, sFile)) and
(_bIncludeHidden or string.sub(sFile, 1, 1) ~= ".") then (include_hidden or string.sub(sFile, 1, 1) ~= ".") then
if #sFile > 4 and sFile:sub(-4) == ".lua" then if #sFile > 4 and sFile:sub(-4) == ".lua" then
sFile = sFile:sub(1, -5) sFile = sFile:sub(1, -5)
end end
@ -351,6 +437,21 @@ local function completeProgramArgument(sProgram, nArgument, sPart, tPreviousPart
return nil return nil
end end
--- Complete a shell command line.
--
-- This accepts an incomplete command, and completes the program name or
-- arguments. For instance, `l` will be completed to `ls`, and `ls ro` will be
-- completed to `ls rom/`.
--
-- Completion handlers for your program may be registered with
-- @{shell.setCompletionFunction}.
--
-- @tparam string sLine The input to complete.
-- @treturn { string }|nil The list of possible completions.
-- @see read For more information about completion.
-- @see shell.completeProgram
-- @see shell.setCompletionFunction
-- @see shell.getCompletionInfo
function shell.complete(sLine) function shell.complete(sLine)
expect(1, sLine, "string") expect(1, sLine, "string")
if #sLine > 0 then if #sLine > 0 then
@ -388,23 +489,66 @@ function shell.complete(sLine)
return nil return nil
end end
function shell.completeProgram(sProgram) --- Complete the name of a program.
expect(1, sProgram, "string") --
return completeProgram(sProgram) -- @tparam string program The name of a program to complete.
-- @treturn { string } A list of possible completions.
-- @see cc.shell.completion.program
function shell.completeProgram(program)
expect(1, program, "string")
return completeProgram(program)
end end
function shell.setCompletionFunction(sProgram, fnComplete) --- Set the completion function for a program. When the program is entered on
expect(1, sProgram, "string") -- the command line, this program will be called to provide auto-complete
expect(2, fnComplete, "function") -- information.
tCompletionInfo[sProgram] = { --
fnComplete = fnComplete, -- The completion function accepts four arguments:
--
-- 1. The current shell. As completion functions are inherited, this is not
-- guaranteed to be the shell you registered this function in.
-- 2. The index of the argument currently being completed.
-- 3. The current argument. This may be the empty string.
-- 4. A list of the previous arguments.
--
-- For instance, when completing `pastebin put rom/st` our pastebin completion
-- function will receive the shell API, an index of 2, `rom/st` as the current
-- argument, and a "previous" table of `{ "put" }`. This function may then wish
-- to return a table containing `artup.lua`, indicating the entire command
-- should be completed to `pastebin put rom/startup.lua`.
--
-- You completion entries may also be followed by a space, if you wish to
-- indicate another argument is expected.
--
-- @tparam string program The path to the program. This should be an absolute path
-- _without_ the leading `/`.
-- @tparam function(shell: table, index: number, argument: string, previous: { string }):({ string }|nil) complete
-- The completion function.
-- @see cc.shell.completion Various utilities to help with writing completion functions.
-- @see shell.complete
-- @see read For more information about completion.
function shell.setCompletionFunction(program, complete)
expect(1, program, "string")
expect(2, complete, "function")
tCompletionInfo[program] = {
fnComplete = complete,
} }
end end
--- Get a table containing all completion functions.
--
-- This should only be needed when building custom shells. Use
-- @{setCompletionFunction} to add a completion function.
--
-- @treturn { [string] = { fnComplete = function } } A table mapping the
-- absolute path of programs, to their completion functions.
function shell.getCompletionInfo() function shell.getCompletionInfo()
return tCompletionInfo return tCompletionInfo
end end
--- Returns the path to the currently running program.
--
-- @treturn string The absolute path to the running program.
function shell.getRunningProgram() function shell.getRunningProgram()
if #tProgramStack > 0 then if #tProgramStack > 0 then
return tProgramStack[#tProgramStack] return tProgramStack[#tProgramStack]
@ -412,17 +556,38 @@ function shell.getRunningProgram()
return nil return nil
end end
function shell.setAlias(_sCommand, _sProgram) --- Add an alias for a program.
expect(1, _sCommand, "string") --
expect(2, _sProgram, "string") -- @tparam string command The name of the alias to add.
tAliases[_sCommand] = _sProgram -- @tparam string program The name or path to the program.
-- @usage Alias `vim` to the `edit` program
--
-- shell.setAlias("vim", "edit")
function shell.setAlias(command, program)
expect(1, command, "string")
expect(2, program, "string")
tAliases[command] = program
end end
function shell.clearAlias(_sCommand) --- Remove an alias.
expect(1, _sCommand, "string") --
tAliases[_sCommand] = nil -- @tparam string command The alias name to remove.
function shell.clearAlias(command)
expect(1, command, "string")
tAliases[command] = nil
end end
--- Get the current aliases for this shell.
--
-- Aliases are used to allow multiple commands to refer to a single program. For
-- instance, the `list` program is aliased `dir` or `ls`. Running `ls`, `dir` or
-- `list` in the shell will all run the `list` program.
--
-- @treturn { [string] = string } A table, where the keys are the names of
-- aliases, and the values are the path to the program.
-- @see shell.setAlias
-- @see shell.resolveProgram This uses aliases when resolving a program name to
-- an absolute path.
function shell.aliases() function shell.aliases()
-- Copy aliases -- Copy aliases
local tCopy = {} local tCopy = {}
@ -433,6 +598,20 @@ function shell.aliases()
end end
if multishell then if multishell then
--- Open a new @{multishell} tab running a command.
--
-- This behaves similarly to @{shell.run}, but instead returns the process
-- index.
--
-- This function is only available if the @{multishell} API is.
--
-- @tparam string ... The command line to run.
-- @see shell.run
-- @see multishell.launch
-- @usage Launch the Lua interpreter and switch to it.
--
-- local id = shell.openTab("lua")
-- shell.switchTab(id)
function shell.openTab(...) function shell.openTab(...)
local tWords = tokenise(...) local tWords = tokenise(...)
local sCommand = tWords[1] local sCommand = tWords[1]
@ -448,9 +627,13 @@ if multishell then
end end
end end
function shell.switchTab(nID) --- Switch to the @{multishell} tab with the given index.
expect(1, nID, "number") --
multishell.setFocus(nID) -- @tparam number id The tab to switch to.
-- @see multishell.setFocus
function shell.switchTab(id)
expect(1, id, "number")
multishell.setFocus(id)
end end
end end