Repository: tidalcycles/vim-tidal
Branch: master
Commit: e440fe5bdfe0
Files: 16
Total size: 49.1 KB
Directory structure:
gitextract_odl0_omb/
├── .gitignore
├── CHANGELOG
├── CODE_OF_CONDUCT.md
├── LICENSE
├── Makefile
├── README.md
├── Tidal.ghci
├── bin/
│ ├── generate-completions
│ ├── tidal
│ ├── tidal.bat
│ └── tidalvim
├── boot.sc
├── ftdetect/
│ └── tidal.vim
├── ftplugin/
│ └── tidal.vim
├── plugin/
│ └── tidal.vim
└── syntax/
└── tidal.vim
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.dirt-samples
================================================
FILE: CHANGELOG
================================================
0.3.3
* Fix syntax highlighting issues with the `#` operator
0.3.2
* Update README
0.3.1
* Add <c-e> mapping for sending paragraphs, on Normal, Visual and Insert modes
* Flash text selection when sending text
* Force tmux to use 256 colors on tidalvim
* Add <c-h> maping as an alternative to <localleader>h
* Try to use getcurpos() if available when restoring cursor position
0.3.0
* Update bootstrap script for Tidal 0.9
* `tidalvim` now only creates 2 panes for Vim and GHCi
* Split `tidalvim` script in two scripts: `tidal` and `tidalvim`
* Better instructions for customizing Tidal bootstrap script
0.2.0
* Remove vim-slime dependency
* Preserve cursor position when sending to tmux
* Configure tmux automatically with defaults
0.1.0
* Use Slime to communicate via tmux
* Create "tidalvim" script for creating Dirt and Tidal instances
* Define more vim-like default bindings
* Add bindings to silence channels
* Add bindings for playing first occurrence of stream
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at munshkr@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 Damián Emiliano Silvani
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
mkfile_path := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
prefix=/usr/local
install:
ln -fs $(mkfile_path)/bin/tidal $(prefix)/bin
ln -fs $(mkfile_path)/bin/tidalvim $(prefix)/bin
uninstall:
rm -f $(prefix)/bin/tidal $(prefix)/bin/tidalvim
.PHONY: install uninstall
================================================
FILE: README.md
================================================
# vim-tidal #
A Vim/NeoVim plugin for [TidalCycles](http://tidalcycles.org), the language for
live coding musical patterns written in Haskell.
This plugin by default uses [tmux](https://tmux.github.io/), a known and loved
terminal multiplexer, for communicating with between Vim and the Tidal
interpreter. It was originally based on
[vim-slime](https://github.com/jpalardy/vim-slime).

If you are using Vim8 or NeoVim, you can use the native Terminal feature instead
of tmux. Read the Configuration section on how to enable it.
[](https://asciinema.org/a/224891)
## Getting Started ##
1. Start livecoding with Vim by simply running:
```bash
$ tidalvim
```
This creates a tmux session with Vim and Tidal running on different panes.
2. Write something like this:
```haskell
d1 $ sound "bd sn"
```
3. While being on that line, press `<c-e>` (Control + E) to evaluate it.
You should see Vim flash that line for a second and a chunk of text appear on
your Tidal interpreter. If you already have SuperDirt or other synth running,
you should hear a kick and a snare :)
## Install ##
Make sure you have TidalCycles installed, with SuperDirt running. See [the Tidal wiki](https://tidalcycles.org/index.php/Userbase) for more information.
### Install tmux ###
#### Ubuntu/Debian ####
You can install it from the main repos:
$ sudo apt-get install tmux
#### OSX ####
$ brew install tmux
#### Windows ####
There seems to be [a Cygwin package for
tmux](https://cygwin.com/cgi-bin2/package-cat.cgi?file=x86%2Ftmux%2Ftmux-1.9a-1&grep=tmux),
but 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).
### Install plugin ###
I recommend using a Vim plugin manager like
[Plug](https://github.com/junegunn/vim-plug). Check the link for instructions
on installing and configuring. If you don't want a plugin manager, you can
also download the latest release
[here](https://github.com/tidalcycles/vim-tidal/releases) and extract the
contents on your Vim directory (usually `~/.vim/`).
For example, with Plug you need to:
* Edit your `.vimrc` file and add these lines:
```vim
Plug 'tidalcycles/vim-tidal'
```
* Restart Vim and execute `:PlugInstall` to automatically download and
install the plugins.
#### UNIX-based Systems ####
If you are on a UNIX-based operating system (Linux distributions, MacOS, etc.), go to the plugin repository and run `make install`:
(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)
$ cd ~/.vim/plugged/vim-tidal
$ sudo make install
This creates symlinks on `/usr/local/bin` for `tidal` and `tidalvim` scripts.
You can remove them later if you want with `make uninstall`.
#### Windows ####
:warning: **This plugin has only been tested on Windows 10 using Neovim >0.5**
If you are on Windows, add the `vim-tidal\bin` directory to your `PATH` user environment variable:
1. Click the `Start` button
2. Type "Edit the system environment variables" and hit `enter` or click on the search result
3. Click the button labeled `Environment variables...`
4. In the `User variables for [username]` table, click the entry for the `Path` variable, followed by the `Edit...` button beneath the same table
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.
Note: 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.
#### Final Installation Note ####
Make sure to have the `filetype plugin on` setting on your .vimrc, otherwise
plugin won't be loaded when opening a .tidal file.
### Older Tidal versions (pre 1.0) ###
Tidal 1.0 introduces some breaking changes, so if haven't upgraded yet, you can
still use this plugin with an older version. Just point your Plug entry to use
the `tidal-0.9` branch.
First change your Plug line on your `.vimrc` to:
```vim
Plug 'tidalcycles/vim-tidal', {'branch': 'tidal-0.9'}
```
Then on Vim run `:PlugInstall` to update your plugin.
## Usage
This plugin comes bundled with two Bash scripts: `tidalvim` and `tidal`.
### `tidalvim`
`tidalvim` starts a tmux session with the screen horizontally splitted, having
Vim on the upper pane and the Tidal interpreter on the lower pane. This is the
simplest way to start using Tidal with Vim.
You don't have to use `tidalvim` necessarily. If you have a more complex setup
or just want to use Vim outside of tmux, you can use `tidal`. See below.
### `tidal`
`tidal` fires up GHCi (the Glasgow Haskell interpreter) and runs a bootstrap
file that loads Tidal up. `tidalvim` uses this script to start the Tidal
interpreter on the lower pane. You can even use it standalone (without Vim) by
simply running `tidal` from your shell.
```haskell
$ tidal
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
tidal> d1 $ sound "bd sn"
tidal> :t density 2 $ n "0 1"
density 2 $ n "0 1" :: Pattern ParamMap
```
So, in case you don't want to use `tidalvim`, just run the following on another
terminal:
```bash
tmux new-session -s tidal tidal
```
What `tidal` does is actually run `ghci` with the argument `-ghci-script
Tidal.ghci`. [Tidal.ghci](Tidal.ghci) is found at the root of the repository,
and is responsible for bootstraping Tidal. See Configure section for more on
how to customize Tidal bootstraping process. Any extra arguments when running
`tidal` will be delegated to `ghci`.
### Commands
These are some of the commands that can be run from Vim command line:
* `:<range>TidalSend`: Send a `[range]` of lines. If no range is provided the
current line is sent.
* `:TidalSend1 {text}`: Send a single line of text specified on the command
line.
* `:TidalConfig`: Configure tmux socket name and target pane
* `:TidalSilence [num]`: Silence stream number `[num]` by sending `d[num]
silence`.
* `:TidalPlay [num]`: Send first ocurrence of stream number `[num`] from the
current cursor position.
* `:TidalHush`: Silences all streams by sending `hush`.
* `:TidalGenerateCompletions {path}`: Generate dictionary for Dirt-Samples
completion (path is optional).
### Default bindings
Using one of these key bindings you can send lines to Tidal:
* `<c-e>` (Control+E), `<localleader>ss`: Send current inner paragraph.
* `<localleader>s`: Send current line or current visually selected block.
`<c-e>` can be called on either Normal, Visual, Select or Insert mode, so it is
probably easier to type than `<localleader>ss` or `<localleader>s`.
There are other bindings to control Tidal like:
* `<localleader>s[num]`: Call `:TidalPlay [num]`
* `<localleader>[num]`: Call `:TidalSilence [num]`
* `<localleader>h`, `<c-h>`: Call `:TidalHush`
#### About `<localleader>`
The `<leader>` key is a special key used to perform commands with a sequence of
keys. The `<localleader>` key behaves as the `<leader>` key, but is *local* to
a buffer. In particular, the above bindings only work in buffers with the
"tidal" file type set, e.g. files whose file type is `.tidal`
By default, there is no `<localleader>` set. To define one, e.g. for use with
a comma (`,`), write this on your `.vimrc` file:
```vim
let maplocalleader=","
```
Reload your configuration (or restart Vim), and after typing `,ss` on a few
lines of code, you should see those being copied onto the Tidal interpreter on
the lower pane.
## Configure ##
### GHCI
By default, `vim-tidal` uses the globally installed GHCI to launch the REPL.
If you have installed Tidal through Stack (`stack install tidal`) or some other
means, you can specify another command to use with `g:tidal_ghci`.
For example, if one installed Tidal with Stack, they would use:
```vim
let g:tidal_ghci = "stack exec ghci --"
```
### Tidal Boot File
A "Tidal boot file" is a file that may be used to initialise Tidal within GHCI.
A custom boot file can be specified using the `g:tidal_boot` variable.
In the case that `g:tidal_boot` is unspecified, vim-tidal will traverse parent
directories until one of either `BootTidal.hs`, `Tidal.ghci` or `boot.tidal` are
found.
If no tidal boot file can be found by traversing parent directories, tidal will
check the `g:tidal_boot_fallback` variable for a fallback boot file. This
variable is useful for specifying a default user-wide tidal boot file on your
system, while still allowing each tidal project to optionally use their own
dedicated, local tidal boot file. By default, `g:tidal_boot_fallback` will point
to the `Tidal.ghci` file provided with this plugin.
### Default bindings ###
By default, there are two normal keybindings and one for visual blocks using
your `<localleader>` key. If you don't have one defined, set it on your
`.vimrc` script with `let maplocalleader=","`, for example.
If you don't like some of the bindings or want to change them, add this line to
disable them:
```vim
let g:tidal_no_mappings = 1
```
See section Mappings on [ftplugin/tidal.vim](ftplugin/tidal.vim) and copy the
bindings you like to your `.vimrc` file and modify them.
### Vim Terminal
On both Vim (version 8 or above) and NeoVim, the default target in which we boot
Tidal with GHCi is the native terminal.
While it is the default, it can also be specified manually with the following:
```vim
let g:tidal_target = "terminal"
```
Open a file with a `.tidal` suffix, write and send a line of code to tidal, and
the tidal terminal will open in a window below your editor.
Use standard vim window navigation controls to focus the terminal (ie `<C-w> down/up`)
You can learn more about the native Vim terminal here:
https://vimhelp.org/terminal.txt.html
### tmux (alternative to Vim terminal)
Before Vim had native terminal support, this plugin provided a "tmux" target in
order to allow for multiplexing the user's terminal via the 3rd party CLI tool.
If you have `tmux` installed and you wish to use it instead of the native Vim
terminal, you can enable this target with the following:
```vim
let g:tidal_target = "tmux"
```
This target will be enabled automatically in the case that the version of Vim in
use does not have native terminal support.
You can configure tmux socket name and target pane by typing `<localleader>c`
or `:TidalConfig`. This will prompt you first for the socket name, then for
the target pane.
About the target pane:
* `":"` means current window, current pane (a reasonable default)
* `":i"` means the ith window, current pane
* `":i.j"` means the ith window, jth pane
* `"h:i.j"` means the tmux session where h is the session identifier (either
session name or number), the ith window and the jth pane
When you exit Vim you will lose that configuration. To make this permanent, set
`g:tidal_default_config` on your `.vimrc`. For example, suppose you want to run
Tidal on a tmux session named `omg`, and the GHCi interpreter will be running
on the window 1 and pane 0. In that case you would need to add this line:
```vim
let g:tidal_default_config = {"socket_name": "default", "target_pane": "omg:1.0"}
```
### Optional Supercollider Terminal
Vim-tidal provides an option for automatically running the supercollider
command-line tool `sclang` alongside the Tidal GCHI terminal. By default this
terminal is disabled, however it can be enabled with the following:
```vim
let g:tidal_sc_enable = 1
```
This can be useful to avoid the need to manually run sclang in a separate
terminal or to open the supercollider IDE.
A custom supercollider boot file can be specified by assigning its path to the
`g:tidal_sc_boot` variable.
In the case that `g:tidal_sc_boot` is unspecified, vim-tidal will traverse
parent directories until one of either `boot.sc` or `boot.scd` are found.
If no supercollider boot file can be found by traversing parent directories,
tidal will check the `g:tidal_sc_boot_fallback` variable for a fallback boot
file. This variable is useful for specifying a default user-wide supercollider
boot file on your system, while still allowing each tidal project to optionally
use their own dedicated, local supercollider boot file.
By default, `g:tidal_sc_boot_fallback` will point to the `boot.sc` file provided
with this plugin which simply starts SuperDirt with the default settings.
### Miscellaneous ###
When sending a paragraph or a single line, vim-tidal will "flash" the selection
for some milliseconds. By default duration is set to 150ms, but you can modify
it by setting the `g:tidal_flash_duration` variable.
Write the paste buffer to an external text file:
```vim
let g:tidal_paste_file = "/tmp/tidal_paste_file.txt"
```
For customizing the startup script for defining helper functions, see below.
## `tidalvim` and `tidal` ##
`tidalvim` is just an example script. You can copy and customize it as much
as you want. See `man tmux` if you want to know more about its options.
For example, if you want to split horizontally instead of vertically, change
the `-v` for `-h` option in the `split-window` line:
```diff
- split-window -v -t $SESSION \; \
+ split-window -h -t $SESSION \; \
```
Both scripts have some options that you can specify as environment variables.
For example:
```
TIDAL_TEMPO_IP=192.168.0.15 SESSION=whatever tidalvim
```
This would start Tidal synced to another Tidal on 192.168.0.15, and it would
try to attach or create a tmux sesssion called `whatever`.
The following is a list of all variables that can be changed:
* `FILE`: File name to open with Vim (default: `$(date +%F).tidal`, e.g.
`2017-03-09.tidal`). The `.tidal` extension is important (you can run
`:setfiletype haskell.tidal` in case you won't use a .tidal file here).
* `SESSION`: tmux session name (default: `tidal`)
* `TIDAL_BOOT_PATH`: Tidal Bootstrap file, a .ghci file (default: `Tidal.ghci`)
* `TIDAL_TEMPO_IP`: Tells Tidal to sync tempo with another Tidal instance on
the specified IP (default: `127.0.0.1`, i.e. use local)
* `VIM`: Vim command (default: `vim`)
* `GHCI`: GHCi command (default: `ghci`)
* `TMUX`: tmux command (default: `tmux`)
### Customizing Tidal startup ###
In case you have defined some helper functions, and/or you want to import other
modules into Tidal, you can edit the `Tidal.ghci` found at the root of the
repository.
However doing this could eventually cause conflicts when trying to upgrade
vim-tidal, so instead I recommend that you define a different `.ghci` file that
first loads `Tidal.ghci` and includes all your custom definitions.
Here is an example. Suppose you define a `myStuff.ghci` file on your home
directory like this:
```haskell
--file: ~/myStuff.ghci
-- Bootstrap Tidal
-- Replace this path if you have vim-tidal installed elsewhere
:script ~/.vim/bundle/vim-tidal/Tidal.ghci
:{
let foo = every 4 $ within (0.75, 1) (density 4)
bar = n "<0 1 2 4>"
:}
```
Then, you would run `tidal` or `tidalvim` with `TIDAL_BOOT_PATH` pointing to
your new script file:
```bash
TIDAL_BOOT_PATH=~/myStuff.ghci tidalvim
```
Please note that this a `.ghci` script, not a Haskell module. So multiline
definitions need to be wrapped around `:{` and `:}`, as shown in the example
above.
## Troubleshooting
Here is a list of common problems.
> I press `<c-e>` but it moves the screen down by one line, and nothing else happens
Usually `<c-e>` is used to move the screen forward by one line, but vim-tidal remaps
this to sending current paragraph. If this is happening you either:
1. Opened a file without `.tidal` extension, or changed file type accidentally.
*Solution*: Reopen Vim or set filetype for current buffer with `:set
ft=tidal`.
2. Have `g:tidal_no_mappings` setting on your `.vimrc`. This disables all
mappings.
*Solution*: Remove `<c-e>` binding, or rebind to something else.
It could also be that you do not have `filetype plugin on` setting in your
.vimrc. Make sure you have that setting defined.
> I press `<c-e>` and nothing else happens
This means that vim-tidal is sending text to tmux, but to the wrong
session/window/pane.
*Solution*: Check that you have configure the socket name and target pane
correctly. See the Configure section above for more information.
If you have any question or something does not work as expected, there are many
channels you can go to:
* [Chat](https://talk.lurk.org/): Reach out at the `#tidal` and `#vim` channels
* [GitHub issues](https://github.com/tidalcycles/vim-tidal/issues/new)
* [Official Tidal forum](https://we.lurk.org/postorius/lists/tidal.we.lurk.org/)
## Contributing
Bug reports and pull requests are welcome on GitHub at
<https://github.com/tidalcycles/vim-tidal>. This project is intended to be a
safe, welcoming space for collaboration, and contributors are expected to
adhere to the [Contributor Covenant](http://contributor-covenant.org) code of
conduct.
## License
Refer to the [LICENSE](LICENSE) file
================================================
FILE: Tidal.ghci
================================================
:set -XOverloadedStrings
:set prompt ""
import Sound.Tidal.Context
import System.IO (hSetEncoding, stdout, utf8)
hSetEncoding stdout utf8
-- total latency = oLatency + cFrameTimespan
tidal <- startTidal (superdirtTarget {oLatency = 0.1, oAddress = "127.0.0.1", oPort = 57120}) (defaultConfig {cVerbose = True, cFrameTimespan = 1/20})
:{
let only = (hush >>)
p = streamReplace tidal
hush = streamHush tidal
panic = do hush
once $ sound "superpanic"
list = streamList tidal
mute = streamMute tidal
unmute = streamUnmute tidal
unmuteAll = streamUnmuteAll tidal
unsoloAll = streamUnsoloAll tidal
solo = streamSolo tidal
unsolo = streamUnsolo tidal
once = streamOnce tidal
first = streamFirst tidal
asap = once
nudgeAll = streamNudgeAll tidal
all = streamAll tidal
resetCycles = streamResetCycles tidal
setcps = asap . cps
getcps = streamGetcps tidal
getnow = streamGetnow tidal
xfade i = transition tidal True (Sound.Tidal.Transition.xfadeIn 4) i
xfadeIn i t = transition tidal True (Sound.Tidal.Transition.xfadeIn t) i
histpan i t = transition tidal True (Sound.Tidal.Transition.histpan t) i
wait i t = transition tidal True (Sound.Tidal.Transition.wait t) i
waitT i f t = transition tidal True (Sound.Tidal.Transition.waitT f t) i
jump i = transition tidal True (Sound.Tidal.Transition.jump) i
jumpIn i t = transition tidal True (Sound.Tidal.Transition.jumpIn t) i
jumpIn' i t = transition tidal True (Sound.Tidal.Transition.jumpIn' t) i
jumpMod i t = transition tidal True (Sound.Tidal.Transition.jumpMod t) i
jumpMod' i t p = transition tidal True (Sound.Tidal.Transition.jumpMod' t p) i
mortal i lifespan release = transition tidal True (Sound.Tidal.Transition.mortal lifespan release) i
interpolate i = transition tidal True (Sound.Tidal.Transition.interpolate) i
interpolateIn i t = transition tidal True (Sound.Tidal.Transition.interpolateIn t) i
clutch i = transition tidal True (Sound.Tidal.Transition.clutch) i
clutchIn i t = transition tidal True (Sound.Tidal.Transition.clutchIn t) i
anticipate i = transition tidal True (Sound.Tidal.Transition.anticipate) i
anticipateIn i t = transition tidal True (Sound.Tidal.Transition.anticipateIn t) i
forId i t = transition tidal False (Sound.Tidal.Transition.mortalOverlay t) i
d1 = p 1 . (|< orbit 0)
d2 = p 2 . (|< orbit 1)
d3 = p 3 . (|< orbit 2)
d4 = p 4 . (|< orbit 3)
d5 = p 5 . (|< orbit 4)
d6 = p 6 . (|< orbit 5)
d7 = p 7 . (|< orbit 6)
d8 = p 8 . (|< orbit 7)
d9 = p 9 . (|< orbit 8)
d10 = p 10 . (|< orbit 9)
d11 = p 11 . (|< orbit 10)
d12 = p 12 . (|< orbit 11)
d13 = p 13
d14 = p 14
d15 = p 15
d16 = p 16
:}
:{
let getState = streamGet tidal
setI = streamSetI tidal
setF = streamSetF tidal
setS = streamSetS tidal
setR = streamSetR tidal
setB = streamSetB tidal
:}
:set prompt "tidal> "
:set prompt-cont ""
default (Pattern String, Integer, Double)
================================================
FILE: bin/generate-completions
================================================
#!/usr/bin/env sh
samplepath=$1
outputpath=$2
ls "$samplepath" | sed 's/README.md//; s/Dirt-Samples.quark//;' | sed '/^\s*$/d' > "$outputpath"
================================================
FILE: bin/tidal
================================================
#!/usr/bin/env bash
set -euf -o pipefail
GHCI=${GHCI:-"ghci"}
TIDAL_DATA_DIR=$($GHCI -e Paths_tidal.getDataDir | sed 's/"//g')
TIDAL_BOOT_PATH=${TIDAL_BOOT_PATH:-"$TIDAL_DATA_DIR/BootTidal.hs"}
# Run GHCI and load Tidal bootstrap file
$GHCI -ghci-script $TIDAL_BOOT_PATH "$@"
================================================
FILE: bin/tidal.bat
================================================
@ECHO OFF
REM Store the directory containing the script in a variable
SET "source=%~dp0"
REM Get path to vim-tidal bootfile
SET "TIDAL_BOOT_PATH=%SOURCE%\..\Tidal.ghci"
REM Launch Tidal Cycles
ghci -ghci-script "%TIDAL_BOOT_PATH%"
================================================
FILE: bin/tidalvim
================================================
#!/usr/bin/env bash
set -euf -o pipefail
VIM=${VIM:-"vim"}
TMUX=${TMUX:-"tmux"}
FILE=${FILE:-"$(date +%F).tidal"}
SESSION=${SESSION:-"tidal"}
TIDAL_BOOT_PATH=${TIDAL_BOOT_PATH:-""}
GHCI=${GHCI:-""}
args=${@:-$FILE}
# Check if tmux session "tidal" is running, attach only
# else, create new session, split windows and run processes
$TMUX -2 attach-session -t $SESSION || $TMUX -2 \
new-session -s $SESSION \; \
split-window -v -t $SESSION \; \
send-keys -t 0 "$VIM $args" C-m \; \
send-keys -t 1 "TIDAL_BOOT_PATH=$TIDAL_BOOT_PATH GHCI=$GHCI tidal" C-m \; \
select-pane -t 0
================================================
FILE: boot.sc
================================================
SuperDirt.start;
================================================
FILE: ftdetect/tidal.vim
================================================
autocmd BufRead,BufNewFile *.tidal setfiletype tidal
================================================
FILE: ftplugin/tidal.vim
================================================
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Functions
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let s:not_prefixable_keywords = [ "import", "data", "instance", "class", "{-#", "type", "case", "do", "let", "default", "foreign", "--"]
" guess correct number of spaces to indent
" (tabs are not allowed)
function! Get_indent_string()
return repeat(" ", 4)
endfunction
" replace tabs by spaces
function! Tab_to_spaces(text)
return substitute(a:text, " ", Get_indent_string(), "g")
endfunction
" Wrap in :{ :} if there's more than one line
function! Wrap_if_multi(lines)
if len(a:lines) > 1
return [":{"] + a:lines + [":}"]
else
return a:lines
endif
endfunction
" change string into array of lines
function! Lines(text)
return split(a:text, "\n")
endfunction
" change lines back into text
function! Unlines(lines)
if g:tidal_target == "tmux"
" Without this, the user has to manually submit a newline each time
" they evaluate an expression with `ctrl e`.
return join(a:lines, "\n") . "\n"
else
return join(a:lines, "\n")
endif
endfunction
" vim slime handler
function! _EscapeText_tidal(text)
let l:lines = Lines(Tab_to_spaces(a:text))
let l:lines = Wrap_if_multi(l:lines)
return Unlines(l:lines)
endfunction
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Mappings
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
if !exists("g:tidal_no_mappings") || !g:tidal_no_mappings
if !hasmapto('<Plug>TidalConfig', 'n')
nmap <buffer> <localleader>c <Plug>TidalConfig
endif
if !hasmapto('<Plug>TidalRegionSend', 'x')
xmap <buffer> <localleader>s <Plug>TidalRegionSend
xmap <buffer> <c-e> <Plug>TidalRegionSend
endif
if !hasmapto('<Plug>TidalLineSend', 'n')
nmap <buffer> <localleader>s <Plug>TidalLineSend
endif
if !hasmapto('<Plug>TidalParagraphSend', 'n')
nmap <buffer> <localleader>ss <Plug>TidalParagraphSend
nmap <buffer> <c-e> <Plug>TidalParagraphSend
endif
imap <buffer> <c-e> <Esc><Plug>TidalParagraphSend<Esc>i<Right>
nnoremap <buffer> <localleader>h :TidalHush<cr>
nnoremap <buffer> <c-h> :TidalHush<cr>
let i = 1
while i <= 9
execute 'nnoremap <buffer> <localleader>'.i.' :TidalSilence '.i.'<cr>'
execute 'nnoremap <buffer> <c-'.i.'> :TidalSilence '.i.'<cr>'
execute 'nnoremap <buffer> <localleader>s'.i.' :TidalPlay '.i.'<cr>'
let i += 1
endwhile
endif
================================================
FILE: plugin/tidal.vim
================================================
if exists("g:loaded_tidal") || &cp || v:version < 700
finish
endif
let g:loaded_tidal = 1
let s:parent_path = fnamemodify(expand("<sfile>"), ":p:h:s?/plugin??")
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Default config
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Attempts to find a tidal boot file in this or any parent directory.
function s:FindTidalBoot()
for name in ["BootTidal.hs", "Tidal.ghci", "boot.tidal"]
let tidal_boot_file = findfile(name, ".".';')
if !empty(tidal_boot_file)
return tidal_boot_file
endif
endfor
endfunction
" Attempts to find a supercollider startup file in this or any parent dir.
function s:FindScBoot()
for name in ["boot.sc", "boot.scd"]
let sc_boot_file = findfile(name, ".".';')
if !empty(sc_boot_file)
return sc_boot_file
endif
endfor
endfunction
if !exists("g:tidal_target")
if has('nvim') || has('terminal')
let g:tidal_target = "terminal"
else
let g:tidal_target = "tmux"
endif
endif
if !exists("g:tidal_paste_file")
let g:tidal_paste_file = tempname()
endif
if !exists("g:tidal_default_config")
let g:tidal_default_config = { "socket_name": "default", "target_pane": ":0.1" }
endif
if !exists("g:tidal_preserve_curpos")
let g:tidal_preserve_curpos = 1
endif
if !exists("g:tidal_flash_duration")
let g:tidal_flash_duration = 150
endif
if !exists("g:tidal_ghci")
let g:tidal_ghci = "ghci"
endif
if !exists("g:tidal_boot_fallback")
let g:tidal_boot_fallback = s:parent_path . "/Tidal.ghci"
endif
if !exists("g:tidal_boot")
let g:tidal_boot = s:FindTidalBoot()
if empty(g:tidal_boot)
let g:tidal_boot = g:tidal_boot_fallback
endif
endif
if !exists("g:tidal_superdirt_enable")
" Allow vim-tidal to automatically start SuperDirt. Disabled by default.
let g:tidal_superdirt_enable = 0
endif
if !exists("g:tidal_sclang")
let g:tidal_sclang = "sclang"
endif
" Allow vim-tidal to automatically start supercollider. Disabled by default.
if !exists("g:tidal_sc_enable")
let g:tidal_sc_enable = 0
endif
if !exists("g:tidal_sc_boot_fallback")
let g:tidal_sc_boot_fallback = s:parent_path . "/boot.sc"
endif
if !exists("g:tidal_sc_boot")
let g:tidal_sc_boot = s:FindScBoot()
if empty(g:tidal_sc_boot)
let g:tidal_sc_boot = g:tidal_sc_boot_fallback
endif
endif
if !exists("g:tidal_sc_boot_cmd")
" A command that can be run from the terminal to start supercollider.
" The default assumes `SuperDirt` is installed.
let g:tidal_sc_boot_cmd = g:tidal_sclang . " " . g:tidal_sc_boot
endif
if filereadable(s:parent_path . "/.dirt-samples")
let &l:dictionary .= ',' . s:parent_path . "/.dirt-samples"
endif
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Tmux
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:TmuxSend(config, text)
let l:prefix = "tmux -L " . shellescape(a:config["socket_name"])
" use STDIN unless configured to use a file
if !exists("g:tidal_paste_file")
call system(l:prefix . " load-buffer -", a:text)
else
call s:WritePasteFile(a:text)
call system(l:prefix . " load-buffer " . g:tidal_paste_file)
end
call system(l:prefix . " paste-buffer -d -t " . shellescape(a:config["target_pane"]))
endfunction
function! s:TmuxPaneNames(A,L,P)
let format = '#{pane_id} #{session_name}:#{window_index}.#{pane_index} #{window_name}#{?window_active, (active),}'
return system("tmux -L " . shellescape(b:tidal_config['socket_name']) . " list-panes -a -F " . shellescape(format))
endfunction
function! s:TmuxConfig() abort
if !exists("b:tidal_config")
let b:tidal_config = {"socket_name": "default", "target_pane": ":"}
end
let b:tidal_config["socket_name"] = input("tmux socket name: ", b:tidal_config["socket_name"])
let b:tidal_config["target_pane"] = input("tmux target pane: ", b:tidal_config["target_pane"], "custom,<SNR>" . s:SID() . "_TmuxPaneNames")
if b:tidal_config["target_pane"] =~ '\s\+'
let b:tidal_config["target_pane"] = split(b:tidal_config["target_pane"])[0]
endif
endfunction
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Terminal
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let s:tidal_term_ghci = -1
let s:tidal_term_sc = -1
" NVim and VIM8 Terminal Implementation
" =====================================
function! s:TerminalOpen()
if has('nvim')
let current_win = winnr()
if s:tidal_term_ghci == -1
" force terminal split to open below current pane
:exe "set splitbelow"
execute "split term://" . g:tidal_ghci . " -ghci-script=" . g:tidal_boot
let s:tidal_term_ghci = b:terminal_job_id
" Give tidal a moment to start up so following commands can take effect
sleep 500m
" Make terminal scroll to follow output
:exe "normal G"
:exe "normal 10\<c-w>_"
endif
if g:tidal_sc_enable == 1 && s:tidal_term_sc == -1
execute "vsplit term://" . g:tidal_sc_boot_cmd
let s:tidal_term_sc = b:terminal_job_id
" Make terminal scroll to follow output
:exe "normal G"
endif
execute current_win .. "wincmd w"
elseif has('terminal')
" Keep track of the current window number so we can switch back.
let current_win = winnr()
" Open a Terminal with GHCI with tidal booted.
if s:tidal_term_ghci == -1
execute "below split"
let s:tidal_term_ghci = term_start((g:tidal_ghci . " -ghci-script=" . g:tidal_boot), #{
\ term_name: 'tidal',
\ term_rows: 10,
\ norestore: 1,
\ curwin: 1,
\ })
endif
" Open a terminal with supercollider running.
if g:tidal_sc_enable == 1 && s:tidal_term_sc == -1
execute "vert split"
let s:tidal_term_sc = term_start(g:tidal_sc_boot_cmd, #{
\ term_name: 'supercollider',
\ term_rows: 10,
\ norestore: 1,
\ curwin: 1,
\ })
endif
" Return focus to the original window.
execute current_win .. "wincmd w"
endif
endfunction
function! s:TerminalSend(config, text)
call s:TerminalOpen()
if has('nvim')
call jobsend(s:tidal_term_ghci, a:text . "\<CR>")
elseif has('terminal')
call term_sendkeys(s:tidal_term_ghci, a:text . "\<CR>")
endif
endfunction
" These two are unnecessary AFAIK.
function! s:TerminalPaneNames(A,L,P)
endfunction
function! s:TerminalConfig() abort
endfunction
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Helpers
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:SID()
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endfun
function! s:WritePasteFile(text)
" could check exists("*writefile")
call system("cat > " . g:tidal_paste_file, a:text)
endfunction
function! s:_EscapeText(text)
if exists("&filetype")
let custom_escape = "_EscapeText_" . substitute(&filetype, "[.]", "_", "g")
if exists("*" . custom_escape)
let result = call(custom_escape, [a:text])
end
end
" use a:text if the ftplugin didn't kick in
if !exists("result")
let result = a:text
end
" return an array, regardless
if type(result) == type("")
return [result]
else
return result
end
endfunction
function! s:TidalGetConfig()
if !exists("b:tidal_config")
if exists("g:tidal_default_config")
let b:tidal_config = g:tidal_default_config
else
call s:TidalDispatch('Config')
end
end
endfunction
function! s:TidalFlashVisualSelection()
" Redraw to show current visual selection, and sleep
redraw
execute "sleep " . g:tidal_flash_duration . " m"
" Then leave visual mode
silent exe "normal! vv"
endfunction
function! s:TidalSendOp(type, ...) abort
call s:TidalGetConfig()
let sel_save = &selection
let &selection = "inclusive"
let rv = getreg('"')
let rt = getregtype('"')
if a:0 " Invoked from Visual mode, use '< and '> marks.
silent exe "normal! `<" . a:type . '`>y'
elseif a:type == 'line'
silent exe "normal! '[V']y"
elseif a:type == 'block'
silent exe "normal! `[\<C-V>`]\y"
else
silent exe "normal! `[v`]y"
endif
call setreg('"', @", 'V')
call s:TidalSend(@")
" Flash selection
if a:type == 'line'
silent exe "normal! '[V']"
call s:TidalFlashVisualSelection()
endif
let &selection = sel_save
call setreg('"', rv, rt)
call s:TidalRestoreCurPos()
endfunction
function! s:TidalSendRange() range abort
call s:TidalGetConfig()
let rv = getreg('"')
let rt = getregtype('"')
silent execute a:firstline . ',' . a:lastline . 'yank'
call s:TidalSend(@")
call setreg('"', rv, rt)
endfunction
function! s:TidalSendLines(count) abort
call s:TidalGetConfig()
let rv = getreg('"')
let rt = getregtype('"')
silent execute "normal! " . a:count . "yy"
call s:TidalSend(@")
call setreg('"', rv, rt)
" Flash lines
silent execute "normal! V"
if a:count > 1
silent execute "normal! " . (a:count - 1) . "\<Down>"
endif
call s:TidalFlashVisualSelection()
endfunction
function! s:TidalStoreCurPos()
if g:tidal_preserve_curpos == 1
if exists("*getcurpos")
let s:cur = getcurpos()
else
let s:cur = getpos('.')
endif
endif
endfunction
function! s:TidalRestoreCurPos()
if g:tidal_preserve_curpos == 1
call setpos('.', s:cur)
endif
endfunction
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Public interface
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! s:TidalSend(text)
call s:TidalGetConfig()
let pieces = s:_EscapeText(a:text)
for piece in pieces
call s:TidalDispatch('Send', b:tidal_config, piece)
endfor
endfunction
function! s:TidalConfig() abort
call inputsave()
call s:TidalDispatch('Config')
call inputrestore()
endfunction
" delegation
function! s:TidalDispatch(name, ...)
let target = substitute(tolower(g:tidal_target), '\(.\)', '\u\1', '') " Capitalize
return call("s:" . target . a:name, a:000)
endfunction
function! s:TidalHush()
execute 'TidalSend1 hush'
endfunction
function! s:TidalSilence(stream)
silent execute 'TidalSend1 d' . a:stream . ' silence'
endfunction
function! s:TidalPlay(stream)
let res = search('^\s*d' . a:stream)
if res > 0
silent execute "normal! vip:TidalSend\<cr>"
silent execute "normal! vip"
call s:TidalFlashVisualSelection()
else
echo "d" . a:stream . " was not found"
endif
endfunction
function! s:TidalGenerateCompletions(path)
let l:exe = s:parent_path . "/bin/generate-completions"
let l:output_path = s:parent_path . "/.dirt-samples"
if !empty(a:path)
let l:sample_path = a:path
else
if has('macunix')
let l:sample_path = "~/Library/Application Support/SuperCollider/downloaded-quarks/Dirt-Samples"
elseif has('unix')
let l:sample_path = "~/.local/share/SuperCollider/downloaded-quarks/Dirt-Samples"
endif
endif
" generate completion file
silent execute '!' . l:exe shellescape(expand(l:sample_path)) shellescape(expand(l:output_path))
echo "Generated dictionary of dirt-samples"
" setup completion
let &l:dictionary .= ',' . l:output_path
endfunction
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Setup key bindings
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
command -bar -nargs=0 TidalConfig call s:TidalConfig()
command -range -bar -nargs=0 TidalSend <line1>,<line2>call s:TidalSendRange()
command -nargs=+ TidalSend1 call s:TidalSend(<q-args>)
command! -nargs=0 TidalHush call s:TidalHush()
command! -nargs=1 TidalSilence call s:TidalSilence(<args>)
command! -nargs=1 TidalPlay call s:TidalPlay(<args>)
command! -nargs=? TidalGenerateCompletions call s:TidalGenerateCompletions(<q-args>)
noremap <SID>Operator :<c-u>call <SID>TidalStoreCurPos()<cr>:set opfunc=<SID>TidalSendOp<cr>g@
noremap <unique> <script> <silent> <Plug>TidalRegionSend :<c-u>call <SID>TidalSendOp(visualmode(), 1)<cr>
noremap <unique> <script> <silent> <Plug>TidalLineSend :<c-u>call <SID>TidalSendLines(v:count1)<cr>
noremap <unique> <script> <silent> <Plug>TidalMotionSend <SID>Operator
noremap <unique> <script> <silent> <Plug>TidalParagraphSend <SID>Operatorip
noremap <unique> <script> <silent> <Plug>TidalConfig :<c-u>TidalConfig<cr>
================================================
FILE: syntax/tidal.vim
================================================
" syntax highlighting for tidal/haskell
"
" Very minor modifications from syntax file of
" https://github.com/neovimhaskell/haskell-vim
"
" Heavily modified version of the haskell syntax
" highlighter to support haskell.
"
" author: raichoo (raichoo@googlemail.com)
if version < 600
syn clear
elseif exists("b:current_syntax")
finish
endif
if get(g:, 'haskell_backpack', 0)
syn keyword haskellBackpackStructure unit signature
syn keyword haskellBackpackDependency dependency
endif
syn spell notoplevel
syn match haskellRecordField contained containedin=haskellBlock
\ "[_a-z][a-zA-Z0-9_']*\(,\s*[_a-z][a-zA-Z0-9_']*\)*\_s\+::\_s"
\ contains=
\ haskellIdentifier,
\ haskellOperators,
\ haskellSeparator,
\ haskellParens
syn match haskellTypeSig
\ "^\s*\(where\s\+\|let\s\+\|default\s\+\)\?[_a-z][a-zA-Z0-9_']*#\?\(,\s*[_a-z][a-zA-Z0-9_']*#\?\)*\_s\+::\_s"
\ contains=
\ haskellWhere,
\ haskellLet,
\ haskellDefault,
\ haskellIdentifier,
\ haskellOperators,
\ haskellSeparator,
\ haskellParens
syn keyword haskellWhere where
syn keyword haskellLet let
syn match HaskellDerive "\<deriving\>\(\s\+\<\(anyclass\|instance\|newtype\|stock\)\>\)\?"
syn keyword haskellDeclKeyword module class instance newtype in
syn match haskellDecl "\<\(type\|data\)\>\s\+\(\<family\>\)\?"
syn keyword haskellDefault default
syn keyword haskellImportKeywords import qualified safe as hiding contained
syn keyword haskellForeignKeywords foreign export import ccall safe unsafe interruptible capi prim contained
syn region haskellForeignImport start="\<foreign\>" end="\_s\+::\s" keepend
\ contains=
\ haskellString,
\ haskellOperators,
\ haskellForeignKeywords,
\ haskellIdentifier
syn match haskellImport "^\s*\<import\>\s\+\(\<safe\>\s\+\)\?\(\<qualified\>\s\+\)\?.\+\(\s\+\<as\>\s\+.\+\)\?\(\s\+\<hiding\>\)\?"
\ contains=
\ haskellParens,
\ haskellOperators,
\ haskellImportKeywords,
\ haskellType,
\ haskellLineComment,
\ haskellBlockComment,
\ haskellString,
\ haskellPragma
syn keyword haskellKeyword do case of
if get(g:, 'haskell_enable_static_pointers', 0)
syn keyword haskellStatic static
endif
syn keyword haskellConditional if then else
syn match haskellNumber "\<[0-9]\+\>\|\<0[xX][0-9a-fA-F]\+\>\|\<0[oO][0-7]\+\>\|\<0[bB][10]\+\>"
syn match haskellFloat "\<[0-9]\+\.[0-9]\+\([eE][-+]\=[0-9]\+\)\=\>"
syn match haskellSeparator "[,;]"
syn region haskellParens matchgroup=haskellDelimiter start="(" end=")" contains=TOP,haskellTypeSig,@Spell
syn region haskellBrackets matchgroup=haskellDelimiter start="\[" end="]" contains=TOP,haskellTypeSig,@Spell
syn region haskellBlock matchgroup=haskellDelimiter start="{" end="}" contains=TOP,@Spell
syn keyword haskellInfix infix infixl infixr
syn keyword haskellBottom undefined error
syn match haskellOperators "[-!#$%&\*\+/<=>\?@\\^|~:.]\+\|\<_\>"
syn match haskellQuote "\<'\+" contained
syn match haskellQuotedType "[A-Z][a-zA-Z0-9_']*\>" contained
syn region haskellQuoted start="\<'\+" end="\>"
\ contains=
\ haskellType,
\ haskellQuote,
\ haskellQuotedType,
\ haskellSeparator,
\ haskellParens,
\ haskellOperators,
\ haskellIdentifier
syn match haskellLineComment "---*\([^-!#$%&\*\+./<=>\?@\\^|~].*\)\?$"
\ contains=
\ haskellTodo,
\ @Spell
syn match haskellBacktick "`[A-Za-z_][A-Za-z0-9_\.']*#\?`"
syn region haskellString start=+"+ skip=+\\\\\|\\"+ end=+"+
\ contains=@Spell
syn match haskellIdentifier "[_a-z][a-zA-z0-9_']*" contained
syn match haskellChar "\<'[^'\\]'\|'\\.'\|'\\u[0-9a-fA-F]\{4}'\>"
syn match haskellType "\<[A-Z][a-zA-Z0-9_']*\>"
syn region haskellBlockComment start="{-" end="-}"
\ contains=
\ haskellBlockComment,
\ haskellTodo,
\ @Spell
syn region haskellPragma start="{-#" end="#-}"
syn region haskellLiquid start="{-@" end="@-}"
"syn match haskellPreProc "^#.*$"
syn keyword haskellTodo TODO FIXME contained
" Treat a shebang line at the start of the file as a comment
syn match haskellShebang "\%^#!.*$"
if !get(g:, 'haskell_disable_TH', 0)
syn match haskellQuasiQuoted "." containedin=haskellQuasiQuote contained
syn region haskellQuasiQuote matchgroup=haskellTH start="\[[_a-zA-Z][a-zA-z0-9._']*|" end="|\]"
syn region haskellTHBlock matchgroup=haskellTH start="\[\(d\|t\|p\)\?|" end="|]" contains=TOP
syn region haskellTHDoubleBlock matchgroup=haskellTH start="\[||" end="||]" contains=TOP
endif
if get(g:, 'haskell_enable_typeroles', 0)
syn keyword haskellTypeRoles phantom representational nominal contained
syn region haskellTypeRoleBlock matchgroup=haskellTypeRoles start="type\s\+role" end="$" keepend
\ contains=
\ haskellType,
\ haskellTypeRoles
endif
if get(g:, 'haskell_enable_quantification', 0)
syn keyword haskellForall forall
endif
if get(g:, 'haskell_enable_recursivedo', 0)
syn keyword haskellRecursiveDo mdo rec
endif
if get(g:, 'haskell_enable_arrowsyntax', 0)
syn keyword haskellArrowSyntax proc
endif
if get(g:, 'haskell_enable_pattern_synonyms', 0)
syn keyword haskellPatternKeyword pattern
endif
highlight def link haskellBottom Macro
highlight def link haskellTH Boolean
highlight def link haskellIdentifier Identifier
highlight def link haskellForeignKeywords Structure
highlight def link haskellKeyword Keyword
highlight def link haskellDefault Keyword
highlight def link haskellConditional Conditional
highlight def link haskellNumber Number
highlight def link haskellFloat Float
highlight def link haskellSeparator Delimiter
highlight def link haskellDelimiter Delimiter
highlight def link haskellInfix Keyword
highlight def link haskellOperators Operator
highlight def link haskellQuote Operator
highlight def link haskellShebang Comment
highlight def link haskellLineComment Comment
highlight def link haskellBlockComment Comment
highlight def link haskellPragma SpecialComment
highlight def link haskellLiquid SpecialComment
highlight def link haskellString String
highlight def link haskellChar String
highlight def link haskellBacktick Operator
highlight def link haskellQuasiQuoted String
highlight def link haskellTodo Todo
"highlight def link haskellPreProc PreProc
highlight def link haskellAssocType Type
highlight def link haskellQuotedType Type
highlight def link haskellType Type
highlight def link haskellImportKeywords Include
if get(g:, 'haskell_classic_highlighting', 0)
highlight def link haskellDeclKeyword Keyword
highlight def link HaskellDerive Keyword
highlight def link haskellDecl Keyword
highlight def link haskellWhere Keyword
highlight def link haskellLet Keyword
else
highlight def link haskellDeclKeyword Structure
highlight def link HaskellDerive Structure
highlight def link haskellDecl Structure
highlight def link haskellWhere Structure
highlight def link haskellLet Structure
endif
if get(g:, 'haskell_enable_quantification', 0)
highlight def link haskellForall Operator
endif
if get(g:, 'haskell_enable_recursivedo', 0)
highlight def link haskellRecursiveDo Keyword
endif
if get(g:, 'haskell_enable_arrowsyntax', 0)
highlight def link haskellArrowSyntax Keyword
endif
if get(g:, 'haskell_enable_static_pointers', 0)
highlight def link haskellStatic Keyword
endif
if get(g:, 'haskell_classic_highlighting', 0)
if get(g:, 'haskell_enable_pattern_synonyms', 0)
highlight def link haskellPatternKeyword Keyword
endif
if get(g:, 'haskell_enable_typeroles', 0)
highlight def link haskellTypeRoles Keyword
endif
else
if get(g:, 'haskell_enable_pattern_synonyms', 0)
highlight def link haskellPatternKeyword Structure
endif
if get(g:, 'haskell_enable_typeroles', 0)
highlight def link haskellTypeRoles Structure
endif
endif
if get(g:, 'haskell_backpack', 0)
highlight def link haskellBackpackStructure Structure
highlight def link haskellBackpackDependency Include
endif
let b:current_syntax = "tidal"
gitextract_odl0_omb/
├── .gitignore
├── CHANGELOG
├── CODE_OF_CONDUCT.md
├── LICENSE
├── Makefile
├── README.md
├── Tidal.ghci
├── bin/
│ ├── generate-completions
│ ├── tidal
│ ├── tidal.bat
│ └── tidalvim
├── boot.sc
├── ftdetect/
│ └── tidal.vim
├── ftplugin/
│ └── tidal.vim
├── plugin/
│ └── tidal.vim
└── syntax/
└── tidal.vim
Condensed preview — 16 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (55K chars).
[
{
"path": ".gitignore",
"chars": 14,
"preview": ".dirt-samples\n"
},
{
"path": "CHANGELOG",
"chars": 979,
"preview": "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 se"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3225,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "LICENSE",
"chars": 1090,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Damián Emiliano Silvani\n\nPermission is hereby granted, free of charge, to any "
},
{
"path": "Makefile",
"chars": 288,
"preview": "mkfile_path := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))\n\nprefix=/usr/local\n\ninstall:\n\tln -fs $(mkfile_p"
},
{
"path": "README.md",
"chars": 17344,
"preview": "# vim-tidal #\n\nA Vim/NeoVim plugin for [TidalCycles](http://tidalcycles.org), the language for\nlive coding musical patte"
},
{
"path": "Tidal.ghci",
"chars": 3067,
"preview": ":set -XOverloadedStrings\n:set prompt \"\"\n\nimport Sound.Tidal.Context\n\nimport System.IO (hSetEncoding, stdout, utf8)\nhSetE"
},
{
"path": "bin/generate-completions",
"chars": 145,
"preview": "#!/usr/bin/env sh\n\nsamplepath=$1\noutputpath=$2\n\nls \"$samplepath\" | sed 's/README.md//; s/Dirt-Samples.quark//;' | sed '/"
},
{
"path": "bin/tidal",
"chars": 278,
"preview": "#!/usr/bin/env bash\nset -euf -o pipefail\n\nGHCI=${GHCI:-\"ghci\"}\nTIDAL_DATA_DIR=$($GHCI -e Paths_tidal.getDataDir | sed 's"
},
{
"path": "bin/tidal.bat",
"chars": 233,
"preview": "@ECHO OFF\n\nREM Store the directory containing the script in a variable\nSET \"source=%~dp0\"\n\nREM Get path to vim-tidal boo"
},
{
"path": "bin/tidalvim",
"chars": 596,
"preview": "#!/usr/bin/env bash\nset -euf -o pipefail\n\nVIM=${VIM:-\"vim\"}\nTMUX=${TMUX:-\"tmux\"}\n\nFILE=${FILE:-\"$(date +%F).tidal\"}\nSESS"
},
{
"path": "boot.sc",
"chars": 17,
"preview": "SuperDirt.start;\n"
},
{
"path": "ftdetect/tidal.vim",
"chars": 53,
"preview": "autocmd BufRead,BufNewFile *.tidal setfiletype tidal\n"
},
{
"path": "ftplugin/tidal.vim",
"chars": 2570,
"preview": "\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\" Functions\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\""
},
{
"path": "plugin/tidal.vim",
"chars": 12517,
"preview": "if exists(\"g:loaded_tidal\") || &cp || v:version < 700\n finish\nendif\nlet g:loaded_tidal = 1\nlet s:parent_path = fnamemod"
},
{
"path": "syntax/tidal.vim",
"chars": 7842,
"preview": "\" syntax highlighting for tidal/haskell\n\"\n\" Very minor modifications from syntax file of\n\" https://github.com/neovimhask"
}
]
About this extraction
This page contains the full source code of the tidalcycles/vim-tidal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 16 files (49.1 KB), approximately 14.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.