SCNVim - A NeoVim frontend for SuperCollider

If you give me a link to GreenScope I can test it on my system. I’m also using Hyprland.

1 Like

thx !! it is on f0 github: GitHub - redFrik/greenSys: Green system including tools, GUI

OK, interesting… I can confirm. Not showing up in scnvim, does show up in scide. Looking at the source code, I can see that all the gui stuff is in a folder called scide_scqt, so it seems very much tied to scide.

1 Like

Try simply renaming that folder… (and the `side_scqt folder in the GUICV quark as well) - this worked for me…

No, it’s a mistake.

Slider, Button, scope views etc. are sclang widgets – no relationship to the IDE.

One would use a scide_scqt folder if one is extending the Document class, which is associated with SCIDE, but that’s not the case here.

I logged a bug report with the quark to change the name.

hjh

1 Like

But here @madskjeldgaard hits some key and then the args are filled in…

edit: ok, that’s coming from this probably:

Which doesn’t work in my setup using UltiSnips.

Edit: it works with luasnip

1 Like

Hello! Has anyone of you succeeded in getting the key binding to work in the LazyVim distro?
I recently switched from a self-built messy neovim in which scnvim was working perfectly to LazyVim and can’t get my head around it. LazyVim discourages the use of the init.lua file.

This is my .config/nvim/lua/plugins/supercollider.lua file in its last state (the multiple require statement looks stinky). I changed it millions of times in the last dayS, turning and moving things around with this little voice inside of my head telling me I might look at the wrong place… So here I am to ask if someone had experience with it!

Important note: syntax highlighting and snippets are working perfectly, but the keys don’t seem to get registered!

return {
  'davidgranstrom/scnvim',
  opts = {
    editor = {
      highlight = {
        color = 'IncSearch',
      },
    },
    postwin = {
      float = {
        enabled = false,
      },
    },
  },
  keys = {
      {'<M-e>', function() require('scnvim').map('editor.send_line', {'i', 'n'}) end },
      {'<C-e>', function() require('scnvim').map('editor.send_block', {'i', 'n'}) end },
      {'<C-E>', function() require('scnvim').map('editor.send_selection', 'x') end },
      {'<C-s>', function() require('scnvim').map('sclang.start') end, desc = 'start SC language' },
      {'<leader>lr', function() require('scnvim').map('sclang.recompile') end },
      {'<C-.>', function() require('scnvim').map_expr('s.quit') end },
      {'<CR>', function() require('scnvim').map('postwin.toggle') end },
      {'<F1>', function() require('scnvim').map_expr('s.boot') end },
      {'<F2>', function() require('scnvim').map_expr('s.meter') end },
  }
}

The key bindings in the code are also messy. My question is more about the structure and where to write what. :slight_smile:
Thanks in advance!!

Hi I also use Lazy -

…I think it is supposed to be keymaps not keys, no?

this works for me:

local scnvim = require('scnvim')
scnvim.setup()
--
local map = scnvim.map
local map_expr = scnvim.map_expr
scnvim.setup {
	ensure_installed = true,
	--[[ sclang = {
		cmd = "/Users/michael/tank/super-mraethel/supercollider/build/Install/SuperCollider/SuperCollider.app/Contents/MacOS/sclang",
	-- 	cmd = "sclang"
		args = {'-l', "/tmp/sclang_conf.yaml"  }
	}, ]]
	extensions = {
		['fzf-sc'] = {
			search_plugin = 'nvim-fzf',
		},
		logger = {
			path = '/tmp/post'
		},
	},
	keymaps = {
		[',l'] = map('editor.send_line', {'i', 'n'}),
		[',.'] = {
			map('editor.send_block', {'i', 'n'}),
			map('editor.send_selection', 'x'),
			},
		['<CR>'] = map('postwin.toggle'),
		['<M-CR>'] = map('postwin.toggle', 'i'),
		['zp'] = map('postwin.clear', {'n', 'i'}),
		[',fp'] = map('postwin.focus',{'n'}),
		['<C-k>'] = map('signature.show', {'n', 'i'}),
		['zZ'] = map('sclang.hard_stop', {'n', 'x', 'i'}),
		['<leader>st'] = map('scnvim.start'),
		['<leader>sp'] = map(scnvim.recompile),
		['<F1>'] = map_expr('s.boot'),
		['<F2>'] = map_expr('s.meter'),
		['zx'] = map_expr('~myFree.()')
		},
	documentation = {
		cmd = '/usr/local/bin/pandoc',
		},
	postwin = {
		size = 55,
		auto_toggle_error = false,
		fixed_size = 55,
		highlight = true,
		float = {
			--enabled =true,
			callback =function(id) vim.api.nvim_win_set_option(id, 'winblend', 0) end,
			height = 18
			},
		border = {

			}

		},
	snippet = {
		engine ={
			name ="luasnip"
		}
	}
}

Hey @semiquaver! Thank you very much for your answer!

“…I think it is supposed to be keymaps not keys , no?”
That’s the whole trick with LazyVim https://www.lazyvim.org/

I had a config in neovim with Lazy.vim as package Manager and it worked like a charm. In the LazyVim distro, you write the content of the setup in the opts map and pass the keymaps in the keys map but these are done on a function call in the SCNvim config. That’s where I seem not to get it. But after seing your config, I got an Idea… I’ll get back to you after having tried it :slight_smile:

Thank you again!

1 Like

Hello @semiquaver, I unfortunately had no luck with any further code twirling. I just asked the Q&A of LazyVim directly.
I will post here again with the full config if I get it to work!

Note that require('scnvim').map() is a helper function to define a mapping, but it does not actually set the mapping.

If you print the result of require('scnvim').map('editor.send_line', {'i', 'n'}) you will see that it returns a table with some predefined values:

{
  fn = <function 1>,
  modes = { "i", "n" },
  options = {
    desc = "scnvim: editor.send_line"
  }
}

This table is later used to construct the keymap. It looks something like this (see scnvim/editor.lua):

vim.keymap.set(v.modes, key, v.fn, v.options)

So, using the scnvim.map function is entirely optional, you could also leave the keymaps table empty in scnvim.setup and define your own mappings with or without the helper function:

vim.keymap.set({'i', 'n'}, '<F5>', function()
  require('scnvim.editor').send_line()
end)

or

local tbl = require('scnvim').map('editor.send_line', {'i', 'n'})
vim.keymap.set(tbl.modes, '<C-x>', tbl.fn, tbl.options)

Hope this helps!

2 Likes

@davidgranstrom first thank you for the amazing work!

And thanks a billion! Of course it helped! I/You got it to work!
It was clear to me that map() is only a helper function, but I didn’t know how to formulate the call and where (I should have read the sources and the docs better… stoopid me)!

So in case someone is encountering the same situation, in LazyVim you have to:

  • Load the plugin with, as suggested above, an empty keymaps map in the file ~/.config/nvim/lua/plugins/supercollider.lua
  • Define the key maps as suggested by @davidgranstrom in the file ~/.config/nvim/lua/config/keymaps.lua

If you want the keymaps to apply for sc files only, wrap them into this condition:

if vim.bo.filetype == "supercollider" then
  local start_sclang_def = require("scnvim").map("sclang.start", { "i", "n" })
  vim.keymap.set(start_sclang_def.modes, "<F2>", start_sclang_def.fn, start_sclang_def.options)

  local boot_server_def = require("scnvim").map_expr("s.boot", { "i", "n" })
  vim.keymap.set(boot_server_def.modes, "<F3>", boot_server_def.fn, boot_server_def.options)

-- and so on
end

Thank you again!

2 Likes

Excited to try out this plugin!

I’m struggling to get my custom classes to load. The folders they reside in is specified in a yaml-file and loads as expected in the SC IDE. I’ve tried this in the config table without any luck:

sclang = {
    args = {'-l', '~/Library/Application Support/SuperCollider/sclang_conf_organic.yaml'}
},

The docs say ‘Comma separated arguments passed to the sclang executable.’. I cannot seem to find any examples, so I’m probably formatting this the wrong way. Passing this argument when running sclang in the terminal seems to work correctly.

I think it might be the ~ tilde… at least for me, that made a difference. (Also on a Mac). So “/Users/you/Library/etc” instead of “~/Library”.

Great, that did the trick! Thank you!

In case this marginally improves somebody’s quality of life, I just made a repo of my config for the nvim-web-devicons plugins that assigns filetype icons to sc files. I have:

scd - blue triangle wave
sc - red sine (overwrites scala icon)
schelp - yellow square
scx - green saw.
quark - white milk bottle (if you leave it sitting long enough, milk becomes what Austrians call Topfen and Germans call Quark).

There’s also a c clef icon for lilypond files.

2 Likes

Can this be added to core? :grin:

hjh

Hi,

I’m new to SuperCollider (running on Ubuntu 24.04) and trying to figure out how to get autocompletion to SCnvim. I’m using lazyvim for plugins and everything is working fine. I can boot the server and get sound. I also managed to get buffer auto completion with blink, but I didn’t find any description how to get autocompletion working with all commands (e.g. SinOsc, etc).

It seems nvim cmp is the way to go, but it’s not clear to me how to install and configure it with lazyvim (I’m can also use any other plugin manager. As I’m new to that stuff I don’t have any preferences, but packer.vim what was suggested by @madskjeldgaard 2022 seems to be unmaintained meanwhile).

I got some command suggestions in nvim with nvim cmp and the help of chatgpt, but there where too many errors showing up:

What I have till now:

This is my nvim tree in .config

/.config/nvim$ tree .

.
├── init.lua
├── lazy-lock.json
└── lua
    └── config
        ├── lazy.lua
        └── plugins
            ├── luasnip.lua
            ├── nightfox.lua
            ├── scnvim.lua
            ├── scnvim.lua_bkp
            └── tokyonight.lua

This is my init.lua file:

require("config.lazy")
--Color theme
vim.cmd([[colorscheme nightfox ]])
--Add line numbers
vim.wo.relativenumber = true

lazy.lua:

-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  local lazyrepo = "https://github.com/folke/lazy.nvim.git"
  local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
  if vim.v.shell_error ~= 0 then
    vim.api.nvim_echo({
      { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
      { out, "WarningMsg" },
      { "\nPress any key to exit..." },
    }, true, {})
    vim.fn.getchar()
    os.exit(1)
  end
end
vim.opt.rtp:prepend(lazypath)

-- Make sure to setup `mapleader` and `maplocalleader` before
-- loading lazy.nvim so that mappings are correct.
-- This is also a good place to setup other settings (vim.opt)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"

-- Setup lazy.nvim
require("lazy").setup({
  spec = {
	  --import plugins here
	  { import = "config.plugins" },
  },
  -- Configure any other settings here. See the documentation for more details.
  -- colorscheme that will be used when installing plugins.
  install = { colorscheme = { "habamax" } },
  -- automatically check for plugin updates
  checker = { enabled = true },
})

and scnvim.lua

return {
  {
    "davidgranstrom/scnvim",
    ft = "supercollider",
    config = function()
      local scnvim = require("scnvim")
      local map = scnvim.map
      local map_expr = scnvim.map_expr

      scnvim.setup({
	      keymaps = {
          ["<M-e>"] = map("editor.send_line", { "i", "n" }),
          ["<C-e>"] = {
            map("editor.send_block", { "i", "n" }),
            map("editor.send_selection", "x"),
          },
          ["<CR>"]    = map("postwin.toggle"),
          ["<M-CR>"]  = map("postwin.toggle", "i"),
          ["<M-L>"]   = map("postwin.clear", { "n", "i" }),
          ["<C-k>"]   = map("signature.show", { "n", "i" }),
          ["<F12>"]   = map("sclang.hard_stop", { "n", "x", "i" }),
          ["<leader>st"] = map("sclang.start"),
          ["<leader>sk"] = map("sclang.recompile"),
          ["<F1>"]    = map_expr("s.boot"),
          ["<F2>"]    = map_expr("s.meter"),
        },
        editor = {
          highlight = {
            color = "IncSearch",
          },
        },
        postwin = {
          float = {
            enabled = true,
          },
        },
      })
    end,
  },
}


I would suggest Blink instead of nvim-cmp - I just switched…

1 Like

thanks, is it somewhere described how to configure this?