Skip to content

2. Configuration

Simon Martineau edited this page May 31, 2024 · 32 revisions

⚠ All the following settings are in lua (with e.g. init.lua) If you use a vimscript config with init.vim, you can insert the lua lines surrounded by lua << EOF and EOF

CUSTOMIZE DEFAULT SETTINGS

Here is the default configuration that you can copy-paste and modify in your init.lua :

require('nvls').setup({
    lilypond = {
    mappings = {
      player = "<F3>",
      compile = "<F5>",
      open_pdf = "<F6>",
      switch_buffers = "<A-Space>",
      insert_version = "<F4>",
      hyphenation = "<F12>",
      hyphenation_change_lang = "<F11>",
      insert_hyphen = "<leader>ih",
      add_hyphen = "<leader>ah",
      del_next_hyphen = "<leader>dh",
      del_prev_hyphen = "<leader>dH",
    },
    options = {
      pitches_language = "default",
      hyphenation_language = "en_DEFAULT",
      output = "pdf",
      backend = nil,
      main_file = "main.ly",
      main_folder = "%:p:h",
      include_dir = nil,
      diagnostics = false,
      pdf_viewer = nil,
    },
  },
  latex = {
    mappings = {
      compile = "<F5>",
      open_pdf = "<F6>",
      lilypond_syntax = "<F3>"
    },
    options = {
      lilypond_book_flags = nil,
      clean_logs = false,
      main_file = "main.tex",
      main_folder = "%:p:h",
      include_dir = nil,
      lilypond_syntax_au = "BufEnter",
      pdf_viewer = nil,
    },
  },
  texinfo = {
    mappings = {
      compile = "<F5>",
      open_pdf = "<F6>",
      lilypond_syntax = "<F3>"
    },
    options = {
      lilypond_book_flags = "--pdf",
      clean_logs = false,
      main_file = "main.texi",
      main_folder = "%:p:h",
      --include_dir = nil,
      lilypond_syntax_au = "BufEnter",
      pdf_viewer = nil,
    },
  },
  player = {
    mappings = {
      quit = "q",
      play_pause = "p",
      loop = "<A-l>",
      backward = "h",
      small_backward = "<S-h>",
      forward = "l",
      small_forward = "<S-l>",
      decrease_speed = "j",
      increase_speed = "k",
      halve_speed = "<S-j>",
      double_speed = "<S-k>"
    },
    options = {
      row = 1,
      col = "99%",
      width = "37",
      height = "1",
      border_style = "single",
      winhighlight = "Normal:Normal,FloatBorder:Normal",
      midi_synth = "fluidsynth",
      fluidsynth_flags = nil,
      timidity_flags = nil,
      audio_format = "mp3",
      mpv_flags = {
        "--msg-level=cplayer=no,ffmpeg=no,alsa=no",
        "--loop",
        "--config-dir=/dev/null"
      }
    },
  },
})

It is possible to modify only part of the parameters, as follows :

require('nvls').setup({
  latex = {
    mappings = {
      compile = "<leader>c"
    },
    options = {
      clean_logs = true
    }
  }

PER-FOLDER CONFIGURATION

This plugin supports per-folder configuration (see the Multiple files projects section in the wiki).


INCLUDE DIRECTORIES

You can append directory to the search path for input files with relative paths in include_dir option. This can be a string or a table in case of multiple include directories :

require('nvls').setup({
  lilypond = {
    options = {
      include_dir = {
        "$HOME/Documents/",
        "$HOME/Lilypond/"
      }
    }
  }
})

HIGHLIGHTINGS

Recommended syntax sync settings

Add this lines to your init.lua :

vim.api.nvim_create_autocmd('BufEnter', { 
  command = "syntax sync fromstart",
  pattern = { '*.ly', '*.ily', '*.tex' }
})

Highlight groups

Here are the defaults used for syntax highlighting :

lilyString = { link = "String" },
lilyDynamic = { bold = true },
lilyComment = { link = "Comment" },
lilyNumber = { link = "Number" },
lilyVar = { link = "Tag" },
lilyBoolean = { link = "Boolean" },
lilySpecial = { bold = true },
lilyArgument = { link = "Type" },
lilyScheme = { link = "Special" },
lilyLyrics = { link = "Special" },
lilyMarkup = { bold = true },
lilyFunction = { link = "Statement" },
lilyArticulation = { link = "PreProc" },
lilyContext = { link = "Type" },
lilyGrob = { link = "Include" },
lilyTranslator = { link = "Type" },
lilyPitch = { link = "Function" },
lilyChord = { 
  ctermfg = "lightMagenta", 
  fg = "lightMagenta", 
  bold = true 
},

You can modify this defaults in require('nvls').setup() function, e.g :

require('nvls').setup({
  lilypond = {
    highlights {
      lilyVar = { ctermfg = "blue" }
    }
  }
)

Highlight pitches for others languages

If you use others languages for pitch names, you can configure nvim-lilypond-suite to highlight the right words with pitches_language option in require('nvls').setup()

For now, only english, français, deutsch, nohl (no highlight) and default highlights are availables.

TODO : create pitches pattern for other languages

Lighter syntax highlighting

Since 7df532e commit, I changed my method for syntax highlighting and avoided word lists as much as possible, for more lightness. You can also define pitches_language = "nohl" in require('nvls').setup() to avoid pitches highlighting.


ERROR MESSAGES

Error messages are sended to the QuickFix window (see :h quickfix). You can open it manually with :copen, or using an autocommand. The following autocmd will open quickfix when there are recognized errors. If the window is already open and there are no recognized errors, close the window :

vim.api.nvim_create_autocmd( 'QuickFixCmdPost', { 
  command = "cwindow",
  pattern = "*"
})

See also : Display error messages in a floating window

Diagnostics

You can use the vim.diagnostic.set API by adding diagnostics=true (experimental). With this option, diagnostics are enabled for the current buffer, and quickfix remains for errors in other files. (lilypond only for now)


MIDI

see issue #29
(TODO: write this section !)


AUTO-COMPLETION

Recommended settings

Install coc.nvim and coc-dictionary & coc-tabnine : works out of the box !

Dictionary files

If you want to use another completion plugin, nvim-lilypond-suite uses the following dictionary files :

$LILYDICTPATH/grobs
$LILYDICTPATH/keywords
$LILYDICTPATH/musicFunctions
$LILYDICTPATH/articulations
$LILYDICTPATH/grobProperties
$LILYDICTPATH/paperVariables
$LILYDICTPATH/headerVariables
$LILYDICTPATH/contextProperties
$LILYDICTPATH/clefs
$LILYDICTPATH/repeatTypes
$LILYDICTPATH/languageNames
$LILYDICTPATH/accidentalsStyles
$LILYDICTPATH/scales
$LILYDICTPATH/musicCommands
$LILYDICTPATH/markupCommands
$LILYDICTPATH/contextsCmd
$LILYDICTPATH/dynamics
$LILYDICTPATH/contexts
$LILYDICTPATH/translators

Configuration example

It requires the following plugins :

nvim-cmp cmp-buffer cmp-path cmp-dictionary cmp-tabnine

local cmp = require('cmp')

vim.o.completeopt="menu,menuone,noselect"

cmp.setup({
  formatting = {
    format = function(entry, item)
      item.kind = ({
        Text = "",
        })[item.kind]
      item.menu = ({
        cmp_tabnine = '',
        path        = '󰉋 ',
        dictionary  = '', 
        buffer      = '󰈙 ', 
        })[entry.source.name]
      return item
    end,
  },
  window = {
    completion = {
      completion = cmp.config.window.bordered(),
      --documentation = false
      documentation = cmp.config.window.bordered()
    },
  },
  mapping = cmp.mapping.preset.insert({
    ["<CR>"] = cmp.mapping.confirm { select = false },
    ['<tab>'] = cmp.mapping(
      cmp.mapping.select_next_item(), { 'i', 's' }
    ),
    ['<S-Tab>'] = cmp.mapping(
      cmp.mapping.select_prev_item(), { 'i', 's' }
    )
  }),
  sources = cmp.config.sources({
    { name = 'cmp_tabnine' },
    { name = 'path', keyword_length = 1 },
    { name = 'dictionary' },
    { name = 'buffer' },
  })
})

POINT AND CLICK

Neovim Remote

To use the "point and click", Nvim must be launched with remote function.

Vanilla Neovim

Since a few months, there's a built-in option :

Open your file with a server listening :

nvim --listen ~/.cache/nvim/server.pipe file.ly

Configure your point & click with something like the following (read the next sections of the wiki to adjust it) :

nvim --server ~/.cache/nvim/server.pipe --remote-send "<cmd>call cursor($line,$col)<cr>"

That's basically the principle. But Nvim does not have the --servername functionality, so there can only be one file per Nvim instance, and you must manually specify a server for all files, which greatly limits the use of this function for point and click.

Neovim-remote

I really recommend using the neovim-remote package, which for me solves all remote issues. You can open your .ly files as usual, and neovim-remote works perfectly, even with multiple .ly files open in the same session.

The rest of this section will be exclusively a config with neovim-remote, but you can adapt the commands to use the built-in function if you prefer.

Configure the Point and Click

Easy (and quite robust) way

xdg-open is (for me) quite bloated and complicated to use for a simple resource opener.
The following configuration will bypass this software. It's much simpler and more effective for me, but if you opt for a more classic configuration, go directly to the next section.

  • Option 1 : Add this lines to /usr/bin/xdg-open (e.g. line 36) :
if [[ "$@" == textedit://*ly:* ]]; then
  tmp=${@#*://} tmp="${tmp%%:*}" attr=${@#*ly:}
  file="${tmp//%20/\\ }"
  line=${attr%:*:*}
  col=${attr##*:}
  nvr -s +:"dr $file | call cursor($line, $col)"
  exit
fi

And that is all !

  • Option 2 : if you don't want to modify xdg-open :

Create a file called xdg-open in $HOME/.local/bin/ containing this code :

if [[ "$@" == textedit://*ly:* ]]; then
  tmp=${@#*://} tmp="${tmp%%:*}" attr=${@#*ly:}
  file="${tmp//%20/\\ }"
  line=${attr%:*:*}
  col=${attr##*:}
  nvr -s +:"dr $file | call cursor($line, $col)"
  exit
fi
/usr/bin/xdg-open "$@"

Make this file executable :

chmod +x $HOME/.local/bin/xdg-open

Add the folder to your path (in .bashrc) :

export PATH="$HOME/.local/bin:$PATH"

Classic way

⚠ This config don't work with files names (and dir names) containing spaces.

  • Install neovim-remote

  • Add this line to ~/.profile (or ~/.bashrc) :

export LYEDITOR="nvr -s +:'dr %(file)s | call cursor(%(line)s,%(char)s+1)'"
  • Follow the instructions on the LilyPond website to configure the system and create lilypond-invoke-editor.desktop

  • Reboot or reload session

Pdf reader

This plugin uses xdg-open command by default to view pdf (or open for mac os). You can specify a different pdf app with the pdf_viewer option :

require('nvls').setup({
  lilypond = {
    options = {
      pdf_viewer = "zathura",
    },
  },
  latex = {
    options = {
      pdf_viewer = "zathura",
    },
  },
})

Zathura

Recommended pdf viewer : zathura with zathura-pdf-mupdf plugin

Okular

Alternate custom text editor command, for Okular :

nvr +:'dr %f | call cursor(%l,%c+1)'