2016-07-28 22:52:31 +03:00
|
|
|
# Plugins
|
|
|
|
|
2016-08-13 23:22:18 +03:00
|
|
|
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`.
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
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:
|
2016-08-13 23:22:18 +03:00
|
|
|
|
|
|
|
```lua
|
2016-08-26 00:24:13 +03:00
|
|
|
function onSave(view)
|
2016-08-13 23:22:18 +03:00
|
|
|
...
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
```
|
|
|
|
|
2016-08-26 00:24:13 +03:00
|
|
|
The `view` variable is a reference to the view the action is being executed on.
|
2017-10-11 16:16:53 +03:00
|
|
|
This is almost always the current view, which you can get with `CurView()` as
|
|
|
|
well.
|
2016-08-26 00:24:13 +03:00
|
|
|
|
2016-08-13 23:22:18 +03:00
|
|
|
All available actions are listed in the keybindings section of the help.
|
|
|
|
|
2017-06-18 00:36:27 +03:00
|
|
|
For callbacks to mouse actions, you are also given the event info:
|
|
|
|
|
|
|
|
```lua
|
|
|
|
function onMousePress(view, event)
|
|
|
|
local x, y = event:Position()
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
```
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
These functions should also return a boolean specifying whether the view should
|
|
|
|
be relocated to the cursor or not after the action is complete.
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
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.
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2017-10-02 05:33:03 +03:00
|
|
|
Another useful callback to know about which is not an action is
|
2016-08-26 00:29:58 +03:00
|
|
|
`onViewOpen(view)` which is called whenever a new view is opened and the new
|
2017-10-11 16:16:53 +03:00
|
|
|
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.
|
2016-08-26 00:29:58 +03:00
|
|
|
|
2016-08-13 23:22:18 +03:00
|
|
|
---
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
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):
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `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`...)
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2016-09-19 14:23:47 +03:00
|
|
|
* `configDir`: contains the path to the micro configuration files
|
|
|
|
|
2016-08-26 00:24:13 +03:00
|
|
|
* `tabs`: a list of all the tabs currently in use
|
|
|
|
|
|
|
|
* `curTab`: the index of the current tabs in the tabs list
|
|
|
|
|
|
|
|
* `messenger`: lets you send messages to the user or create prompts
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `NewBuffer(text, path string) *Buffer`: creates a new buffer from a given
|
|
|
|
reader with a given path
|
2016-12-11 03:24:49 +03:00
|
|
|
|
2018-02-02 21:57:02 +03:00
|
|
|
* `NewBufferFromFile(path string) *Buffer`: creates a new buffer from a given
|
|
|
|
path
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `GetLeadingWhitespace() bool`: returns the leading whitespace of the given
|
|
|
|
string
|
2016-12-11 03:24:49 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `IsWordChar(str string) bool`: returns whether or not the string is a 'word
|
|
|
|
character'
|
2016-12-11 03:24:49 +03:00
|
|
|
|
2016-09-19 14:23:47 +03:00
|
|
|
* `RuneStr(r rune) string`: returns a string containing the given rune
|
|
|
|
|
|
|
|
* `Loc(x, y int) Loc`: returns a new `Loc` struct
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `WorkingDirectory() string`: returns a rooted path name to the current working
|
|
|
|
directory
|
2016-09-19 14:23:47 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `JoinPaths(dir... string) string`: combines multiple directories to a full
|
|
|
|
path
|
2017-09-02 17:30:19 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `DirectoryName(path string)`: returns all but the last element of path,
|
|
|
|
typically the path's directory
|
2016-11-18 19:53:48 +03:00
|
|
|
|
2016-08-26 00:24:13 +03:00
|
|
|
* `GetOption(name string)`: returns the value of the requested option
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `AddOption(name string, value interface{})`: sets the given option with the
|
|
|
|
given value (`interface{}` means any type in Go)
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `SetOption(option, value string)`: sets the given option to the value. This
|
|
|
|
will set the option globally, unless it is a local only option.
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2016-12-14 23:11:57 +03:00
|
|
|
* `SetLocalOption(option, value string, view *View)`: sets the given option to
|
2016-09-09 07:07:58 +03:00
|
|
|
the value locally in the given buffer
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2016-09-09 07:07:58 +03:00
|
|
|
* `BindKey(key, action string)`: binds `key` to `action`
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2016-08-26 00:24:13 +03:00
|
|
|
* `MakeCommand(name, function string, completions ...Completion)`:
|
2017-10-11 16:16:53 +03:00
|
|
|
creates a command with `name` which will call `function` when executed. Use 0
|
|
|
|
for completions to get NoCompletion.
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2016-09-02 20:50:19 +03:00
|
|
|
* `MakeCompletion(function string)`:
|
2016-09-09 07:07:58 +03:00
|
|
|
creates a `Completion` to use with `MakeCommand`
|
2016-09-02 20:50:19 +03:00
|
|
|
|
2016-08-26 00:24:13 +03:00
|
|
|
* `CurView()`: returns the current view
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2016-08-26 00:24:13 +03:00
|
|
|
* `HandleCommand(cmd string)`: runs the given command
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2018-01-23 05:03:52 +03:00
|
|
|
* `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.
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `ToCharPos(loc Loc, buf *Buffer) int`: returns the character position of a
|
|
|
|
given x, y location
|
2016-12-11 03:24:49 +03:00
|
|
|
|
|
|
|
* `Reload`: (Re)load everything
|
2016-10-29 03:34:28 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `ByteOffset(loc Loc, buf *Buffer) int`: exactly like `ToCharPos` except it it
|
|
|
|
counts bytes instead of runes
|
2016-10-29 03:34:28 +03:00
|
|
|
|
2016-11-16 08:13:17 +03:00
|
|
|
* `JobSpawn(cmdName string, cmdArgs []string, onStdout, onStderr, onExit string, userargs ...string)`:
|
2017-10-11 16:16:53 +03:00
|
|
|
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
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2016-11-16 08:13:17 +03:00
|
|
|
* `JobStart(cmd string, onStdout, onStderr, onExit string, userargs ...string)`:
|
2017-10-11 16:16:53 +03:00
|
|
|
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`.
|
2016-11-16 08:13:17 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
* `JobSend(cmd *exec.Cmd, data string)`: send a string into the stdin of the job
|
|
|
|
process
|
2016-08-13 23:22:18 +03:00
|
|
|
|
2016-08-26 00:24:13 +03:00
|
|
|
* `JobStop(cmd *exec.Cmd)`: kill a job
|
2016-08-13 23:22:18 +03:00
|
|
|
|
|
|
|
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
|
2017-10-11 16:16:53 +03:00
|
|
|
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.
|
2016-08-17 18:56:56 +03:00
|
|
|
|
|
|
|
Using the view object, you can also access the buffer associated with that view
|
2017-10-11 16:16:53 +03:00
|
|
|
by using `CurView().Buf`, which lets you access the `FileType`, `Path`,
|
|
|
|
`Name`...
|
2016-08-17 18:56:56 +03:00
|
|
|
|
|
|
|
The possible methods which you can call using the `messenger` variable are:
|
|
|
|
|
|
|
|
* `messenger.Message(msg ...interface{})`
|
|
|
|
* `messenger.Error(msg ...interface{})`
|
2017-09-02 17:30:19 +03:00
|
|
|
* `messenger.YesNoPrompt(prompt string) (bool,bool)`
|
2016-08-17 18:56:56 +03:00
|
|
|
* `messenger.Prompt(prompt, historyType string, completionType Completion) (string, bool)`
|
2017-09-02 17:30:19 +03:00
|
|
|
* `messenger.AddLog(msg ...interface{})`
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
#### Note
|
|
|
|
|
2017-09-11 19:23:19 +03:00
|
|
|
Go function signatures use `.` and lua uses `:` so
|
|
|
|
|
2017-09-02 17:30:19 +03:00
|
|
|
```go
|
|
|
|
messenger.Message()
|
|
|
|
```
|
2017-09-11 19:23:19 +03:00
|
|
|
|
|
|
|
turns to
|
|
|
|
|
|
|
|
```lua
|
|
|
|
messenger:Message()
|
|
|
|
```
|
2017-09-02 17:30:19 +03:00
|
|
|
|
|
|
|
If you want a standard prompt, just use
|
2017-10-11 16:16:53 +03:00
|
|
|
|
2017-09-02 17:30:19 +03:00
|
|
|
```lua
|
|
|
|
messenger:Prompt(prompt, "", 0)
|
|
|
|
```
|
2016-08-17 18:56:56 +03:00
|
|
|
|
2017-09-02 17:30:19 +03:00
|
|
|
Debug or logging your plugin can be done with below lua example code.
|
2017-10-11 16:16:53 +03:00
|
|
|
|
2017-09-02 17:30:19 +03:00
|
|
|
```lua
|
|
|
|
messenger:AddLog("Message goes here ",pluginVariableToPrintHere)
|
|
|
|
```
|
2017-09-11 19:23:19 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
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.
|
|
|
|
|
2016-08-17 18:56:56 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
## Accessing the Go standard library
|
2017-09-11 19:23:19 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
It is possible for your lua code to access many of the functions in the Go
|
|
|
|
standard library.
|
2017-09-11 19:23:19 +03:00
|
|
|
|
|
|
|
Simply import the package you'd like and then you can use it. For example:
|
|
|
|
|
|
|
|
```lua
|
2017-11-16 22:29:36 +03:00
|
|
|
local ioutil = import("io/ioutil")
|
2017-09-11 19:23:19 +03:00
|
|
|
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
|
|
|
|
```
|
|
|
|
|
2017-11-16 22:29:36 +03:00
|
|
|
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).
|
2017-09-11 19:23:19 +03:00
|
|
|
|
2017-11-16 22:29:36 +03:00
|
|
|
```
|
|
|
|
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.
|
2016-09-16 18:02:10 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
## 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:
|
2016-09-16 18:02:10 +03:00
|
|
|
|
|
|
|
```lua
|
|
|
|
AddRuntimeFile("test", "help", "test.md")
|
|
|
|
```
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
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.
|
|
|
|
|
2016-09-27 21:24:52 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
## Autocomplete command arguments
|
2016-09-02 20:50:19 +03:00
|
|
|
|
|
|
|
See this example to learn how to use `MakeCompletion` and `MakeCommand`
|
|
|
|
|
|
|
|
```lua
|
|
|
|
local function StartsWith(String,Start)
|
2017-06-18 00:36:27 +03:00
|
|
|
String = String:upper()
|
|
|
|
Start = Start:upper()
|
|
|
|
return string.sub(String,1,string.len(Start))==Start
|
2016-09-02 20:50:19 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
function complete(input)
|
2017-06-18 00:36:27 +03:00
|
|
|
local allCompletions = {"Hello", "World", "Foo", "Bar"}
|
|
|
|
local result = {}
|
|
|
|
|
|
|
|
for i,v in pairs(allCompletions) do
|
|
|
|
if StartsWith(v, input) then
|
|
|
|
table.insert(result, v)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return result
|
2016-09-02 20:50:19 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
function foo(arg)
|
2017-06-18 00:36:27 +03:00
|
|
|
messenger:Message(arg)
|
2016-09-02 20:50:19 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
MakeCommand("foo", "example.foo", MakeCompletion("example.complete"))
|
|
|
|
```
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
|
|
|
|
## Default plugins
|
2016-08-17 18:56:56 +03:00
|
|
|
|
2016-10-07 03:28:10 +03:00
|
|
|
For examples of plugins, see the default `autoclose` and `linter` plugins
|
2017-10-11 16:16:53 +03:00
|
|
|
(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).
|
|
|
|
|
2016-10-06 01:26:41 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
## Plugin Manager
|
2016-10-06 01:26:41 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
Micro also has a built in plugin manager which you can invoke with the
|
|
|
|
`> plugin ...` command.
|
2016-10-06 01:26:41 +03:00
|
|
|
|
|
|
|
For the valid commands you can use, see the `command` help topic.
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
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.
|
2016-10-06 01:26:41 +03:00
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
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:
|
2016-10-06 01:26:41 +03:00
|
|
|
|
|
|
|
```json
|
|
|
|
[{
|
|
|
|
"Name": "pluginname",
|
|
|
|
"Description": "Here is a nice concise description of my plugin",
|
|
|
|
"Tags": ["python", "linting"],
|
|
|
|
"Versions": [
|
|
|
|
{
|
|
|
|
"Version": "1.0.0",
|
|
|
|
"Url": "https://github.com/user/plugin/archive/v1.0.0.zip",
|
|
|
|
"Require": {
|
|
|
|
"micro": ">=1.0.3"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}]
|
|
|
|
```
|
|
|
|
|
2017-10-11 16:16:53 +03:00
|
|
|
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.
|