From 3b6bbca658576db728c4acb59ccdde9caba9e7bd Mon Sep 17 00:00:00 2001 From: pat-alt Date: Mon, 7 Apr 2025 18:38:24 +0200 Subject: [PATCH] quarto --- lazy-lock.json | 7 +- lua/custom/plugins/quarto.lua | 159 +++++++++++++++++++++++++++++++++- 2 files changed, 161 insertions(+), 5 deletions(-) diff --git a/lazy-lock.json b/lazy-lock.json index 7e76a9a2..346d3a8a 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -7,12 +7,16 @@ "conform.nvim": { "branch": "master", "commit": "eebc724d12c5579d733d1f801386e0ceb909d001" }, "fidget.nvim": { "branch": "main", "commit": "d9ba6b7bfe29b3119a610892af67602641da778e" }, "gitsigns.nvim": { "branch": "main", "commit": "17ab794b6fce6fce768430ebc925347e349e1d60" }, + "img-clip.nvim": { "branch": "main", "commit": "08a02e14c8c0d42fa7a92c30a98fd04d6993b35d" }, + "jupytext.nvim": { "branch": "main", "commit": "c8baf3ad344c59b3abd461ecc17fc16ec44d0f7b" }, "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, "lazydev.nvim": { "branch": "main", "commit": "2367a6c0a01eb9edb0464731cc0fb61ed9ab9d2c" }, "mason-lspconfig.nvim": { "branch": "main", "commit": "1a31f824b9cd5bc6f342fc29e9a53b60d74af245" }, "mason-tool-installer.nvim": { "branch": "main", "commit": "1255518cb067e038a4755f5cb3e980f79b6ab89c" }, "mason.nvim": { "branch": "main", "commit": "fc98833b6da5de5a9c5b1446ac541577059555be" }, - "mini.nvim": { "branch": "main", "commit": "e744b5dbb3158242af77124bd6763a8647ea82ed" }, + "mini.nvim": { "branch": "main", "commit": "fe8a669078a5066220262f173bf901f322e39c05" }, + "molten-nvim": { "branch": "main", "commit": "a286aa914d9a154bc359131aab788b5a077a5a99" }, + "nabla.nvim": { "branch": "master", "commit": "27a6ea9ed7452bb9e0b19eb0942b5bcf7d051b2f" }, "nvim-cmp": { "branch": "main", "commit": "059e89495b3ec09395262f16b1ad441a38081d04" }, "nvim-lspconfig": { "branch": "master", "commit": "442e077e326ac467daf9cd63e72120fb450a850b" }, "nvim-treesitter": { "branch": "master", "commit": "205faba1768a6e4c854f156bc6a21a41b242599c" }, @@ -26,5 +30,6 @@ "todo-comments.nvim": { "branch": "main", "commit": "304a8d204ee787d2544d8bc23cd38d2f929e7cc5" }, "tokyonight.nvim": { "branch": "main", "commit": "057ef5d260c1931f1dffd0f052c685dcd14100a3" }, "vim-sleuth": { "branch": "master", "commit": "be69bff86754b1aa5adcbb527d7fcd1635a84080" }, + "vim-slime": { "branch": "main", "commit": "9bc2e13f8441b09fd7352a11629a4da0ea4cb058" }, "which-key.nvim": { "branch": "main", "commit": "370ec46f710e058c9c1646273e6b225acf47cbed" } } diff --git a/lua/custom/plugins/quarto.lua b/lua/custom/plugins/quarto.lua index 37e64ac0..508488d1 100644 --- a/lua/custom/plugins/quarto.lua +++ b/lua/custom/plugins/quarto.lua @@ -1,11 +1,162 @@ --- plugins/quarto.lua return { - { -- Quarto + + { -- requires plugins in lua/plugins/treesitter.lua and lua/plugins/lsp.lua + -- for complete functionality (language features) 'quarto-dev/quarto-nvim', + dev = false, + opts = { + lspFeatures = { + enabled = true, + chunks = 'curly', + }, + codeRunner = { + enabled = true, + default_method = 'slime', + }, + }, dependencies = { + -- for language features in code cells + -- configured in lua/plugins/lsp.lua 'jmbuhr/otter.nvim', - 'nvim-treesitter/nvim-treesitter', }, }, -} + { -- directly open ipynb files as quarto docuements + -- and convert back behind the scenes + 'GCBallesteros/jupytext.nvim', + opts = { + custom_language_formatting = { + python = { + extension = 'qmd', + style = 'quarto', + force_ft = 'quarto', + }, + r = { + extension = 'qmd', + style = 'quarto', + force_ft = 'quarto', + }, + }, + }, + }, + + { -- send code from python/r/qmd documets to a terminal or REPL + -- like ipython, R, bash + 'jpalardy/vim-slime', + dev = false, + init = function() + vim.b['quarto_is_python_chunk'] = false + Quarto_is_in_python_chunk = function() + require('otter.tools.functions').is_otter_language_context 'python' + end + + vim.cmd [[ + let g:slime_dispatch_ipython_pause = 100 + function SlimeOverride_EscapeText_quarto(text) + call v:lua.Quarto_is_in_python_chunk() + if exists('g:slime_python_ipython') && len(split(a:text,"\n")) > 1 && b:quarto_is_python_chunk && !(exists('b:quarto_is_r_mode') && b:quarto_is_r_mode) + return ["%cpaste -q\n", g:slime_dispatch_ipython_pause, a:text, "--", "\n"] + else + if exists('b:quarto_is_r_mode') && b:quarto_is_r_mode && b:quarto_is_python_chunk + return [a:text, "\n"] + else + return [a:text] + end + end + endfunction + ]] + + vim.g.slime_target = 'neovim' + vim.g.slime_no_mappings = true + vim.g.slime_python_ipython = 1 + end, + config = function() + vim.g.slime_input_pid = false + vim.g.slime_suggest_default = true + vim.g.slime_menu_config = false + vim.g.slime_neovim_ignore_unlisted = true + + local function mark_terminal() + local job_id = vim.b.terminal_job_id + vim.print('job_id: ' .. job_id) + end + + local function set_terminal() + vim.fn.call('slime#config', {}) + end + vim.keymap.set('n', 'cm', mark_terminal, { desc = '[m]ark terminal' }) + vim.keymap.set('n', 'cs', set_terminal, { desc = '[s]et terminal' }) + end, + }, + + { -- paste an image from the clipboard or drag-and-drop + 'HakonHarnes/img-clip.nvim', + event = 'BufEnter', + ft = { 'markdown', 'quarto', 'latex' }, + opts = { + default = { + dir_path = 'img', + }, + filetypes = { + markdown = { + url_encode_path = true, + template = '![$CURSOR]($FILE_PATH)', + drag_and_drop = { + download_images = false, + }, + }, + quarto = { + url_encode_path = true, + template = '![$CURSOR]($FILE_PATH)', + drag_and_drop = { + download_images = false, + }, + }, + }, + }, + config = function(_, opts) + require('img-clip').setup(opts) + vim.keymap.set('n', 'ii', ':PasteImage', { desc = 'insert [i]mage from clipboard' }) + end, + }, + + { -- preview equations + 'jbyuki/nabla.nvim', + keys = { + { 'qm', ':lua require"nabla".toggle_virt()', desc = 'toggle [m]ath equations' }, + }, + }, + + { + 'benlubas/molten-nvim', + dev = false, + enabled = true, + version = '^1.0.0', -- use version <2.0.0 to avoid breaking changes + build = ':UpdateRemotePlugins', + init = function() + vim.g.molten_image_provider = 'image.nvim' + -- vim.g.molten_output_win_max_height = 20 + vim.g.molten_auto_open_output = true + vim.g.molten_auto_open_html_in_browser = true + vim.g.molten_tick_rate = 200 + end, + config = function() + local init = function() + local quarto_cfg = require('quarto.config').config + quarto_cfg.codeRunner.default_method = 'molten' + vim.cmd [[MoltenInit]] + end + local deinit = function() + local quarto_cfg = require('quarto.config').config + quarto_cfg.codeRunner.default_method = 'slime' + vim.cmd [[MoltenDeinit]] + end + vim.keymap.set('n', 'mi', init, { silent = true, desc = 'Initialize molten' }) + vim.keymap.set('n', 'md', deinit, { silent = true, desc = 'Stop molten' }) + vim.keymap.set('n', 'mp', ':MoltenImagePopup', { silent = true, desc = 'molten image popup' }) + vim.keymap.set('n', 'mb', ':MoltenOpenInBrowser', { silent = true, desc = 'molten open in browser' }) + vim.keymap.set('n', 'mh', ':MoltenHideOutput', { silent = true, desc = 'hide output' }) + vim.keymap.set('n', 'ms', ':noautocmd MoltenEnterOutput', { silent = true, desc = 'show/enter output' }) + end, + }, +}