martineausimon / nvim-lilypond-suite

Neovim plugin for writing LilyPond scores, with asynchronous make, midi/mp3 player, fast syntax highlighting, "hyphenation" function, and support for LaTex and Texinfo files
GNU General Public License v3.0
130 stars 11 forks source link

Tips and tricks #6

Closed kflak closed 2 years ago

kflak commented 2 years ago

Not an issue per se, but just felt like it would be nice to share a few tricks here...

  1. use nvim-overseer to run a continuous compilation pipeline every time you save an .ly file. The work-flow goes like this: Define a template for overseer somewhere in your configuration like this:
    overseer.register_template({
    name = "lilypond",
    builder = function(params)
        return {
            cmd = {"lilypond", vim.fn.expand("%:p:t")},
            name = "lilypond",
            cwd = "",
            env = {},
            components = {
                "default",
            },
            metadata = {},
        }
    end,
    desc = "Compile lilypond file",
    tags = {overseer.TAG.BUILD},
    params = {},
    priority = 50,
    condition = {
        filetype = {"lilypond"},
    },
    })

    After opening a lilypond file, run :OverseerRun and select the job from the list. After this, run :OverseerQuickaction watch and hit enter to select current working directory.

This will start a background job where overseer compiles to pdf every time you save. If you combine this with an autosave-plugin and a pdf viewer that automatically updates, you will get live, immediate feedback on your scores.

  1. Make sure nvim doesn't start next line with >> after enclosing a block with these: vim.cmd([[autocmd FileType lilypond set formatoptions-=cro]]) Or, in lua:
    
    local api = vim.api
    local group = api.nvim_create_augroup("MyAutocmds", { clear = true})

api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, { pattern = {"*.ly"}, callback = function() vim.opt.formatoptions = 'jql' end, group = group })

martineausimon commented 2 years ago

Hi ! Thanks for sharing this !

I did not know nvim-overseer, and it looks great ! Initially I thought that an autocmd could be enough to compile on write, but it's buggy (it could be an improvement of :LilyCmp cmd...), and this plugin works perfect !

For the second point, my default formatoptions setting is tcqj so I had never noticed this behavior. I think the best way to transpose your vimscript setting is :

  vim.opt.formatoptions:remove({'c', 'r', 'o'})

I may create a 'tips and tricks' section on the README to share this !

kflak commented 2 years ago

Ah, great, I was looking for a way to simply remove the relevant formatoptions in lua, but couldn't find it.

kflak commented 2 years ago

I may create a 'tips and tricks' section on the README to share this ! How about creating a wiki as well? Haven't tried doing so myself, but can't imagine it's very complicated... That way you can keep the readme at a manageable size...

martineausimon commented 2 years ago

Indeed, it is a good idea! I've never done either, but I'll look into it this week

martineausimon commented 2 years ago

https://github.com/martineausimon/nvim-lilypond-suite/wiki/4.-Tips-and-tricks

kflak commented 1 year ago

Hi, opening this up again, as I've refined my overseer-template a bit, and it would be nice to include it in the wiki:

overseer.register_template({
    name = "lilypond",
    builder = function(params)
        return {
            cmd = {"lilypond", vim.fn.expand("%:p:t")},
            name = "lilypond",
            cwd = "",
            env = {},
            components = {
                "default",
                {
                    "on_output_parse", parser = {
                        -- Put the parser results into the 'diagnostics' field on the task result
                        diagnostics = {
                            -- Extract fields using lua patterns
                            {
                                "extract",
                                "^([^%s].+):(%d+):(%d+): (.+)$",
                                "filename",
                                "lnum",
                                "col",
                                "text"
                            },
                        }
                    } 
                },
                {
                    "on_result_diagnostics",
                    remove_on_restart = true,
                },
                {
                    "on_result_diagnostics_quickfix",
                    open = true
                    -- open = false -- just color highlight errors, dont open 'qf' window
                },
                {"on_complete_dispose", timeout = 600},
            },
            metadata = {},
        }
    end,
    desc = "Compile lilypond file",
    tags = {overseer.TAG.BUILD},
    params = {},
    priority = 50,
    condition = {
        filetype = {"lilypond"},
    },
})

The difference is that this will populate a quickfix window with any errors, allowing you to jump directly to the relevant error immediately on compilation failure. This might be a bit intrusive if you're setting up a task watcher that will run after each save operation (and then combine that with an autosave plugin...), so you might want to use the open = false optin in the on_result_diagnostics_quickfix component.

Props to @salkin-mada for giving me the solution!

martineausimon commented 1 year ago

Hi @kflak,

Sorry, I took a while to respond...

By configuring it this way, overseer.nvim will be launched with the options defined in require('nvls').setup() (main file, included directories, output format, and backend). I'll add that to the README.md!

local overseer = require('overseer')

overseer.register_template({
  name = "lilypond",
  builder = function(params)
    local file = require('nvls.config').fileInfos()
    local opts = require('nvls').get_nvls_options().lilypond.options

    local cmd = {
      "lilypond",
      "-f", opts.output,
    }

    local backend = opts.backend or nil
    if backend then
      table.insert(cmd, "-dbackend=" .. backend)
    end

    local include_dir = opts.include_dir or nil
    if type(include_dir) == "table" then
      for _, dir in ipairs(include_dir) do
        table.insert(cmd, "-I")
        table.insert(cmd, vim.fn.expand(dir))
      end
    elseif include_dir ~= nil and include_dir ~= "" then
      table.insert(cmd, "-I")
      table.insert(cmd, vim.fn.expand(include_dir))
    end

    table.insert(cmd, file.main)

    return {
      cmd = cmd,
      name = "lilypond",
      cwd = file.folder,
      components = {
        "default",
        {
          "on_output_parse", parser = {
            diagnostics = {
              {
                "extract",
                "^([^%s].+):(%d+):(%d+): (.+)$",
                "filename",
                "lnum",
                "col",
                "text"
              },
            }
          }
        },
        {
          "on_result_diagnostics",
          remove_on_restart = true,
        },
        {
          "on_result_diagnostics_quickfix",
          open = true
        },
        {
          "on_complete_dispose",
          timeout = 600
        },
      },
      metadata = {},
    }
  end,
  desc = "Compile Lilypond file",
  tags = { overseer.TAG.BUILD },
  priority = 50,
  condition = {
    filetype = { "lilypond" },
  },
})
kflak commented 1 year ago

This is fantastic! Thanks :-)