nvim-orgmode / orgmode

Orgmode clone written in Lua for Neovim 0.9+.
https://nvim-orgmode.github.io/
MIT License
3.03k stars 134 forks source link

Opening code blocks in a temporal buffer #146

Closed oko-nasa closed 2 years ago

oko-nasa commented 2 years ago

Does this feature exist in Emacs orgmode core?

Yes

Orgmode link

By the end of the Literal-Exampels section, there's a keybind for what seems to be opening code blocks in a separate buffer. https://orgmode.org/org.html#Literal-Examples

Feature value

Editing in a separate buffer with its own filetype is much more comfortable than doing it within the block. Furthermore, that makes it easier to interoperate with other plugins - just the top off my head, autocompletion and diagnostics via LSP would be trivially included.

Additional context

No response

levouh commented 2 years ago

Probably not the cleanest (I believe there's actually also a bug with how src_block gets defined in this quick example), but we can pretty easily interact with source blocks using something like:

local parsers = require("nvim-treesitter.parsers")
local ts_utils = require("nvim-treesitter.ts_utils")

local in_src_block = function()
  if not parsers.has_parser() then
    return nil
  end

  local current = ts_utils.get_node_at_cursor()
  if not current then
    return
  end

  local src_node
  while current ~= nil do
    if current:type() == "block" then
      local child_count = current:named_child_count()

      for i = 1, child_count do
        local child = current:named_child(i - 1)

        if child:type() == "name" then
          src_node = child
          break
        end
      end

      if src_node and ts_utils.get_node_text(src_node)[1] == "SRC" then
        break
      end
    end

    current = current:parent()
  end

  if not src_node then
    vim.notify("Not in a source block", vim.lsp.log_levels.WARN, { title = "Orgmode" })
    return false
  end

  local pos = vim.api.nvim_win_get_cursor(0)
  return ts_utils.is_in_node_range(src_node:parent(), pos[1], pos[2])
end

(really this just checks if we are in a source block, but returning the node text is a trivial addition). From this then we can just put the lines in a new buffer, and set ft=... to whatever from there. Happy to open a PR with a proof-of-concept for this @kristijanhusak, but curious on your thoughts first.

levouh commented 2 years ago

The above example applies only to SRC blocks too, but I'm not familiar enough with Org to know why we'd want to edit a non-SRC block in another buffer other than just for "shits and giggles". The solution could apply in a general sense, but it would change what handling is necessary for doing things like setting :h filetype and similar (referring specifically to the documentation noted by @seiyagit, where one might want to edit a #+BEGIN_EXAMPLE block in another buffer).

kristijanhusak commented 2 years ago

Happy to open a PR with a proof-of-concept for this @kristijanhusak, but curious on your thoughts first.

@levouh go for it :)