{"id":21517559,"url":"https://github.com/tek/myo","last_synced_at":"2025-04-09T21:42:45.711Z","repository":{"id":43478930,"uuid":"164256909","full_name":"tek/myo","owner":"tek","description":"neovim layout \u0026 command manager","archived":false,"fork":false,"pushed_at":"2024-06-28T15:32:41.000Z","size":1102,"stargazers_count":6,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-09-01T03:59:51.841Z","etag":null,"topics":["commands","error","haskell","neovim","parser","tmux"],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tek.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-05T22:41:52.000Z","updated_at":"2024-06-28T15:26:06.000Z","dependencies_parsed_at":"2023-10-29T14:31:24.733Z","dependency_job_id":"fc67e6ca-5477-4143-90d0-a6ea7f30bcb5","html_url":"https://github.com/tek/myo","commit_stats":{"total_commits":275,"total_committers":2,"mean_commits":137.5,"dds":"0.18545454545454543","last_synced_commit":"bf468ee552d0502470aeb6dc8583fd8c1e193d3e"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tek%2Fmyo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tek%2Fmyo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tek%2Fmyo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tek%2Fmyo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tek","download_url":"https://codeload.github.com/tek/myo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226113180,"owners_count":17575436,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commands","error","haskell","neovim","parser","tmux"],"created_at":"2024-11-24T00:42:29.760Z","updated_at":"2024-11-24T00:42:30.633Z","avatar_url":"https://github.com/tek.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Intro\n\n**Myo** is a [Neovim] plugin written in [Haskell] with the plugin framework [Ribosome].\n\nIt provides several interacting features that include:\n* [**UI**](#ui): automatic opening, closing and layouting of tmux panes\n* [**Commands**](#commands): Execution of configurable shell commands in [tmux] or subprocesses\n* [**Output**](#output): Parsing, rendering and navigation of messages produced by commands\n\n**Myo** benefits a lot from having per-project and per-project-type configuration for setting up language-specific commands.\nIf you don't have a solution for this, the author also maintains [proteome], a project management plugin.\n\n![Haskell output screenshot](img/haskell-output.png)\n\n# Install\n\nThe plugin can be loaded by specifying the repo to a package manager like any other, for example by cloning it in a\nsubdirectory of `'packpath'` or using one of the many plugin managers.\n\n```vim\nPlug 'tek/myo'\n```\n\nSince the plugin is written in Haskell, its executable has to be fetched or built on the first start.\n\n* If the [Nix package manager](https://nixos.org/learn.html) is available, the plugin will be fetched from the Nix cache\n  (or built if the current commit isn't in the cache)\n* Otherwise it will be downloaded from Github's releases.\n* If the variable `g:myo_fetch_bin` is set to `1`, Nix is ignored and the binary is downloaded from Github\n  regardless.\n\n# Configuration\n\nThere are a few settings that, when changing their variables, will trigger\nreconfiguration of the corresponding component:\n\n* `myo_ui`\n* `myo_commands`\n\n**Myo** uses several autocommands to detect changes.\n\nFor the examples in this Readme, I will be using a setup for compiling and testing [Scala] with [sbt].\n\n## MyoDiag\n\nThis command will display some information about the plugin in a scratch buffer.\n\n# UI\n\nThe purpose of the UI component is to allow creating tracked tmux panes with a fixed layout from mappings that are\ncleaned up when vim quits.\nThe UI is configured through the variable `myo_ui` whenever it is modified.\nIts schema looks like this:\n\n```vim\nlet s:sbt_pane =\n      \\ {\n      \\ 'layout': 'make',\n      \\ 'ident': 'sbt',\n      \\ 'minSize': 0.5,\n      \\ 'maxSize': 35,\n      \\ 'position': 8\n      \\ }\nlet g:myo_ui = {\n      \\ 'panes': [s:sbt_pane]\n      \\ }\n```\n\nThese settings will be combined with the built-in default layout that consists of determining the window and pane in\nwhich Neovim has been started and a vertical layout named `make` positioned to the right of the Neovim pane that\ncontains one pane, also called `make`, which is used as the default target when executing system commands.\n\nIt is possible to set up much more complex layouts, with windows and sessions yet to come.\nThe `myo_ui` variable may contain a key `layouts` with the same schema as for panes.\n\nThe library used for interacting with tmux is [chiasma].\n\n### Pane Fields\n\n* `layout` is the name of the parent layout of the pane.\n* `pin` causes this pane to be opened whenever its layout becomes visible, i.e. when another pane in it is opened.\n   The default `make` pane has this set.\n* `position` is a value that orders panes in a layout. It can have any numerical value.\n* `fixed_size` tries to make a pane always have this number of lines or columns.\n* `minimized_size`, default `2`, is the number of cells that the pane gets when minimized.\n* `weight` is used to distribute surplus space onto panes.\n\nPanes open automatically when a command is executed in them, but there are functions for doing so manually.\n\n## Opening and minimizing panes and layouts\n\n```vim\n:MyoTogglePane sbt\n```\n\nwill open the pane `sbt` in the lower right corner, or, if it is open already, minimize it to a size of two cells in the\ndirection of its parent layout (in this case, vertically).\n\n```vim\n:MyoToggleLayout make\n```\n\nwill open the primary pane of the layout `make` if no panes in the layout are open, or minimize the layout.\n\n```vim\n:MyoOpenPane sbt\n:MyoOpenLayout make\n```\n\nwill perform the same tasks, but won't minimize an already open view.\n\n```vim\n:MyoHidePane sbt\n:MyoHideLayout make\n```\n\nwill minimize the view if it is open, otherwise it will do nothing.\n\n## MyoFocus\n\nThis command takes a pane name and will set it as the active pane in tmux.\n\n## Inspecting view state\n\n```vim\n:echo MyoPaneState('make')\n```\n\nwill print the current target state of a pane (what is configured by **Myo**, not the actual tmux state).\n\n```vim\n:echo MyoLayoutState('make')\n```\n\nwill print the same for a layout.\n\n# Commands\n\nA command consists of a list of shell commands and some optional values:\n* a tmux pane in which to execute it\n* a shell command in which to execute it\n* a runner (tmux or subprocess)\n* a language for parsing its output\n\nCommands are read from the `myo_commands` variable:\n\n```vim\nlet s:sbt_cmd = {\n  \\ 'ident': 'sbt',\n  \\ 'lines': ['sbt'],\n  \\ 'target': 'sbt',\n  \\ 'lang': 'scala',\n  \\ }\nlet s:compile_cmd = {\n  \\ 'ident': 'compile',\n  \\ 'lines': ['test:compile'],\n  \\ 'target': 'sbt',\n  \\ 'lang': 'scala',\n  \\ }\nlet g:myo_commands = { 'system': [s:sbt_cmd], 'shell': [s:compile_cmd] }\n```\n\nThis snippet defines a _system command_ (run directly in the tmux pane) with the command line `sbt` that will be\nexecuted in the previously created pane `sbt` (defined by the `target` field).\n\nNext, it defines a _shell command_ named `compile`, which has as its target the name of a system command, here `sbt`.\nThis means that when running this command, it will be sent to the tmux pane running `sbt` (it will be started if\nnecessary) and some interactions with it, like output parsing, will be deferred to the system command.\nIts command line is `test:compile`, which is the text sent to `sbt`.\n\n### Command Fields\n\n* `ident` is the name of the command, to be used with `MyoRun` and `MyoParse`.\n* `lines` is a list of command lines that will be executed in tmux. For subprocess commands, only one line is valid.\n* `target` points to a pane or shell in which the command will be run.\n* `lang` is used to find the appropriate parser for command output. Currently supported: `scala`, `haskell`.\n* `displayName` is an optional override for the text to be displayed to the user instead of the `ident`.\n* `skipHistory` is a boolean that excludes the command from the command history.\n* `kill` is a boolean that causes a running command to be killed when another one is run in the same target.\n* `capture` is a boolean that changes how the command's output is parsed.\n  If it is `true`, the currently visible output in a tmux pane is used; otherwise, the entire output since the start of\n  execution.\n* `maxLogBytes` is a number that limits the size of the stored output.\n\n### Parameter interpolation\n\nCommand lines may be template strings with references to parameters:\n\n```vim\nlet ghc_test_cmd = {\n  \\ 'ident': 'test',\n  \\ 'lines': ['hadrian/build test {test_way:--test-way={test_way}} {test_options} {test_case:--only={test_case}}'],\n  \\ 'params': { 'test_options': '-j6' }\n  \\ 'target': 'make',\n  \\ }\n```\n\nThere are four variants of interpolations:\n\n* `{param_name}` substitutes the value and terminates with error if it is undefined\n* `{param_name:}` substitutes the value or the empty string\n* `{param_name:expr}` processes `expr` as a template or substitutes the empty string if the parameter is undefined\n* `{param_name?expr}` processes `expr` as a template if the parameter is a boolean and true (`v:true` or a nonzero\n  number) or substitutes the empty string if the parameter is false or undefined\n\nParameter values are determined from several sources, in decreasing order of precedence:\n\n* [CLI-style options](#cli).\n* Overrides from edits in a menu.\n* Overrides from the command option callback.\n* The nvim function `Myo_param_\u003cname\u003e`.\n  For example, for the param `{test_case}`, the function `Myo_param_test_case` is called.\n  The return value must be a string or boolean, depending on the parameter type.\n  Two special return values are recognized:\n  * `{ 'ignore': 1 }` continues resolution with the next sources (essentially \"fallback to default\")\n  * `{ 'error': 'Custom error message' }` will abort execution of the command and print the error message\n* The nvim variable `\u003cscope\u003e:myo_param_\u003cname\u003e` from the scopes `g:`, `t:`, `w:`, `b:` in that order.\n  For example, `b:myo_param_test_case`.\n* The default values specified in the command config's attribute `params`.\n  If this is specified, the interpolation styles `{param_name:}` and `{param_name}` behave identically and always\n  substitute the default as fallback.\n\n## MyoRun\n\nThis Neovim command/function triggers the execution of a **Myo** command:\n\n```vim\nMyoRun compile\n```\n\nThis invocation will:\n* create the tmux panes for `sbt` (which will also create `make` since it is pinned).\n* run `sbt` in its pane\n* send `test:compile` to the `sbt` pane\n\nSubsequent invocations will check the stored process ID and skip the second step if it is alive.\n\n### Per-invocation option overrides\n\nThe command's options may be overridden by a Neovim callback.\nIf the callback exists, **Myo** will call it whenever `MyoRun` is executed.\nThe functions name has the schema `MyoOverrides_\u003ccommand-name\u003e`, where the name is escaped by substituting\nnon-alphanumerical characters by `_`.\nThe name is either the command's `displayName` or, if that's undefined, its `ident`.\nFor example, for a command named `some test-command`, the function name will be `MyoOverrides_some_test_command`.\n\nThe user may return arbitrary command options from that function, in particular a command line and a set of\ninterpolation parameter values.\n\nThe purpose of this is to adapt options based on the current cursor context, to \"run the test at the cursor position\".\nA special Neovim command, `MyoTest`, uses an automatically created command to make this more explicit.\nImportantly, this doesn't happen when the command is rerun from the history – the first invocation can lock in a certain\nposition, to be repeated later without changing to the new position of the cursor.\n\nThe function must take an argument, which will contain the following data:\n\n```json\n{\n  \"path\": \"/path/to/file\",\n  \"rel\": \"relative/path/to/file\",\n  \"line\": 5,\n  \"col\": 10,\n  \"text\": \"content of the cursor line\",\n  \"cword\": \"result of expand('\u003ccword\u003e')\"\n}\n```\n\nThese denote the position of the cursor.\nIf the current buffer is not a file, the `path` attribute will contain Neovim's current working directory and `rel` will\nbe empty.\nThe indexes are zero-based.\n\nThe function's return value may either be a dict or a single command line string.\n\nIf the `command` attribute is returned, the named command will be executed instead of the originally requested one.\nThis is primarily useful for `MyoTest`.\n\nIf `myo-test` isn't defined, a default configuration will be created.\nThis command can be used to set a template string for all test executions that is dynamically changed by parameter\nvalues returned from `MyoTestOverrides`.\n\nThe `lines` attribute, or the returned string, overrides the command's default template, which may contain interpolation\nplaceholders that will be resolved as described above.\n\nIf the `params` attribute is returned, it will be used to override the parameter values from the sources described\nabove.\n\nIf the `shell` attribute is returned, it will set the command by that name as the shell in which the test will run;\notherwise, the `target` attribute may set the tmux pane target.\n\n### CLI style overrides {#cli}\n\nThe commands `MyoRun` and `MyoTest` allow an additional method for parameter overrides – CLI arguments:\n\n```vim\nMyoRun compile --debug=on --name='test name' --fast\n```\n\nThese have the highest precedence.\nThe `--param=value` variant works for string arguments, while `--flag` enables booleans.\n\n## MyoReRun\n\nThis function allows you to run commands from the history.\nFor example, to run the previous command again:\n\n```vim\n:MyoReRun 0\n```\n\n## MyoTest\n\nThis Neovim command/function runs the command `myo-test`, which will be created with default settings if the user didn't\nconfigure it.\nIt will call the function `MyoTestOverrides` instead of the command name based function to determine the overrides.\nThis is mere convenience to ensure that a command for running the cursor test is always available.\n\n## MyoHistory\n\nThis command displays the history in a scratch buffer with a prompt for substring searching.\nSelecting one of the entries with `\u003ccr\u003e` will rerun the command.\nThe prompt starts in normal mode, where you can cycle through the history with `j`/`k`, run a command with `\u003ccr\u003e`,\nand abort with `\u003cesc\u003e` or `\u003cc-c\u003e`.\n\nPressing `e` will change to a different view, in which each of the command lines and parameters will be listed.\nPressing `e` again on one of them will load its value into the prompt, where it can be modified and written back with\n`\u003cesc\u003e`.\nWhen you are satisfied with the edits, you can press `\u003ccr\u003e` to run the command with the modified values.\n\n## MyoCommands\n\nThis command displays all defined commands in a menu like [`MyoHistory`](#myohistory).\n\n## MyoVimTest\n\n**Myo** features support for [vim-test], which is a plugin with many built-in heuristics for determining the appropriate\ncommand to execute something relating to the current cursor position.\nWhen running this function:\n\n```vim\n:MyoVimTest\n```\n\n**Myo** will call [vim-test] and execute its output in the pane or shell configured by `g:myo_test_pane` or\n`g:myo_test_shell` (default being `make`).\n\n# Output\n\nWhen a command is executed, its output is read into **Myo**'s state.\nRunning the command\n\n```vim\n:MyoParseLatest\n```\n\nWill run the appropriate parser, read from the command option `pane` or the variable `g:myo_test_lang` (currently only\n`haskell or ``scala`), and display its result in a scratch window, as showcased in the screenshot at the top of the\nreadme.\n\nAfter parsing, the cursor will be set to the last of first error (depending on the values of `g:myo_output_jump_first`\nand `g:myo_output_auto_jump`).\nUsing the functions `MyoPrev` and `MyoNext`, you can cycle through the error list.\n\n# Default Commands\n\nFor some languages, a default layout and command set will be set up on startup.\nTo prevent this, set:\n\n```vim\nlet g:myo_default_commands = v:false\n```\n\n[Neovim]: https://github.com/neovim/neovim\n[Haskell]: https://www.haskell.org\n[ribosome]: https://github.com/tek/ribosome\n[chromatin]: https://github.com/tek/chromatin\n[tmux]: https://github.com/tmux/tmux\n[proteome]: https://github.com/tek/proteome\n[Scala]: https://scala-lang.org\n[sbt]: https://scala-sbt.org\n[chiasma]: https://github.com/tek/chiasma\n[vim-test]: https://github.com/janko/vim-test\n[stack]: https://docs.haskellstack.org/en/stable/README\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftek%2Fmyo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftek%2Fmyo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftek%2Fmyo/lists"}