X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=runtime%2Fhelp%2Fplugins.md;h=bf4be6a7edf3ee9855d16dc419aaf634991f39d1;hb=36dc6647dd7a589d97b0bc3808decbb8312a9758;hp=e79c3cc71690b4319a80e06be1f2cb8f18ff7c61;hpb=397361f23dd0c8d59e86bf2a325f19ea9243d51c;p=micro.git diff --git a/runtime/help/plugins.md b/runtime/help/plugins.md index e79c3cc7..bf4be6a7 100644 --- a/runtime/help/plugins.md +++ b/runtime/help/plugins.md @@ -4,10 +4,9 @@ Micro supports creating plugins with a simple Lua system. Every plugin has a main script which is run at startup which should be placed in `~/.config/micro/plugins/pluginName/pluginName.lua`. -There are a number of callback functions which you can create in your -plugin to run code at times other than startup. The naming scheme is -`onAction(view)`. For example a function which is run every time the user saves -the buffer would be: +There are a number of callback functions which you can create in your plugin to +run code at times other than startup. The naming scheme is `onAction(view)`. For +example a function which is run every time the user saves the buffer would be: ```lua function onSave(view) @@ -17,7 +16,8 @@ end ``` The `view` variable is a reference to the view the action is being executed on. -This is almost always the current view, which you can get with `CurView()` as well. +This is almost always the current view, which you can get with `CurView()` as +well. All available actions are listed in the keybindings section of the help. @@ -31,27 +31,28 @@ function onMousePress(view, event) end ``` -These functions should also return a boolean specifying whether the view -should be relocated to the cursor or not after the action is complete. +These functions should also return a boolean specifying whether the view should +be relocated to the cursor or not after the action is complete. -Note that these callbacks occur after the action has been completed. If you -want a callback before the action is executed, use `preAction()`. In this case -the boolean returned specifies whether or not the action should be executed -after the lua code completes. +Note that these callbacks occur after the action has been completed. If you want +a callback before the action is executed, use `preAction()`. In this case the +boolean returned specifies whether or not the action should be executed after +the lua code completes. -Another useful callback to know about which is not a action is +Another useful callback to know about which is not an action is `onViewOpen(view)` which is called whenever a new view is opened and the new -view is passed in. This is useful for setting local options based on the filetype, -for example turning off `tabstospaces` only for Go files when they are opened. +view is passed in. This is useful for setting local options based on the +filetype, for example turning off `tabstospaces` only for Go files when they are +opened. --- -There are a number of functions and variables that are available to you in -order to access the inner workings of micro. Here is a list (the type signatures -for functions are given using Go's type system): +There are a number of functions and variables that are available to you in order +to access the inner workings of micro. Here is a list (the type signatures for +functions are given using Go's type system): -* `OS`: variable which gives the OS micro is currently running on (this is the same -as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...) +* `OS`: variable which gives the OS micro is currently running on (this is the + same as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...) * `configDir`: contains the path to the micro configuration files @@ -61,27 +62,35 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...) * `messenger`: lets you send messages to the user or create prompts -* `NewBuffer(text, path string) *Buffer`: creates a new buffer from a given reader with a given path +* `NewBuffer(text, path string) *Buffer`: creates a new buffer from a given + reader with a given path -* `GetLeadingWhitespace() bool`: returns the leading whitespace of the given string +* `GetLeadingWhitespace() bool`: returns the leading whitespace of the given + string -* `IsWordChar(str string) bool`: returns whether or not the string is a 'word character' +* `IsWordChar(str string) bool`: returns whether or not the string is a 'word + character' * `RuneStr(r rune) string`: returns a string containing the given rune * `Loc(x, y int) Loc`: returns a new `Loc` struct -* `JoinPaths(dir... string) string` combines multiple directories to a full path +* `WorkingDirectory() string`: returns a rooted path name to the current working + directory -* `DirectoryName(path string)` returns all but the last element of path ,typically the path's directory +* `JoinPaths(dir... string) string`: combines multiple directories to a full + path + +* `DirectoryName(path string)`: returns all but the last element of path, + typically the path's directory * `GetOption(name string)`: returns the value of the requested option -* `AddOption(name string, value interface{})`: sets the given option with the given - value (`interface{}` means any type in Go) +* `AddOption(name string, value interface{})`: sets the given option with the + given value (`interface{}` means any type in Go) -* `SetOption(option, value string)`: sets the given option to the value. This will - set the option globally, unless it is a local only option. +* `SetOption(option, value string)`: sets the given option to the value. This + will set the option globally, unless it is a local only option. * `SetLocalOption(option, value string, view *View)`: sets the given option to the value locally in the given buffer @@ -89,8 +98,8 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...) * `BindKey(key, action string)`: binds `key` to `action` * `MakeCommand(name, function string, completions ...Completion)`: - creates a command with `name` which will call `function` when executed. - Use 0 for completions to get NoCompletion. + creates a command with `name` which will call `function` when executed. Use 0 + for completions to get NoCompletion. * `MakeCompletion(function string)`: creates a `Completion` to use with `MakeCommand` @@ -99,68 +108,179 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...) * `HandleCommand(cmd string)`: runs the given command -* `HandleShellCommand(shellCmd string, interactive bool, waitToClose bool)`: runs the given shell - command. The `interactive` bool specifies whether the command should run in the background. The - `waitToClose` bool only applies if `interactive` is true and means that it should wait before - returning to the editor. +* `ExecCommand(name string, args []string) (string, error)`: exec a (shell) command with the + given arguments. Returns the command's output and a possible error. + +* `RunShellCommand(cmd string) (string, error)`: Run a shell command. This uses `ExecCommand` + under the hood but also does some parsing for the arguments (i.e. quoted arguments). The + function returns the command's output and a possible error. + +* `RunBackgroundShell(cmd string)`: Run a shell command in the background. + +* `RunInteractiveShell(cmd string, wait bool, getOutput bool) (string, error)`: Run a shell command + by closing micro and running the command interactively. If `wait` is true, a prompt will be + used after the process exits to prevent the terminal from immediately returning to micro, allowing + the user to view the output of the process. If `getOutput` is true, the command's standard output + will be returned. Note that if `getOutput` is true, some interactive commands may not behave + normally because `isatty` will return false. + +* `RunTermEmulator(cmd string, wait bool, getOutput bool, callback string) error`: Same as + `RunInteractiveShell` except the command is run within the current split in a terminal emulator. + The `callback` input is a string callback to a lua function which will be called when the process + exits. The output of the process will be provided as the first and only argument to the callback + (it will be empty if `getOutput` is false). + Note that this functionality is only supported on some operating systems (linux, darwin, dragonfly, + openbsd, freebsd). Use the `TermEmuSupported` (see below) boolean to determine if the current + system is supported. + +* `TermEmuSupported`: Boolean specifying if the terminal emulator is supported on the version of + micro that is running. -* `ToCharPos(loc Loc, buf *Buffer) int`: returns the character position of a given x, y location +* `ToCharPos(loc Loc, buf *Buffer) int`: returns the character position of a + given x, y location * `Reload`: (Re)load everything -* `ByteOffset(loc Loc, buf *Buffer) int`: exactly like `ToCharPos` except it it counts bytes instead of runes +* `ByteOffset(loc Loc, buf *Buffer) int`: exactly like `ToCharPos` except it it + counts bytes instead of runes * `JobSpawn(cmdName string, cmdArgs []string, onStdout, onStderr, onExit string, userargs ...string)`: - Starts running the given process in the background. `onStdout` `onStderr` and `onExit` - are callbacks to lua functions which will be called when the given actions happen - to the background process. - `userargs` are the arguments which will get passed to the callback functions + Starts running the given process in the background. `onStdout` `onStderr` and + `onExit` are callbacks to lua functions which will be called when the given + actions happen to the background process. `userargs` are the arguments which + will get passed to the callback functions * `JobStart(cmd string, onStdout, onStderr, onExit string, userargs ...string)`: - Starts running the given shell command in the background. Note that the command execute - is first parsed by a shell when using this command. It is executed with `sh -c`. + Starts running the given shell command in the background. Note that the + command execute is first parsed by a shell when using this command. It is + executed with `sh -c`. -* `JobSend(cmd *exec.Cmd, data string)`: send a string into the stdin of the job process +* `JobSend(cmd *exec.Cmd, data string)`: send a string into the stdin of the job + process * `JobStop(cmd *exec.Cmd)`: kill a job This may seem like a small list of available functions but some of the objects returned by the functions have many methods. `CurView()` returns a view object -which has all the actions which you can call. For example `CurView():Save(false)`. -You can see the full list of possible actions in the keybindings help topic. -The boolean on all the actions indicates whether or not the lua callbacks should -be run. I would recommend generally sticking to false when making a plugin to -avoid recursive problems, for example if you call `CurView():Save(true)` in `onSave()`. -Just use `CurView():Save(false)` so that it won't call `onSave()` again. +which has all the actions which you can call. For example +`CurView():Save(false)`. You can see the full list of possible actions in the +keybindings help topic. The boolean on all the actions indicates whether or not +the lua callbacks should be run. I would recommend generally sticking to false +when making a plugin to avoid recursive problems, for example if you call +`CurView():Save(true)` in `onSave()`. Just use `CurView():Save(false)` so that +it won't call `onSave()` again. Using the view object, you can also access the buffer associated with that view -by using `CurView().Buf`, which lets you access the `FileType`, `Path`, `Name`... +by using `CurView().Buf`, which lets you access the `FileType`, `Path`, +`Name`... The possible methods which you can call using the `messenger` variable are: * `messenger.Message(msg ...interface{})` * `messenger.Error(msg ...interface{})` -* `messenger.YesNoPrompt(prompt string) (bool, bool)` +* `messenger.YesNoPrompt(prompt string) (bool,bool)` * `messenger.Prompt(prompt, historyType string, completionType Completion) (string, bool)` +* `messenger.AddLog(msg ...interface{})` -If you want a standard prompt, just use `messenger.Prompt(prompt, "", 0)` +#### Note -# Adding help files, syntax files, or colorschemes in your plugin +Go function signatures use `.` and lua uses `:` so -You can use the `AddRuntimeFile(name, type, path string)` function to add various kinds of -files to your plugin. For example, if you'd like to add a help topic to your plugin -called `test`, you would create a `test.md` file, and call the function: +```go +messenger.Message() +``` + +turns to + +```lua +messenger:Message() +``` + +If you want a standard prompt, just use + +```lua +messenger:Prompt(prompt, "", 0) +``` + +Debug or logging your plugin can be done with below lua example code. + +```lua +messenger:AddLog("Message goes here ",pluginVariableToPrintHere) +``` + +In Micro to see your plugin logging output press `CtrlE` then type `log`, a +logging window will open and any logging sent from your plugin will be displayed +here. + + +## Accessing the Go standard library + +It is possible for your lua code to access many of the functions in the Go +standard library. + +Simply import the package you'd like and then you can use it. For example: + +```lua +local ioutil = import("io/ioutil") +local fmt = import("fmt") + +local data, err = ioutil.ReadFile("SomeFile.txt") + +if err ~= nil then + messenger:Error("Error reading file: SomeFile.txt") +else + -- Data is returned as an array of bytes + -- Using Sprintf will convert it to a string + local str = fmt.Sprintf("%s", data) + + -- Do something with the file you just read! + -- ... +end +``` + +Here are the packages from the Go standard library that you can access. +Nearly all functions from these packages are supported. For an exact +list of which functions are supported you can look through `lua.go` +(which should be easy to understand). + +``` +fmt +io +io/ioutil +net +math +math/rand +os +runtime +path +filepath +strings +regexp +errors +time +``` + +For documentation for each of these functions, you can simply look +through the Go standard library documentation. + +## Adding help files, syntax files, or colorschemes in your plugin + +You can use the `AddRuntimeFile(name, type, path string)` function to add +various kinds of files to your plugin. For example, if you'd like to add a help +topic to your plugin called `test`, you would create a `test.md` file, and call +the function: ```lua AddRuntimeFile("test", "help", "test.md") ``` -Use `AddRuntimeFilesFromDirectory(name, type, dir, pattern)` to add a number of files -to the runtime. -To read the content of a runtime file use `ReadRuntimeFile(fileType, name string)` -or `ListRuntimeFiles(fileType string)` for all runtime files. +Use `AddRuntimeFilesFromDirectory(name, type, dir, pattern)` to add a number of +files to the runtime. To read the content of a runtime file use +`ReadRuntimeFile(fileType, name string)` or `ListRuntimeFiles(fileType string)` +for all runtime files. + -# Autocomplete command arguments +## Autocomplete command arguments See this example to learn how to use `MakeCompletion` and `MakeCommand` @@ -190,27 +310,32 @@ end MakeCommand("foo", "example.foo", MakeCompletion("example.complete")) ``` -# Default plugins + +## Default plugins For examples of plugins, see the default `autoclose` and `linter` plugins -(stored in the normal micro core repo under `runtime/plugins`) as well as -any plugins that are stored in the official channel [here](https://github.com/micro-editor/plugin-channel). +(stored in the normal micro core repo under `runtime/plugins`) as well as any +plugins that are stored in the official channel +[here](https://github.com/micro-editor/plugin-channel). + -# Plugin Manager +## Plugin Manager -Micro also has a built in plugin manager which you can invoke with the `> plugin ...` command. +Micro also has a built in plugin manager which you can invoke with the +`> plugin ...` command. For the valid commands you can use, see the `command` help topic. -The manager fetches plugins from the channels (which is simply a list of plugin metadata) -which it knows about. By default, micro only knows about the official channel which is located -at github.com/micro-editor/plugin-channel but you can add your own third-party channels using -the `pluginchannels` option and you can directly link third-party plugins to allow installation -through the plugin manager with the `pluginrepos` option. +The manager fetches plugins from the channels (which is simply a list of plugin +metadata) which it knows about. By default, micro only knows about the official +channel which is located at github.com/micro-editor/plugin-channel but you can +add your own third-party channels using the `pluginchannels` option and you can +directly link third-party plugins to allow installation through the plugin +manager with the `pluginrepos` option. -If you'd like to publish a plugin you've made as an official plugin, you should upload your -plugin online (to Github preferably) and add a `repo.json` file. This file will contain the -metadata for your plugin. Here is an example: +If you'd like to publish a plugin you've made as an official plugin, you should +upload your plugin online (to Github preferably) and add a `repo.json` file. +This file will contain the metadata for your plugin. Here is an example: ```json [{ @@ -229,7 +354,8 @@ metadata for your plugin. Here is an example: }] ``` -Then open a pull request at github.com/micro-editor/plugin-channel adding a link to the -raw `repo.json` that is in your plugin repository. -To make updating the plugin work, the first line of your plugins lua code should contain the version of the plugin. (Like this: `VERSION = "1.0.0"`) -Please make sure to use [semver](http://semver.org/) for versioning. +Then open a pull request at github.com/micro-editor/plugin-channel adding a link +to the raw `repo.json` that is in your plugin repository. To make updating the +plugin work, the first line of your plugins lua code should contain the version +of the plugin. (Like this: `VERSION = "1.0.0"`) Please make sure to use +[semver](http://semver.org/) for versioning.