[
  {
    "path": ".gitignore",
    "content": ".dirt-samples\n"
  },
  {
    "path": "CHANGELOG",
    "content": "0.3.3\n\n* Fix syntax highlighting issues with the `#` operator\n\n0.3.2\n\n* Update README\n\n0.3.1\n\n* Add <c-e> mapping for sending paragraphs, on Normal, Visual and Insert modes\n* Flash text selection when sending text\n* Force tmux to use 256 colors on tidalvim\n* Add <c-h> maping as an alternative to <localleader>h\n* Try to use getcurpos() if available when restoring cursor position\n\n0.3.0\n\n* Update bootstrap script for Tidal 0.9\n* `tidalvim` now only creates 2 panes for Vim and GHCi\n* Split `tidalvim` script in two scripts: `tidal` and `tidalvim`\n* Better instructions for customizing Tidal bootstrap script\n\n0.2.0\n\n* Remove vim-slime dependency\n* Preserve cursor position when sending to tmux\n* Configure tmux automatically with defaults\n\n0.1.0\n\n* Use Slime to communicate via tmux\n* Create \"tidalvim\" script for creating Dirt and Tidal instances\n* Define more vim-like default bindings\n* Add bindings to silence channels\n* Add bindings for playing first occurrence of stream\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\nadvances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at munshkr@gmail.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014 Damián Emiliano Silvani\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "mkfile_path := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))\n\nprefix=/usr/local\n\ninstall:\n\tln -fs $(mkfile_path)/bin/tidal $(prefix)/bin\n\tln -fs $(mkfile_path)/bin/tidalvim $(prefix)/bin\n\nuninstall:\n\trm -f $(prefix)/bin/tidal $(prefix)/bin/tidalvim\n\n.PHONY: install uninstall\n"
  },
  {
    "path": "README.md",
    "content": "# vim-tidal #\n\nA Vim/NeoVim plugin for [TidalCycles](http://tidalcycles.org), the language for\nlive coding musical patterns written in Haskell.\n\nThis plugin by default uses [tmux](https://tmux.github.io/), a known and loved\nterminal multiplexer, for communicating with between Vim and the Tidal\ninterpreter.  It was originally based on\n[vim-slime](https://github.com/jpalardy/vim-slime).\n\n![](http://i.imgur.com/frOLFFI.gif)\n\nIf you are using Vim8 or NeoVim, you can use the native Terminal feature instead\nof tmux. Read the Configuration section on how to enable it.\n\n[![asciicast](https://asciinema.org/a/224891.svg)](https://asciinema.org/a/224891)\n\n## Getting Started ##\n\n1. Start livecoding with Vim by simply running:\n\n   ```bash\n   $ tidalvim\n   ```\n\n   This creates a tmux session with Vim and Tidal running on different panes.\n\n2. Write something like this:\n\n   ```haskell\n   d1 $ sound \"bd sn\"\n   ```\n\n3. While being on that line, press `<c-e>` (Control + E) to evaluate it.\n\n   You should see Vim flash that line for a second and a chunk of text appear on\n   your Tidal interpreter.  If you already have SuperDirt or other synth running,\n   you should hear a kick and a snare :)\n\n## Install ##\n\nMake sure you have TidalCycles installed, with SuperDirt running. See [the Tidal wiki](https://tidalcycles.org/index.php/Userbase) for more information.\n\n### Install tmux ###\n\n#### Ubuntu/Debian ####\n\nYou can install it from the main repos:\n\n    $ sudo apt-get install tmux\n\n#### OSX ####\n\n    $ brew install tmux\n\n#### Windows ####\n\nThere seems to be [a Cygwin package for\ntmux](https://cygwin.com/cgi-bin2/package-cat.cgi?file=x86%2Ftmux%2Ftmux-1.9a-1&grep=tmux),\nbut at present it is [not working](https://github.com/microsoft/terminal/issues/5132#issuecomment-604560893) with any known terminal emulator for Windows. As such, this plugin has only been tested with the *Windows native* build of [Neovim](https://github.com/tidalcycles/vim-tidal#neovim-terminal-target).\n\n\n### Install plugin ###\n\nI recommend using a Vim plugin manager like\n[Plug](https://github.com/junegunn/vim-plug).  Check the link for instructions\non installing and configuring.  If you don't want a plugin manager, you can\nalso download the latest release\n[here](https://github.com/tidalcycles/vim-tidal/releases) and extract the\ncontents on your Vim directory (usually `~/.vim/`).\n\nFor example, with Plug you need to:\n\n  * Edit your `.vimrc` file and add these lines:\n\n```vim\nPlug 'tidalcycles/vim-tidal'\n```\n\n  * Restart Vim and execute `:PlugInstall` to automatically download and\n    install the plugins.\n\n#### UNIX-based Systems ####\n\nIf you are on a UNIX-based operating system (Linux distributions, MacOS, etc.), go to the plugin repository and run `make install`:\n\n(if you are using NeoVim and you won't run tmux then you don't need to run `make install` to be able to load the plugin inside NeoVim)\n\n    $ cd ~/.vim/plugged/vim-tidal\n    $ sudo make install\n\nThis creates symlinks on `/usr/local/bin` for `tidal` and `tidalvim` scripts.\nYou can remove them later if you want with `make uninstall`.\n\n#### Windows ####\n\n:warning: **This plugin has only been tested on Windows 10 using Neovim >0.5**\n\nIf you are on Windows, add the `vim-tidal\\bin` directory to your `PATH` user environment variable:\n\n    1. Click the `Start` button\n    2. Type \"Edit the system environment variables\" and hit `enter` or click on the search result\n    3. Click the button labeled `Environment variables...`\n    4. In the `User variables for [username]` table, click the entry for the `Path` variable, followed by the `Edit...` button beneath the same table\n    5. Click the `New` button in the following dialog, enter the *full path* to the `vim-tidal\\bin` directory, and click `OK` until all the preceding dialogs are closed.\n\nNote: The full path to the `vim-tidal\\bin` directory, will look something like `C:\\Users\\[username]\\AppData\\Local\\nvim\\plugged\\vim-tidal\\bin`, assuming you are using vim-plug as this document recommends.\n\n#### Final Installation Note ####\n\nMake sure to have the `filetype plugin on` setting on your .vimrc, otherwise\nplugin won't be loaded when opening a .tidal file.\n\n### Older Tidal versions (pre 1.0) ###\n\nTidal 1.0 introduces some breaking changes, so if haven't upgraded yet, you can\nstill use this plugin with an older version. Just point your Plug entry to use\nthe `tidal-0.9` branch.\n\nFirst change your Plug line on your `.vimrc` to:\n\n```vim\nPlug 'tidalcycles/vim-tidal', {'branch': 'tidal-0.9'}\n```\n\nThen on Vim run `:PlugInstall` to update your plugin.\n\n\n## Usage\n\nThis plugin comes bundled with two Bash scripts: `tidalvim` and `tidal`.\n\n### `tidalvim`\n\n`tidalvim` starts a tmux session with the screen horizontally splitted, having\nVim on the upper pane and the Tidal interpreter on the lower pane.  This is the\nsimplest way to start using Tidal with Vim.\n\nYou don't have to use `tidalvim` necessarily. If you have a more complex setup\nor just want to use Vim outside of tmux, you can use `tidal`.  See below.\n\n### `tidal`\n\n`tidal` fires up GHCi (the Glasgow Haskell interpreter) and runs a bootstrap\nfile that loads Tidal up. `tidalvim` uses this script to start the Tidal\ninterpreter on the lower pane.  You can even use it standalone (without Vim) by\nsimply running `tidal` from your shell.\n\n```haskell\n$ tidal\nGHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help\ntidal> d1 $ sound \"bd sn\"\ntidal> :t density 2 $ n \"0 1\"\ndensity 2 $ n \"0 1\" :: Pattern ParamMap\n```\n\nSo, in case you don't want to use `tidalvim`, just run the following on another\nterminal:\n\n```bash\ntmux new-session -s tidal tidal\n```\n\nWhat `tidal` does is actually run `ghci` with the argument `-ghci-script\nTidal.ghci`.  [Tidal.ghci](Tidal.ghci) is found at the root of the repository,\nand is responsible for bootstraping Tidal.  See Configure section for more on\nhow to customize Tidal bootstraping process.  Any extra arguments when running\n`tidal` will be delegated to `ghci`.\n\n### Commands\n\nThese are some of the commands that can be run from Vim command line:\n\n* `:<range>TidalSend`: Send a `[range]` of lines. If no range is provided the\n  current line is sent.\n\n* `:TidalSend1 {text}`: Send a single line of text specified on the command\n  line.\n\n* `:TidalConfig`: Configure tmux socket name and target pane\n\n* `:TidalSilence [num]`: Silence stream number `[num]` by sending `d[num]\n  silence`.\n\n* `:TidalPlay [num]`: Send first ocurrence of stream number `[num`] from the\n  current cursor position.\n\n* `:TidalHush`: Silences all streams by sending `hush`.\n\n* `:TidalGenerateCompletions {path}`: Generate dictionary for Dirt-Samples\n  completion (path is optional).\n\n### Default bindings\n\nUsing one of these key bindings you can send lines to Tidal:\n\n* `<c-e>` (Control+E), `<localleader>ss`: Send current inner paragraph.\n* `<localleader>s`: Send current line or current visually selected block.\n\n`<c-e>` can be called on either Normal, Visual, Select or Insert mode, so it is\nprobably easier to type than `<localleader>ss` or `<localleader>s`.\n\nThere are other bindings to control Tidal like:\n\n* `<localleader>s[num]`: Call `:TidalPlay [num]`\n* `<localleader>[num]`: Call `:TidalSilence [num]`\n* `<localleader>h`, `<c-h>`: Call `:TidalHush`\n\n#### About `<localleader>`\n\nThe `<leader>` key is a special key used to perform commands with a sequence of\nkeys.  The `<localleader>` key behaves as the `<leader>` key, but is *local* to\na buffer.  In particular, the above bindings only work in buffers with the\n\"tidal\" file type set, e.g. files whose file type is `.tidal`\n\nBy default, there is no `<localleader>` set.  To define one, e.g. for use with\na comma (`,`), write this on your `.vimrc` file:\n\n```vim\nlet maplocalleader=\",\"\n```\n\nReload your configuration (or restart Vim), and after typing `,ss` on a few\nlines of code, you should see those being copied onto the Tidal interpreter on\nthe lower pane.\n\n\n## Configure ##\n\n### GHCI\n\nBy default, `vim-tidal` uses the globally installed GHCI to launch the REPL.\nIf you have installed Tidal through Stack (`stack install tidal`) or some other\nmeans, you can specify another command to use with `g:tidal_ghci`.\n\nFor example, if one installed Tidal with Stack, they would use:\n\n```vim\nlet g:tidal_ghci = \"stack exec ghci --\"\n```\n\n### Tidal Boot File\n\nA \"Tidal boot file\" is a file that may be used to initialise Tidal within GHCI.\nA custom boot file can be specified using the `g:tidal_boot` variable.\n\nIn the case that `g:tidal_boot` is unspecified, vim-tidal will traverse parent\ndirectories until one of either `BootTidal.hs`, `Tidal.ghci` or `boot.tidal` are\nfound.\n\nIf no tidal boot file can be found by traversing parent directories, tidal will\ncheck the `g:tidal_boot_fallback` variable for a fallback boot file. This\nvariable is useful for specifying a default user-wide tidal boot file on your\nsystem, while still allowing each tidal project to optionally use their own\ndedicated, local tidal boot file. By default, `g:tidal_boot_fallback` will point\nto the `Tidal.ghci` file provided with this plugin.\n\n### Default bindings ###\n\nBy default, there are two normal keybindings and one for visual blocks using\nyour `<localleader>` key.  If you don't have one defined, set it on your\n`.vimrc` script with `let maplocalleader=\",\"`, for example.\n\nIf you don't like some of the bindings or want to change them, add this line to\ndisable them:\n\n```vim\nlet g:tidal_no_mappings = 1\n```\n\nSee section Mappings on [ftplugin/tidal.vim](ftplugin/tidal.vim) and copy the\nbindings you like to your `.vimrc` file and modify them.\n\n### Vim Terminal\n\nOn both Vim (version 8 or above) and NeoVim, the default target in which we boot\nTidal with GHCi is the native terminal.\n\nWhile it is the default, it can also be specified manually with the following:\n\n```vim\nlet g:tidal_target = \"terminal\"\n```\n\nOpen a file with a `.tidal` suffix, write and send a line of code to tidal, and\nthe tidal terminal will open in a window below your editor.\n\nUse standard vim window navigation controls to focus the terminal (ie `<C-w> down/up`)\n\nYou can learn more about the native Vim terminal here:\n\nhttps://vimhelp.org/terminal.txt.html\n\n### tmux (alternative to Vim terminal)\n\nBefore Vim had native terminal support, this plugin provided a \"tmux\" target in\norder to allow for multiplexing the user's terminal via the 3rd party CLI tool.\nIf you have `tmux` installed and you wish to use it instead of the native Vim\nterminal, you can enable this target with the following:\n\n```vim\nlet g:tidal_target = \"tmux\"\n```\n\nThis target will be enabled automatically in the case that the version of Vim in\nuse does not have native terminal support.\n\nYou can configure tmux socket name and target pane by typing `<localleader>c`\nor `:TidalConfig`.  This will prompt you first for the socket name, then for\nthe target pane.\n\nAbout the target pane:\n\n* `\":\"` means current window, current pane (a reasonable default)\n* `\":i\"` means the ith window, current pane\n* `\":i.j\"` means the ith window, jth pane\n* `\"h:i.j\"` means the tmux session where h is the session identifier (either\n  session name or number), the ith window and the jth pane\n\nWhen you exit Vim you will lose that configuration. To make this permanent, set\n`g:tidal_default_config` on your `.vimrc`.  For example, suppose you want to run\nTidal on a tmux session named `omg`, and the GHCi interpreter will be running\non the window 1 and pane 0.  In that case you would need to add this line:\n\n```vim\nlet g:tidal_default_config = {\"socket_name\": \"default\", \"target_pane\": \"omg:1.0\"}\n```\n\n### Optional Supercollider Terminal\n\nVim-tidal provides an option for automatically running the supercollider\ncommand-line tool `sclang` alongside the Tidal GCHI terminal. By default this\nterminal is disabled, however it can be enabled with the following:\n\n```vim\nlet g:tidal_sc_enable = 1\n```\n\nThis can be useful to avoid the need to manually run sclang in a separate\nterminal or to open the supercollider IDE.\n\nA custom supercollider boot file can be specified by assigning its path to the\n`g:tidal_sc_boot` variable.\n\nIn the case that `g:tidal_sc_boot` is unspecified, vim-tidal will traverse\nparent directories until one of either `boot.sc` or `boot.scd` are found.\n\nIf no supercollider boot file can be found by traversing parent directories,\ntidal will check the `g:tidal_sc_boot_fallback` variable for a fallback boot\nfile. This variable is useful for specifying a default user-wide supercollider\nboot file on your system, while still allowing each tidal project to optionally\nuse their own dedicated, local supercollider boot file.\n\nBy default, `g:tidal_sc_boot_fallback` will point to the `boot.sc` file provided\nwith this plugin which simply starts SuperDirt with the default settings.\n\n### Miscellaneous ###\n\nWhen sending a paragraph or a single line, vim-tidal will \"flash\" the selection\nfor some milliseconds.  By default duration is set to 150ms, but you can modify\nit by setting the `g:tidal_flash_duration` variable.\n\nWrite the paste buffer to an external text file:\n\n```vim\nlet g:tidal_paste_file = \"/tmp/tidal_paste_file.txt\"\n```\n\nFor customizing the startup script for defining helper functions, see below.\n\n\n## `tidalvim` and `tidal` ##\n\n`tidalvim`  is just an example script.  You can copy and customize it as much\nas you want.  See `man tmux` if you want to know more about its options.\n\nFor example, if you want to split horizontally instead of vertically, change\nthe `-v` for `-h` option in the `split-window` line:\n\n```diff\n- split-window -v -t $SESSION   \\; \\\n+ split-window -h -t $SESSION   \\; \\\n```\n\nBoth scripts have some options that you can specify as environment variables.\nFor example:\n\n```\nTIDAL_TEMPO_IP=192.168.0.15 SESSION=whatever tidalvim\n```\n\nThis would start Tidal synced to another Tidal on 192.168.0.15, and it would\ntry to attach or create a tmux sesssion called `whatever`.\n\nThe following is a list of all variables that can be changed:\n\n* `FILE`: File name to open with Vim (default: `$(date +%F).tidal`, e.g.\n  `2017-03-09.tidal`).  The `.tidal` extension is important (you can run\n  `:setfiletype haskell.tidal` in case you won't use a .tidal file here).\n\n* `SESSION`: tmux session name (default: `tidal`)\n\n* `TIDAL_BOOT_PATH`: Tidal Bootstrap file, a .ghci file (default: `Tidal.ghci`)\n\n* `TIDAL_TEMPO_IP`: Tells Tidal to sync tempo with another Tidal instance on\n  the specified IP (default: `127.0.0.1`, i.e. use local)\n\n* `VIM`: Vim command (default: `vim`)\n\n* `GHCI`: GHCi command (default: `ghci`)\n\n* `TMUX`: tmux command (default: `tmux`)\n\n### Customizing Tidal startup ###\n\nIn case you have defined some helper functions, and/or you want to import other\nmodules into Tidal, you can edit the `Tidal.ghci` found at the root of the\nrepository.\n\nHowever doing this could eventually cause conflicts when trying to upgrade\nvim-tidal, so instead I recommend that you define a different `.ghci` file that\nfirst loads `Tidal.ghci` and includes all your custom definitions.\n\nHere is an example.  Suppose you define a `myStuff.ghci` file on your home\ndirectory like this:\n\n```haskell\n--file: ~/myStuff.ghci\n\n-- Bootstrap Tidal\n-- Replace this path if you have vim-tidal installed elsewhere\n:script ~/.vim/bundle/vim-tidal/Tidal.ghci\n\n:{\nlet foo = every 4 $ within (0.75, 1) (density 4)\n    bar = n \"<0 1 2 4>\"\n:}\n```\n\nThen, you would run `tidal` or `tidalvim` with `TIDAL_BOOT_PATH` pointing to\nyour new script file:\n\n```bash\nTIDAL_BOOT_PATH=~/myStuff.ghci tidalvim\n```\n\nPlease note that this a `.ghci` script, not a Haskell module. So multiline\ndefinitions need to be wrapped around `:{` and `:}`, as shown in the example\nabove.\n\n\n## Troubleshooting\n\nHere is a list of common problems.\n\n> I press `<c-e>` but it moves the screen down by one line, and nothing else happens\n\nUsually `<c-e>` is used to move the screen forward by one line, but vim-tidal remaps\nthis to sending current paragraph. If this is happening you either:\n\n1. Opened a file without `.tidal` extension, or changed file type accidentally.\n   *Solution*: Reopen Vim or set filetype for current buffer with `:set\n   ft=tidal`.\n2. Have `g:tidal_no_mappings` setting on your `.vimrc`. This disables all\n   mappings.\n   *Solution*: Remove `<c-e>` binding, or rebind to something else.\n\nIt could also be that you do not have `filetype plugin on` setting in your\n.vimrc.  Make sure you have that setting defined.\n\n> I press `<c-e>` and nothing else happens\n\nThis means that vim-tidal is sending text to tmux, but to the wrong\nsession/window/pane.\n*Solution*: Check that you have configure the socket name and target pane\ncorrectly.  See the Configure section above for more information.\n\nIf you have any question or something does not work as expected, there are many\nchannels you can go to:\n\n* [Chat](https://talk.lurk.org/): Reach out at the `#tidal` and `#vim` channels\n* [GitHub issues](https://github.com/tidalcycles/vim-tidal/issues/new)\n* [Official Tidal forum](https://we.lurk.org/postorius/lists/tidal.we.lurk.org/)\n\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at\n<https://github.com/tidalcycles/vim-tidal>.  This project is intended to be a\nsafe, welcoming space for collaboration, and contributors are expected to\nadhere to the [Contributor Covenant](http://contributor-covenant.org) code of\nconduct.\n\n\n## License\n\nRefer to the [LICENSE](LICENSE) file\n"
  },
  {
    "path": "Tidal.ghci",
    "content": ":set -XOverloadedStrings\n:set prompt \"\"\n\nimport Sound.Tidal.Context\n\nimport System.IO (hSetEncoding, stdout, utf8)\nhSetEncoding stdout utf8\n\n-- total latency = oLatency + cFrameTimespan\ntidal <- startTidal (superdirtTarget {oLatency = 0.1, oAddress = \"127.0.0.1\", oPort = 57120}) (defaultConfig {cVerbose = True, cFrameTimespan = 1/20})\n\n:{\nlet only = (hush >>)\n    p = streamReplace tidal\n    hush = streamHush tidal\n    panic = do hush\n               once $ sound \"superpanic\"\n    list = streamList tidal\n    mute = streamMute tidal\n    unmute = streamUnmute tidal\n    unmuteAll = streamUnmuteAll tidal\n    unsoloAll = streamUnsoloAll tidal\n    solo = streamSolo tidal\n    unsolo = streamUnsolo tidal\n    once = streamOnce tidal\n    first = streamFirst tidal\n    asap = once\n    nudgeAll = streamNudgeAll tidal\n    all = streamAll tidal\n    resetCycles = streamResetCycles tidal\n    setcps = asap . cps\n    getcps = streamGetcps tidal\n    getnow = streamGetnow tidal\n    xfade i = transition tidal True (Sound.Tidal.Transition.xfadeIn 4) i\n    xfadeIn i t = transition tidal True (Sound.Tidal.Transition.xfadeIn t) i\n    histpan i t = transition tidal True (Sound.Tidal.Transition.histpan t) i\n    wait i t = transition tidal True (Sound.Tidal.Transition.wait t) i\n    waitT i f t = transition tidal True (Sound.Tidal.Transition.waitT f t) i\n    jump i = transition tidal True (Sound.Tidal.Transition.jump) i\n    jumpIn i t = transition tidal True (Sound.Tidal.Transition.jumpIn t) i\n    jumpIn' i t = transition tidal True (Sound.Tidal.Transition.jumpIn' t) i\n    jumpMod i t = transition tidal True (Sound.Tidal.Transition.jumpMod t) i\n    jumpMod' i t p = transition tidal True (Sound.Tidal.Transition.jumpMod' t p) i\n    mortal i lifespan release = transition tidal True (Sound.Tidal.Transition.mortal lifespan release) i\n    interpolate i = transition tidal True (Sound.Tidal.Transition.interpolate) i\n    interpolateIn i t = transition tidal True (Sound.Tidal.Transition.interpolateIn t) i\n    clutch i = transition tidal True (Sound.Tidal.Transition.clutch) i\n    clutchIn i t = transition tidal True (Sound.Tidal.Transition.clutchIn t) i\n    anticipate i = transition tidal True (Sound.Tidal.Transition.anticipate) i\n    anticipateIn i t = transition tidal True (Sound.Tidal.Transition.anticipateIn t) i\n    forId i t = transition tidal False (Sound.Tidal.Transition.mortalOverlay t) i\n    d1 = p 1 . (|< orbit 0)\n    d2 = p 2 . (|< orbit 1)\n    d3 = p 3 . (|< orbit 2)\n    d4 = p 4 . (|< orbit 3)\n    d5 = p 5 . (|< orbit 4)\n    d6 = p 6 . (|< orbit 5)\n    d7 = p 7 . (|< orbit 6)\n    d8 = p 8 . (|< orbit 7)\n    d9 = p 9 . (|< orbit 8)\n    d10 = p 10 . (|< orbit 9)\n    d11 = p 11 . (|< orbit 10)\n    d12 = p 12 . (|< orbit 11)\n    d13 = p 13\n    d14 = p 14\n    d15 = p 15\n    d16 = p 16\n:}\n\n:{\nlet getState = streamGet tidal\n    setI = streamSetI tidal\n    setF = streamSetF tidal\n    setS = streamSetS tidal\n    setR = streamSetR tidal\n    setB = streamSetB tidal\n:}\n\n:set prompt \"tidal> \"\n:set prompt-cont \"\"\n\ndefault (Pattern String, Integer, Double)\n"
  },
  {
    "path": "bin/generate-completions",
    "content": "#!/usr/bin/env sh\n\nsamplepath=$1\noutputpath=$2\n\nls \"$samplepath\" | sed 's/README.md//; s/Dirt-Samples.quark//;' | sed '/^\\s*$/d' > \"$outputpath\"\n"
  },
  {
    "path": "bin/tidal",
    "content": "#!/usr/bin/env bash\nset -euf -o pipefail\n\nGHCI=${GHCI:-\"ghci\"}\nTIDAL_DATA_DIR=$($GHCI -e Paths_tidal.getDataDir | sed 's/\"//g')\nTIDAL_BOOT_PATH=${TIDAL_BOOT_PATH:-\"$TIDAL_DATA_DIR/BootTidal.hs\"}\n\n# Run GHCI and load Tidal bootstrap file\n$GHCI -ghci-script $TIDAL_BOOT_PATH \"$@\"\n"
  },
  {
    "path": "bin/tidal.bat",
    "content": "@ECHO OFF\n\nREM Store the directory containing the script in a variable\nSET \"source=%~dp0\"\n\nREM Get path to vim-tidal bootfile\nSET \"TIDAL_BOOT_PATH=%SOURCE%\\..\\Tidal.ghci\"\n\nREM Launch Tidal Cycles\nghci -ghci-script \"%TIDAL_BOOT_PATH%\""
  },
  {
    "path": "bin/tidalvim",
    "content": "#!/usr/bin/env bash\nset -euf -o pipefail\n\nVIM=${VIM:-\"vim\"}\nTMUX=${TMUX:-\"tmux\"}\n\nFILE=${FILE:-\"$(date +%F).tidal\"}\nSESSION=${SESSION:-\"tidal\"}\n\nTIDAL_BOOT_PATH=${TIDAL_BOOT_PATH:-\"\"}\nGHCI=${GHCI:-\"\"}\n\nargs=${@:-$FILE}\n\n# Check if tmux session \"tidal\" is running, attach only\n# else, create new session, split windows and run processes\n$TMUX -2 attach-session -t $SESSION || $TMUX -2 \\\n  new-session -s $SESSION   \\; \\\n  split-window -v -t $SESSION   \\; \\\n  send-keys -t 0 \"$VIM $args\" C-m   \\; \\\n  send-keys -t 1 \"TIDAL_BOOT_PATH=$TIDAL_BOOT_PATH GHCI=$GHCI tidal\" C-m   \\; \\\n  select-pane -t 0\n"
  },
  {
    "path": "boot.sc",
    "content": "SuperDirt.start;\n"
  },
  {
    "path": "ftdetect/tidal.vim",
    "content": "autocmd BufRead,BufNewFile *.tidal setfiletype tidal\n"
  },
  {
    "path": "ftplugin/tidal.vim",
    "content": "\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Functions\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nlet s:not_prefixable_keywords = [ \"import\", \"data\", \"instance\", \"class\", \"{-#\", \"type\", \"case\", \"do\", \"let\", \"default\", \"foreign\", \"--\"]\n\n\" guess correct number of spaces to indent\n\" (tabs are not allowed)\nfunction! Get_indent_string()\n    return repeat(\" \", 4)\nendfunction\n\n\" replace tabs by spaces\nfunction! Tab_to_spaces(text)\n    return substitute(a:text, \"\t\", Get_indent_string(), \"g\")\nendfunction\n\n\" Wrap in :{ :} if there's more than one line\nfunction! Wrap_if_multi(lines)\n    if len(a:lines) > 1\n        return [\":{\"] + a:lines + [\":}\"]\n    else\n        return a:lines\n    endif\nendfunction\n\n\" change string into array of lines\nfunction! Lines(text)\n    return split(a:text, \"\\n\")\nendfunction\n\n\" change lines back into text\nfunction! Unlines(lines)\n    if g:tidal_target == \"tmux\"\n        \" Without this, the user has to manually submit a newline each time\n        \" they evaluate an expression with `ctrl e`.\n        return join(a:lines, \"\\n\") . \"\\n\"\n    else\n        return join(a:lines, \"\\n\")\n    endif\nendfunction\n\n\" vim slime handler\nfunction! _EscapeText_tidal(text)\n    let l:lines = Lines(Tab_to_spaces(a:text))\n    let l:lines = Wrap_if_multi(l:lines)\n    return Unlines(l:lines)\nendfunction\n\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Mappings\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nif !exists(\"g:tidal_no_mappings\") || !g:tidal_no_mappings\n  if !hasmapto('<Plug>TidalConfig', 'n')\n    nmap <buffer> <localleader>c <Plug>TidalConfig\n  endif\n\n  if !hasmapto('<Plug>TidalRegionSend', 'x')\n    xmap <buffer> <localleader>s  <Plug>TidalRegionSend\n    xmap <buffer> <c-e> <Plug>TidalRegionSend\n  endif\n\n  if !hasmapto('<Plug>TidalLineSend', 'n')\n    nmap <buffer> <localleader>s  <Plug>TidalLineSend\n  endif\n\n  if !hasmapto('<Plug>TidalParagraphSend', 'n')\n    nmap <buffer> <localleader>ss <Plug>TidalParagraphSend\n    nmap <buffer> <c-e> <Plug>TidalParagraphSend\n  endif\n\n  imap <buffer> <c-e> <Esc><Plug>TidalParagraphSend<Esc>i<Right>\n\n  nnoremap <buffer> <localleader>h :TidalHush<cr>\n  nnoremap <buffer> <c-h> :TidalHush<cr>\n  let i = 1\n  while i <= 9\n    execute 'nnoremap <buffer> <localleader>'.i.'  :TidalSilence '.i.'<cr>'\n    execute 'nnoremap <buffer> <c-'.i.'>  :TidalSilence '.i.'<cr>'\n    execute 'nnoremap <buffer> <localleader>s'.i.' :TidalPlay '.i.'<cr>'\n    let i += 1\n  endwhile\nendif\n"
  },
  {
    "path": "plugin/tidal.vim",
    "content": "if exists(\"g:loaded_tidal\") || &cp || v:version < 700\n  finish\nendif\nlet g:loaded_tidal = 1\nlet s:parent_path = fnamemodify(expand(\"<sfile>\"), \":p:h:s?/plugin??\")\n\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Default config\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n\" Attempts to find a tidal boot file in this or any parent directory.\nfunction s:FindTidalBoot()\n  for name in [\"BootTidal.hs\", \"Tidal.ghci\", \"boot.tidal\"]\n    let tidal_boot_file = findfile(name, \".\".';')\n    if !empty(tidal_boot_file)\n      return tidal_boot_file\n    endif\n  endfor\nendfunction\n\n\" Attempts to find a supercollider startup file in this or any parent dir.\nfunction s:FindScBoot()\n  for name in [\"boot.sc\", \"boot.scd\"]\n    let sc_boot_file = findfile(name, \".\".';')\n    if !empty(sc_boot_file)\n      return sc_boot_file\n    endif\n  endfor\nendfunction\n\nif !exists(\"g:tidal_target\")\n  if has('nvim') || has('terminal')\n    let g:tidal_target = \"terminal\"\n  else\n    let g:tidal_target = \"tmux\"\n  endif\nendif\n\nif !exists(\"g:tidal_paste_file\")\n  let g:tidal_paste_file = tempname()\nendif\n\nif !exists(\"g:tidal_default_config\")\n  let g:tidal_default_config = { \"socket_name\": \"default\", \"target_pane\": \":0.1\" }\nendif\n\nif !exists(\"g:tidal_preserve_curpos\")\n  let g:tidal_preserve_curpos = 1\nendif\n\nif !exists(\"g:tidal_flash_duration\")\n  let g:tidal_flash_duration = 150\nendif\n\nif !exists(\"g:tidal_ghci\")\n  let g:tidal_ghci = \"ghci\"\nendif\n\nif !exists(\"g:tidal_boot_fallback\")\n  let g:tidal_boot_fallback = s:parent_path . \"/Tidal.ghci\"\nendif\n\nif !exists(\"g:tidal_boot\")\n  let g:tidal_boot = s:FindTidalBoot()\n  if empty(g:tidal_boot)\n    let g:tidal_boot = g:tidal_boot_fallback\n  endif\nendif\n\nif !exists(\"g:tidal_superdirt_enable\")\n  \" Allow vim-tidal to automatically start SuperDirt. Disabled by default.\n  let g:tidal_superdirt_enable = 0\nendif\n\nif !exists(\"g:tidal_sclang\")\n  let g:tidal_sclang = \"sclang\"\nendif\n\n\" Allow vim-tidal to automatically start supercollider. Disabled by default.\nif !exists(\"g:tidal_sc_enable\")\n  let g:tidal_sc_enable = 0\nendif\n\nif !exists(\"g:tidal_sc_boot_fallback\")\n  let g:tidal_sc_boot_fallback = s:parent_path . \"/boot.sc\"\nendif\n\nif !exists(\"g:tidal_sc_boot\")\n  let g:tidal_sc_boot = s:FindScBoot()\n  if empty(g:tidal_sc_boot)\n    let g:tidal_sc_boot = g:tidal_sc_boot_fallback\n  endif\nendif\n\nif !exists(\"g:tidal_sc_boot_cmd\")\n  \" A command that can be run from the terminal to start supercollider.\n  \" The default assumes `SuperDirt` is installed.\n  let g:tidal_sc_boot_cmd = g:tidal_sclang . \" \" . g:tidal_sc_boot\nendif\n\nif filereadable(s:parent_path . \"/.dirt-samples\")\n  let &l:dictionary .= ',' . s:parent_path . \"/.dirt-samples\"\nendif\n\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Tmux\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nfunction! s:TmuxSend(config, text)\n  let l:prefix = \"tmux -L \" . shellescape(a:config[\"socket_name\"])\n  \" use STDIN unless configured to use a file\n  if !exists(\"g:tidal_paste_file\")\n    call system(l:prefix . \" load-buffer -\", a:text)\n  else\n    call s:WritePasteFile(a:text)\n    call system(l:prefix . \" load-buffer \" . g:tidal_paste_file)\n  end\n  call system(l:prefix . \" paste-buffer -d -t \" . shellescape(a:config[\"target_pane\"]))\nendfunction\n\nfunction! s:TmuxPaneNames(A,L,P)\n  let format = '#{pane_id} #{session_name}:#{window_index}.#{pane_index} #{window_name}#{?window_active, (active),}'\n  return system(\"tmux -L \" . shellescape(b:tidal_config['socket_name']) . \" list-panes -a -F \" . shellescape(format))\nendfunction\n\nfunction! s:TmuxConfig() abort\n  if !exists(\"b:tidal_config\")\n    let b:tidal_config = {\"socket_name\": \"default\", \"target_pane\": \":\"}\n  end\n\n  let b:tidal_config[\"socket_name\"] = input(\"tmux socket name: \", b:tidal_config[\"socket_name\"])\n  let b:tidal_config[\"target_pane\"] = input(\"tmux target pane: \", b:tidal_config[\"target_pane\"], \"custom,<SNR>\" . s:SID() . \"_TmuxPaneNames\")\n  if b:tidal_config[\"target_pane\"] =~ '\\s\\+'\n    let b:tidal_config[\"target_pane\"] = split(b:tidal_config[\"target_pane\"])[0]\n  endif\nendfunction\n\n\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Terminal\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nlet s:tidal_term_ghci = -1\nlet s:tidal_term_sc = -1\n\n\" NVim and VIM8 Terminal Implementation\n\" =====================================\nfunction! s:TerminalOpen()\n  if has('nvim')\n    let current_win = winnr()\n\n    if s:tidal_term_ghci == -1\n        \" force terminal split to open below current pane\n        :exe \"set splitbelow\"\n        execute \"split term://\" . g:tidal_ghci . \" -ghci-script=\" . g:tidal_boot\n        let s:tidal_term_ghci = b:terminal_job_id\n\n        \" Give tidal a moment to start up so following commands can take effect\n        sleep 500m\n\n        \" Make terminal scroll to follow output\n        :exe \"normal G\"\n        :exe \"normal 10\\<c-w>_\"\n    endif\n\n    if g:tidal_sc_enable == 1 && s:tidal_term_sc == -1\n        execute \"vsplit term://\" . g:tidal_sc_boot_cmd\n        let s:tidal_term_sc = b:terminal_job_id\n\n        \" Make terminal scroll to follow output\n        :exe \"normal G\"\n    endif\n\n    execute current_win .. \"wincmd w\"\n  elseif has('terminal')\n    \" Keep track of the current window number so we can switch back.\n    let current_win = winnr()\n\n    \" Open a Terminal with GHCI with tidal booted.\n    if s:tidal_term_ghci == -1\n      execute \"below split\"\n      let s:tidal_term_ghci = term_start((g:tidal_ghci . \" -ghci-script=\" . g:tidal_boot), #{\n            \\ term_name: 'tidal',\n            \\ term_rows: 10,\n            \\ norestore: 1,\n            \\ curwin: 1,\n            \\ })\n    endif\n\n    \" Open a terminal with supercollider running.\n    if g:tidal_sc_enable == 1 && s:tidal_term_sc == -1\n      execute \"vert split\"\n      let s:tidal_term_sc = term_start(g:tidal_sc_boot_cmd, #{\n           \\ term_name: 'supercollider',\n           \\ term_rows: 10,\n           \\ norestore: 1,\n           \\ curwin: 1,\n           \\ })\n    endif\n\n    \" Return focus to the original window.\n    execute current_win .. \"wincmd w\"\n  endif\nendfunction\n\nfunction! s:TerminalSend(config, text)\n  call s:TerminalOpen()\n  if has('nvim')\n    call jobsend(s:tidal_term_ghci, a:text . \"\\<CR>\")\n  elseif has('terminal')\n    call term_sendkeys(s:tidal_term_ghci, a:text . \"\\<CR>\")\n  endif\nendfunction\n\n\" These two are unnecessary AFAIK.\nfunction! s:TerminalPaneNames(A,L,P)\nendfunction\nfunction! s:TerminalConfig() abort\nendfunction\n\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Helpers\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nfunction! s:SID()\n  return matchstr(expand('<sfile>'), '<SNR>\\zs\\d\\+\\ze_SID$')\nendfun\n\nfunction! s:WritePasteFile(text)\n  \" could check exists(\"*writefile\")\n  call system(\"cat > \" . g:tidal_paste_file, a:text)\nendfunction\n\nfunction! s:_EscapeText(text)\n  if exists(\"&filetype\")\n    let custom_escape = \"_EscapeText_\" . substitute(&filetype, \"[.]\", \"_\", \"g\")\n    if exists(\"*\" . custom_escape)\n      let result = call(custom_escape, [a:text])\n    end\n  end\n\n  \" use a:text if the ftplugin didn't kick in\n  if !exists(\"result\")\n    let result = a:text\n  end\n\n  \" return an array, regardless\n  if type(result) == type(\"\")\n    return [result]\n  else\n    return result\n  end\nendfunction\n\nfunction! s:TidalGetConfig()\n  if !exists(\"b:tidal_config\")\n    if exists(\"g:tidal_default_config\")\n      let b:tidal_config = g:tidal_default_config\n    else\n      call s:TidalDispatch('Config')\n    end\n  end\nendfunction\n\nfunction! s:TidalFlashVisualSelection()\n  \" Redraw to show current visual selection, and sleep\n  redraw\n  execute \"sleep \" . g:tidal_flash_duration . \" m\"\n  \" Then leave visual mode\n  silent exe \"normal! vv\"\nendfunction\n\nfunction! s:TidalSendOp(type, ...) abort\n  call s:TidalGetConfig()\n\n  let sel_save = &selection\n  let &selection = \"inclusive\"\n  let rv = getreg('\"')\n  let rt = getregtype('\"')\n\n  if a:0  \" Invoked from Visual mode, use '< and '> marks.\n    silent exe \"normal! `<\" . a:type . '`>y'\n  elseif a:type == 'line'\n    silent exe \"normal! '[V']y\"\n  elseif a:type == 'block'\n    silent exe \"normal! `[\\<C-V>`]\\y\"\n  else\n    silent exe \"normal! `[v`]y\"\n  endif\n\n  call setreg('\"', @\", 'V')\n  call s:TidalSend(@\")\n\n  \" Flash selection\n  if a:type == 'line'\n    silent exe \"normal! '[V']\"\n    call s:TidalFlashVisualSelection()\n  endif\n\n  let &selection = sel_save\n  call setreg('\"', rv, rt)\n\n  call s:TidalRestoreCurPos()\nendfunction\n\nfunction! s:TidalSendRange() range abort\n  call s:TidalGetConfig()\n\n  let rv = getreg('\"')\n  let rt = getregtype('\"')\n  silent execute a:firstline . ',' . a:lastline . 'yank'\n  call s:TidalSend(@\")\n  call setreg('\"', rv, rt)\nendfunction\n\nfunction! s:TidalSendLines(count) abort\n  call s:TidalGetConfig()\n\n  let rv = getreg('\"')\n  let rt = getregtype('\"')\n\n  silent execute \"normal! \" . a:count . \"yy\"\n\n  call s:TidalSend(@\")\n  call setreg('\"', rv, rt)\n\n  \" Flash lines\n  silent execute \"normal! V\"\n  if a:count > 1\n    silent execute \"normal! \" . (a:count - 1) . \"\\<Down>\"\n  endif\n  call s:TidalFlashVisualSelection()\nendfunction\n\nfunction! s:TidalStoreCurPos()\n  if g:tidal_preserve_curpos == 1\n    if exists(\"*getcurpos\")\n      let s:cur = getcurpos()\n    else\n      let s:cur = getpos('.')\n    endif\n  endif\nendfunction\n\nfunction! s:TidalRestoreCurPos()\n  if g:tidal_preserve_curpos == 1\n    call setpos('.', s:cur)\n  endif\nendfunction\n\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Public interface\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nfunction! s:TidalSend(text)\n  call s:TidalGetConfig()\n\n  let pieces = s:_EscapeText(a:text)\n  for piece in pieces\n    call s:TidalDispatch('Send', b:tidal_config, piece)\n  endfor\nendfunction\n\nfunction! s:TidalConfig() abort\n  call inputsave()\n  call s:TidalDispatch('Config')\n  call inputrestore()\nendfunction\n\n\" delegation\nfunction! s:TidalDispatch(name, ...)\n  let target = substitute(tolower(g:tidal_target), '\\(.\\)', '\\u\\1', '') \" Capitalize\n  return call(\"s:\" . target . a:name, a:000)\nendfunction\n\nfunction! s:TidalHush()\n  execute 'TidalSend1 hush'\nendfunction\n\nfunction! s:TidalSilence(stream)\n  silent execute 'TidalSend1 d' . a:stream . ' silence'\nendfunction\n\nfunction! s:TidalPlay(stream)\n  let res = search('^\\s*d' . a:stream)\n  if res > 0\n    silent execute \"normal! vip:TidalSend\\<cr>\"\n    silent execute \"normal! vip\"\n    call s:TidalFlashVisualSelection()\n  else\n    echo \"d\" . a:stream . \" was not found\"\n  endif\nendfunction\n\nfunction! s:TidalGenerateCompletions(path)\n  let l:exe = s:parent_path . \"/bin/generate-completions\"\n  let l:output_path = s:parent_path . \"/.dirt-samples\"\n\n  if !empty(a:path)\n    let l:sample_path = a:path\n  else\n    if has('macunix')\n      let l:sample_path = \"~/Library/Application Support/SuperCollider/downloaded-quarks/Dirt-Samples\"\n    elseif has('unix')\n      let l:sample_path = \"~/.local/share/SuperCollider/downloaded-quarks/Dirt-Samples\"\n    endif\n  endif\n  \" generate completion file\n  silent execute '!' . l:exe shellescape(expand(l:sample_path)) shellescape(expand(l:output_path))\n  echo \"Generated dictionary of dirt-samples\"\n  \" setup completion\n  let &l:dictionary .= ',' . l:output_path\nendfunction\n\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Setup key bindings\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\ncommand -bar -nargs=0 TidalConfig call s:TidalConfig()\ncommand -range -bar -nargs=0 TidalSend <line1>,<line2>call s:TidalSendRange()\ncommand -nargs=+ TidalSend1 call s:TidalSend(<q-args>)\n\ncommand! -nargs=0 TidalHush call s:TidalHush()\ncommand! -nargs=1 TidalSilence call s:TidalSilence(<args>)\ncommand! -nargs=1 TidalPlay call s:TidalPlay(<args>)\ncommand! -nargs=? TidalGenerateCompletions call s:TidalGenerateCompletions(<q-args>)\n\nnoremap <SID>Operator :<c-u>call <SID>TidalStoreCurPos()<cr>:set opfunc=<SID>TidalSendOp<cr>g@\n\nnoremap <unique> <script> <silent> <Plug>TidalRegionSend :<c-u>call <SID>TidalSendOp(visualmode(), 1)<cr>\nnoremap <unique> <script> <silent> <Plug>TidalLineSend :<c-u>call <SID>TidalSendLines(v:count1)<cr>\nnoremap <unique> <script> <silent> <Plug>TidalMotionSend <SID>Operator\nnoremap <unique> <script> <silent> <Plug>TidalParagraphSend <SID>Operatorip\nnoremap <unique> <script> <silent> <Plug>TidalConfig :<c-u>TidalConfig<cr>\n"
  },
  {
    "path": "syntax/tidal.vim",
    "content": "\" syntax highlighting for tidal/haskell\n\"\n\" Very minor modifications from syntax file of\n\" https://github.com/neovimhaskell/haskell-vim\n\"\n\" Heavily modified version of the haskell syntax\n\" highlighter to support haskell.\n\"\n\" author: raichoo (raichoo@googlemail.com)\n\nif version < 600\n  syn clear\nelseif exists(\"b:current_syntax\")\n  finish\nendif\n\nif get(g:, 'haskell_backpack', 0)\n  syn keyword haskellBackpackStructure unit signature\n  syn keyword haskellBackpackDependency dependency\nendif\n\nsyn spell notoplevel\nsyn match haskellRecordField contained containedin=haskellBlock\n  \\ \"[_a-z][a-zA-Z0-9_']*\\(,\\s*[_a-z][a-zA-Z0-9_']*\\)*\\_s\\+::\\_s\"\n  \\ contains=\n  \\ haskellIdentifier,\n  \\ haskellOperators,\n  \\ haskellSeparator,\n  \\ haskellParens\nsyn match haskellTypeSig\n  \\ \"^\\s*\\(where\\s\\+\\|let\\s\\+\\|default\\s\\+\\)\\?[_a-z][a-zA-Z0-9_']*#\\?\\(,\\s*[_a-z][a-zA-Z0-9_']*#\\?\\)*\\_s\\+::\\_s\"\n  \\ contains=\n  \\ haskellWhere,\n  \\ haskellLet,\n  \\ haskellDefault,\n  \\ haskellIdentifier,\n  \\ haskellOperators,\n  \\ haskellSeparator,\n  \\ haskellParens\nsyn keyword haskellWhere where\nsyn keyword haskellLet let\nsyn match HaskellDerive \"\\<deriving\\>\\(\\s\\+\\<\\(anyclass\\|instance\\|newtype\\|stock\\)\\>\\)\\?\"\nsyn keyword haskellDeclKeyword module class instance newtype in\nsyn match haskellDecl \"\\<\\(type\\|data\\)\\>\\s\\+\\(\\<family\\>\\)\\?\"\nsyn keyword haskellDefault default\nsyn keyword haskellImportKeywords import qualified safe as hiding contained\nsyn keyword haskellForeignKeywords foreign export import ccall safe unsafe interruptible capi prim contained\nsyn region haskellForeignImport start=\"\\<foreign\\>\" end=\"\\_s\\+::\\s\" keepend\n  \\ contains=\n  \\ haskellString,\n  \\ haskellOperators,\n  \\ haskellForeignKeywords,\n  \\ haskellIdentifier\nsyn match haskellImport \"^\\s*\\<import\\>\\s\\+\\(\\<safe\\>\\s\\+\\)\\?\\(\\<qualified\\>\\s\\+\\)\\?.\\+\\(\\s\\+\\<as\\>\\s\\+.\\+\\)\\?\\(\\s\\+\\<hiding\\>\\)\\?\"\n  \\ contains=\n  \\ haskellParens,\n  \\ haskellOperators,\n  \\ haskellImportKeywords,\n  \\ haskellType,\n  \\ haskellLineComment,\n  \\ haskellBlockComment,\n  \\ haskellString,\n  \\ haskellPragma\nsyn keyword haskellKeyword do case of\nif get(g:, 'haskell_enable_static_pointers', 0)\n  syn keyword haskellStatic static\nendif\nsyn keyword haskellConditional if then else\nsyn match haskellNumber \"\\<[0-9]\\+\\>\\|\\<0[xX][0-9a-fA-F]\\+\\>\\|\\<0[oO][0-7]\\+\\>\\|\\<0[bB][10]\\+\\>\"\nsyn match haskellFloat \"\\<[0-9]\\+\\.[0-9]\\+\\([eE][-+]\\=[0-9]\\+\\)\\=\\>\"\nsyn match haskellSeparator  \"[,;]\"\nsyn region haskellParens matchgroup=haskellDelimiter start=\"(\" end=\")\" contains=TOP,haskellTypeSig,@Spell\nsyn region haskellBrackets matchgroup=haskellDelimiter start=\"\\[\" end=\"]\" contains=TOP,haskellTypeSig,@Spell\nsyn region haskellBlock matchgroup=haskellDelimiter start=\"{\" end=\"}\" contains=TOP,@Spell\nsyn keyword haskellInfix infix infixl infixr\nsyn keyword haskellBottom undefined error\nsyn match haskellOperators \"[-!#$%&\\*\\+/<=>\\?@\\\\^|~:.]\\+\\|\\<_\\>\"\nsyn match haskellQuote \"\\<'\\+\" contained\nsyn match haskellQuotedType \"[A-Z][a-zA-Z0-9_']*\\>\" contained\nsyn region haskellQuoted start=\"\\<'\\+\" end=\"\\>\"\n  \\ contains=\n  \\ haskellType,\n  \\ haskellQuote,\n  \\ haskellQuotedType,\n  \\ haskellSeparator,\n  \\ haskellParens,\n  \\ haskellOperators,\n  \\ haskellIdentifier\nsyn match haskellLineComment \"---*\\([^-!#$%&\\*\\+./<=>\\?@\\\\^|~].*\\)\\?$\"\n  \\ contains=\n  \\ haskellTodo,\n  \\ @Spell\nsyn match haskellBacktick \"`[A-Za-z_][A-Za-z0-9_\\.']*#\\?`\"\nsyn region haskellString start=+\"+ skip=+\\\\\\\\\\|\\\\\"+ end=+\"+\n  \\ contains=@Spell\nsyn match haskellIdentifier \"[_a-z][a-zA-z0-9_']*\" contained\nsyn match haskellChar \"\\<'[^'\\\\]'\\|'\\\\.'\\|'\\\\u[0-9a-fA-F]\\{4}'\\>\"\nsyn match haskellType \"\\<[A-Z][a-zA-Z0-9_']*\\>\"\nsyn region haskellBlockComment start=\"{-\" end=\"-}\"\n  \\ contains=\n  \\ haskellBlockComment,\n  \\ haskellTodo,\n  \\ @Spell\nsyn region haskellPragma start=\"{-#\" end=\"#-}\"\nsyn region haskellLiquid start=\"{-@\" end=\"@-}\"\n\"syn match haskellPreProc \"^#.*$\"\nsyn keyword haskellTodo TODO FIXME contained\n\" Treat a shebang line at the start of the file as a comment\nsyn match haskellShebang \"\\%^#!.*$\"\nif !get(g:, 'haskell_disable_TH', 0)\n    syn match haskellQuasiQuoted \".\" containedin=haskellQuasiQuote contained\n    syn region haskellQuasiQuote matchgroup=haskellTH start=\"\\[[_a-zA-Z][a-zA-z0-9._']*|\" end=\"|\\]\"\n    syn region haskellTHBlock matchgroup=haskellTH start=\"\\[\\(d\\|t\\|p\\)\\?|\" end=\"|]\" contains=TOP\n    syn region haskellTHDoubleBlock matchgroup=haskellTH start=\"\\[||\" end=\"||]\" contains=TOP\nendif\nif get(g:, 'haskell_enable_typeroles', 0)\n  syn keyword haskellTypeRoles phantom representational nominal contained\n  syn region haskellTypeRoleBlock matchgroup=haskellTypeRoles start=\"type\\s\\+role\" end=\"$\" keepend\n    \\ contains=\n    \\ haskellType,\n    \\ haskellTypeRoles\nendif\nif get(g:, 'haskell_enable_quantification', 0)\n  syn keyword haskellForall forall\nendif\nif get(g:, 'haskell_enable_recursivedo', 0)\n  syn keyword haskellRecursiveDo mdo rec\nendif\nif get(g:, 'haskell_enable_arrowsyntax', 0)\n  syn keyword haskellArrowSyntax proc\nendif\nif get(g:, 'haskell_enable_pattern_synonyms', 0)\n  syn keyword haskellPatternKeyword pattern\nendif\n\nhighlight def link haskellBottom Macro\nhighlight def link haskellTH Boolean\nhighlight def link haskellIdentifier Identifier\nhighlight def link haskellForeignKeywords Structure\nhighlight def link haskellKeyword Keyword\nhighlight def link haskellDefault Keyword\nhighlight def link haskellConditional Conditional\nhighlight def link haskellNumber Number\nhighlight def link haskellFloat Float\nhighlight def link haskellSeparator Delimiter\nhighlight def link haskellDelimiter Delimiter\nhighlight def link haskellInfix Keyword\nhighlight def link haskellOperators Operator\nhighlight def link haskellQuote Operator\nhighlight def link haskellShebang Comment\nhighlight def link haskellLineComment Comment\nhighlight def link haskellBlockComment Comment\nhighlight def link haskellPragma SpecialComment\nhighlight def link haskellLiquid SpecialComment\nhighlight def link haskellString String\nhighlight def link haskellChar String\nhighlight def link haskellBacktick Operator\nhighlight def link haskellQuasiQuoted String\nhighlight def link haskellTodo Todo\n\"highlight def link haskellPreProc PreProc\nhighlight def link haskellAssocType Type\nhighlight def link haskellQuotedType Type\nhighlight def link haskellType Type\nhighlight def link haskellImportKeywords Include\nif get(g:, 'haskell_classic_highlighting', 0)\n  highlight def link haskellDeclKeyword Keyword\n  highlight def link HaskellDerive Keyword\n  highlight def link haskellDecl Keyword\n  highlight def link haskellWhere Keyword\n  highlight def link haskellLet Keyword\nelse\n  highlight def link haskellDeclKeyword Structure\n  highlight def link HaskellDerive Structure\n  highlight def link haskellDecl Structure\n  highlight def link haskellWhere Structure\n  highlight def link haskellLet Structure\nendif\n\nif get(g:, 'haskell_enable_quantification', 0)\n  highlight def link haskellForall Operator\nendif\nif get(g:, 'haskell_enable_recursivedo', 0)\n  highlight def link haskellRecursiveDo Keyword\nendif\nif get(g:, 'haskell_enable_arrowsyntax', 0)\n  highlight def link haskellArrowSyntax Keyword\nendif\nif get(g:, 'haskell_enable_static_pointers', 0)\n  highlight def link haskellStatic Keyword\nendif\nif get(g:, 'haskell_classic_highlighting', 0)\n  if get(g:, 'haskell_enable_pattern_synonyms', 0)\n    highlight def link haskellPatternKeyword Keyword\n  endif\n  if get(g:, 'haskell_enable_typeroles', 0)\n    highlight def link haskellTypeRoles Keyword\n  endif\nelse\n  if get(g:, 'haskell_enable_pattern_synonyms', 0)\n    highlight def link haskellPatternKeyword Structure\n  endif\n  if get(g:, 'haskell_enable_typeroles', 0)\n    highlight def link haskellTypeRoles Structure\n  endif\nendif\n\nif get(g:, 'haskell_backpack', 0)\n  highlight def link haskellBackpackStructure Structure\n  highlight def link haskellBackpackDependency Include\nendif\n\nlet b:current_syntax = \"tidal\"\n"
  }
]