]> git.lizzy.rs Git - micro.git/blobdiff - runtime/help/plugins.md
Make debug mode flag, plugins can access logbuf
[micro.git] / runtime / help / plugins.md
index 763f015c91b416a4d064b2e81117568205152806..6c431068542fd888fb18b127d6230e1b440cb949 100644 (file)
 # Plugins
 
-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`.
+Micro supports creating plugins with a simple Lua system. Plugins are
+folders containing Lua files and possibly other source files placed
+in `~/.config/micro/plug`. The plugin directory (within `plug`) should
+contain at least one Lua file and an `info.json` file. The info file
+provides additional information such as the name of the plugin, the
+plugin's website, dependencies, etc... Here is an example info file
+from the go plugin, which has the following file structure:
 
-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)
-    ...
-    return false
-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.
-
-All available actions are listed in the keybindings section of the help.
-
-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
+~/.config/micro/plug/go-plugin/
+    go.lua
+    info.json
+    help/
+        go-plugin.md
 ```
 
-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.
+The `go.lua` file contains the main code for the plugin, though the
+code may be distributed across multiple Lua files. The `info.json`
+file contains information about the plugin such as the website,
+description, version, and any requirements. Plugins may also
+have additional files which can be added to micro's runtime files,
+of which there are 5 types:
 
-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.
+* Colorschemes
+* Syntax files
+* Help files
+* Plugin files
+* Syntax header files
 
----
+In most cases, a plugin will want to add help files, but in certain
+cases a plugin may also want to add colorschemes or syntax files. It
+is unlikely for a plugin to need to add plugin files at runtime or
+syntax header files. No directory structure is enforced but keeping
+runtime files in their own directories is good practice.
 
-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):
+# Info file
 
-* `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`...)
+The `info.json` for the Go plugin is the following:
 
-* `configDir`: contains the path to the micro configuration files
-
-* `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
-
-* `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
-
-* `IsWordChar(str string) bool`: returns whether or not the string is a 'word
-   character'
+```
+{
+    "name": "go",
+    "description": "Go formatting and tool support",
+    "website": "https://github.com/micro-editor/go-plugin",
+       "install": "https://github.com/micro-editor/go-plugin",
+    "version": "1.0.0",
+    "require": [
+        "micro >= 2.0.0"
+    ]
+}
+```
 
-* `RuneStr(r rune) string`: returns a string containing the given rune
+All fields are simply interpreted as strings, so the version does not
+need to be a semantic version, and the dependencies are also only
+meant to be parsed by humans. The name should be an identifier, and
+the website should point to a valid website. The install field should
+provide info about installing the plugin, or point to a website that
+provides information.
 
-* `Loc(x, y int) Loc`: returns a new `Loc` struct
+Note that the name of the plugin is defined by the name field in
+the `info.json` and not by the installation path. Some functions micro
+exposes to plugins require passing the name of the plugin.
 
-* `WorkingDirectory() string`: returns a rooted path name to the current working
-   directory
+## Lua callbacks
 
-* `JoinPaths(dir... string) string`: combines multiple directories to a full
-   path
+Plugins use Lua but also have access to many functions both from micro
+and from the Go standard library. Many callbacks are also defined which
+are called when certain events happen. Here is the list of callbacks
+which micro defines:
 
-* `DirectoryName(path string)`: returns all but the last element of path,
-   typically the path's directory
+* `init()`: this function should be used for your plugin initialization.
 
-* `GetOption(name string)`: returns the value of the requested option
+* `onBufferOpen(buf)`: runs when a buffer is opened. The input contains
+   the buffer object.
 
-* `AddOption(name string, value interface{})`: sets the given option with the
-   given value (`interface{}` means any type in Go)
+* `onBufPaneOpen(bufpane)`: runs when a bufpane is opened. The input
+   contains the bufpane object.
 
-* `SetOption(option, value string)`: sets the given option to the value. This
-   will set the option globally, unless it is a local only option.
+* `onAction(bufpane)`: runs when `Action` is triggered by the user, where
+   `Action` is a bindable action (see `> help keybindings`). A bufpane
+   is passed as input and the function should return a boolean defining
+   whether the view should be relocated after this action is performed.
 
-* `SetLocalOption(option, value string, view *View)`: sets the given option to
-   the value locally in the given buffer
+* `preAction(bufpane)`: runs immediately before `Action` is triggered
+   by the user. Returns a boolean which defines whether the action should
+   be canceled.
 
-* `BindKey(key, action string)`: binds `key` to `action`
+For example a function which is run every time the user saves the buffer
+would be:
 
-* `MakeCommand(name, function string, completions ...Completion)`: 
-   creates a command with `name` which will call `function` when executed. Use 0
-   for completions to get NoCompletion.
+```lua
+function onSave(bp)
+    ...
+    return false
+end
+```
 
-* `MakeCompletion(function string)`:
-   creates a `Completion` to use with `MakeCommand`
+The `bp` variable is a reference to the bufpane the action is being executed within.
+This is almost always the current bufpane.
 
-* `CurView()`: returns the current view
+All available actions are listed in the keybindings section of the help.
 
-* `HandleCommand(cmd string)`: runs the given command
+For callbacks to mouse actions, you are also given the event info:
 
-* `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.
+```lua
+function onMousePress(view, event)
+    local x, y = event:Position()
 
-* `ToCharPos(loc Loc, buf *Buffer) int`: returns the character position of a
-   given x, y location
+    return false
+end
+```
 
-* `Reload`: (Re)load everything
+These functions should also return a boolean specifying whether the bufpane should
+be relocated to the cursor or not after the action is complete.
 
-* `ByteOffset(loc Loc, buf *Buffer) int`: exactly like `ToCharPos` except it it
-   counts bytes instead of runes
+## Accessing micro functions
 
-* `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
+Some of micro's internal information is exposed in the form of packages which
+can be imported by Lua plugins. A package can be imported in Lua and a value
+within it can be accessed using the following syntax:
 
-* `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`.
+```lua
+local micro = import("micro")
+micro.Log("Hello")
+```
 
-* `JobSend(cmd *exec.Cmd, data string)`: send a string into the stdin of the job
-   process
+The packages and functions are listed below (in Go type signatures):
+
+* `micro`
+    - `TermMessage(msg interface{}...)`
+    - `TermError()`
+    - `InfoBar()`
+    - `Log(msg interface{}...)`
+    - `SetStatusInfoFn(fn string)`
+* `micro/config`
+    - `MakeCommand`
+    - `FileComplete`
+    - `HelpComplete`
+    - `OptionComplete`
+    - `OptionValueComplete`
+    - `NoComplete`
+    - `TryBindKey`
+    - `Reload`
+    - `AddRuntimeFilesFromDirectory`
+    - `AddRuntimeFileFromMemory`
+    - `AddRuntimeFile`
+    - `ListRuntimeFiles`
+    - `ReadRuntimeFile`
+    - `RTColorscheme`
+    - `RTSyntax`
+    - `RTHelp`
+    - `RTPlugin`
+    - `RegisterCommonOption`
+    - `RegisterGlobalOption`
+* `micro/shell`
+    - `ExecCommand`
+    - `RunCommand`
+    - `RunBackgroundShell`
+    - `RunInteractiveShell`
+    - `JobStart`
+    - `JobSpawn`
+    - `JobStop`
+    - `JobStop`
+    - `RunTermEmulator`
+    - `TermEmuSupported`
+* `micro/buffer`
+    - `NewMessage`
+    - `NewMessageAtLine`
+    - `MTInfo`
+    - `MTWarning`
+    - `MTError`
+    - `Loc`
+    - `BTDefault`
+    - `BTLog`
+    - `BTRaw`
+    - `BTInfo`
+    - `NewBufferFromFile`
+    - `ByteOffset`
+    - `Log`
+    - `LogBuf`
+* `micro/util`
+    - `RuneAt`
+    - `GetLeadingWhitespace`
+    - `IsWordChar`
 
-* `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.
+returned by the functions have many methods. The Lua plugin may access any
+public methods of an object returned by any of the functions above. Unfortunately
+it is not possible to list all the available functions on this page. Please
+go to the internal documentation at https://godoc.org/github.com/zyedidia/micro
+to see the full list of available methods. Note that only methods of types that
+are available to plugins via the functions above can be called from a plugin.
+For an even more detailed reference see the source code on Github.
 
-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`...
+For example, with a BufPane object called `bp`, you could call the `Save` function
+in Lua with `bp:Save()`.
 
-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.Prompt(prompt, historyType string, completionType Completion) (string, bool)`
-* `messenger.AddLog(msg ...interface{})`
-
-#### Note 
-
-Go function signatures use `.` and lua uses `:` so
+Note that Lua uses the `:` syntax to call a function rather than Go's `.` syntax.
 
 ```go
-messenger.Message()
+micro.InfoBar().Message()
 ```
 
 turns to
 
 ```lua
-messenger:Message()
+micro.InfoBar():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
@@ -199,13 +218,14 @@ standard library.
 Simply import the package you'd like and then you can use it. For example:
 
 ```lua
-local ioutil = import("ioutil")
+local ioutil = import("io/ioutil")
 local fmt = import("fmt")
+local micro = import("micro")
 
 local data, err = ioutil.ReadFile("SomeFile.txt")
 
 if err ~= nil then
-    messenger:Error("Error reading file: SomeFile.txt")
+    micro.InfoBar():Error("Error reading file: SomeFile.txt")
 else
     -- Data is returned as an array of bytes
     -- Using Sprintf will convert it to a string
@@ -216,104 +236,76 @@ else
 end
 ```
 
-For a full list of which packages and functions from the standard library you
-can access, look at `lua.go` in the source code (it shouldn't be too hard to
-look through).
+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, see the Go standard
+library documentation at https://golang.org/pkg/ (for the packages
+exposed to micro plugins). The Lua standard library is also available
+to plugins though it is rather small.
 
 ## 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:
+You can use the `AddRuntimeFile(name string, type config.RTFiletype, 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")
+config = import("micro/config")
+config.AddRuntimeFile("test", config.RTHelp, "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.
-
-
-## Autocomplete command arguments
-
-See this example to learn how to use `MakeCompletion` and `MakeCommand`
-
-```lua
-local function StartsWith(String,Start)
-    String = String:upper()
-    Start = Start:upper() 
-    return string.sub(String,1,string.len(Start))==Start
-end
-
-function complete(input)
-    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
-end
-
-function foo(arg)
-    messenger:Message(arg)
-end
-
-MakeCommand("foo", "example.foo", MakeCompletion("example.complete"))
-```
-
+for all runtime files. In addition, there is `AddRuntimeFileFromMemory` which
+adds a runtime file based on a string that may have been constructed at
+runtime.
 
 ## 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).
+There are 6 default plugins that come pre-installed with micro. These are
 
+* `autoclose`: automatically closes brackets, quotes, etc...
+* `comment`: provides automatic commenting for a number of languages
+* `ftoptions`: alters some default options depending on the filetype
+* `linter`: provides extensible linting for many languages
+* `literate`: provides advanced syntax highlighting for the Literate
+   programming tool.
+* `status`: provides some extensions to the status line (integration with
+   Git and more).
 
-## Plugin Manager
+These are good examples for many use-cases if you are looking to write
+your own plugins.
 
-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.
-
-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
-[{
-  "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"
-      }
-    }
-  ]
-}]
-```
+## Plugin Manager
 
-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.
+Micro's plugin manager is you! Ultimately the plugins that are created
+for micro are quite simple and don't require a complex automated tool
+to manage them. They should be "git cloned" or somehow placed in the
+`~/.config/micro/plug` directory, and that is all that's necessary
+for installation. In the rare case that a more complex installation
+process is needed (such as dependencies, or additional setup) the
+plugin creator should provide the additional instructions on their
+website and point to the link using the `install` field in the `info.json`
+file.