Skip to content

Conversation

@riodelphino
Copy link

@riodelphino riodelphino commented Sep 18, 2025

Easy Integration for bufferline.

Feature

  • Add config for customizing buffer name
  • Use zk.list instead of lyaml, to fetch zk note information. (title, tags, e.t.c.)

@riodelphino riodelphino mentioned this pull request Sep 18, 2025
1 task
@riodelphino
Copy link
Author

It's ready to be merged !
(Sorry for many small commits...)

integrations = {
bufferline = {
...
select = { "id", "title", "filenameStem", "metadata" }, -- Add metadata
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused here why title is being used here, but then titles are accessed with metadata.title below. Shouldn't it be metadata.title here as well or left out completely?

Copy link
Author

@riodelphino riodelphino Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a little bit confusing for me too.
Let me summarize it again.


The metadata table is fetched only from the YAML frontmatter.
So, metadata.title comes exclusively from YAML -- It does not pick up # heading.

On the other hand, title can come from either the YAML frontmatter or a # heading (with YAML taking priority).

Since some people write the title in YAML while others use a # heading, it's better to keep using "title" in select.
Using note.title is a safer fallback.

Possible title styles:

---
title : Title in YAML
---
# Title in heading
---
title : Title in YAML
---

# Title in heading

I tested it again.
Keeping "title" in select and using note.title captures the title in all cases.

Would it be better to add a note about this around the sample code?

e.g.

Note

note.metadata.title captures only YAML title, while note.title can capture either the YAML title or a # heading.
Therefore, including "title" in select table and using note.title is a safer fallback to catch the title in any positions.

Copy link
Member

@tjex tjex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had a look through everything and code looks good, although I have no experience with bufferline. I'll need to setup and double check.

@tjex tjex self-assigned this Oct 1, 2025
@riodelphino
Copy link
Author

riodelphino commented Oct 15, 2025

I think bufferline = { enabled = true } should be false by default.

Which plugin are you using instead of bufferline.nvim?

@tjex
Copy link
Member

tjex commented Nov 8, 2025

@riodelphino I'm effectively using the build in statusline, enhanced by tjdevrie's express_line

https://github.com/tjdevries/express_line.nvim

@mathias-ewald
Copy link

This will never get merged, will it?

@riodelphino
Copy link
Author

riodelphino commented Nov 19, 2025

This will never get merged, will it?

I've heard that @tjex is so busy now and there is only few reviewers recently.

But he seemed positive about the merge.

Let's wait leisurely.

Or use my folk until merge, at your own risk.

or

@mathias-ewald Does this PR seem useful for you too?

@riodelphino
Copy link
Author

I'm effectively using the build in statusline, enhanced by tjdevrie's express_line

https://github.com/tjdevries/express_line.nvim

Thank you.
It's a status-line plugin with displaying buffer name.
Since it's not maintained for years, sorry, I'm not sure that it is worth for integrating it😂
If it was a major and well-maintained plugin, I would try integrating it.

@tjex
Copy link
Member

tjex commented Nov 20, 2025

I wasn't suggesting or expecting you to integrate / adapt for express_line!.. Just answering to your question as to what I use.

This will never get merged, will it?

@mathias-ewald If it's working, then it will get merged. If you're wanting to help speed things up, then you're welcome to try it out and report back. It would seem you use bufferline already, and should then be a much better authority than me (who doesn't use it) to report whether it works or not.

Please understand that it's not motivating or in any way useful, for the first message of someone who's been waiting silently on the sidelines and wanting something to be merged to be, "This will never get merged, will it?". Some prior interaction, even a thumbs up on the initial PR message, shows maintainers and the contributor that there are others interested in it being done.

@mathias-ewald
Copy link

@tjex You're right. My apologies. It was an inconsiderate response to the issue being created in 2018.

I have great interest in this and it's probably one of my greatest pain points navigating my notes. I will see if I can carve out some time to support this project in the future.

@tjex
Copy link
Member

tjex commented Nov 20, 2025

@mathias-ewald It was created September 18, 2025. Not September 2018.

And yep, carving out the time is the difficult part. But, if you can find the time to assist on a singular PR here and there by pasting the contributors branch in your config and running it, then that helps me alot. The more people who can try out a PR and report that it's working, the better.

@tjex
Copy link
Member

tjex commented Nov 20, 2025

E.g, From first install / try, it's not working for me. And my break is now done at work. So I have to put this aside again.

image

Bufferline is just showing the filename in the tab:

image

zk config

		require("zk").setup({
			picker = globals.picker,
			lsp = {
				config = {
					cmd = { "zk", "lsp", "--log", "/tmp/zk-lsp.log" },
					name = "zk",
					on_attach = function()
						local bufnr = vim.api.nvim_get_current_buf()
						require("cmp_nvim_lsp").default_capabilities()
						keymaps(bufnr)
					end,
				},

				-- automatically attach buffers in a zk notebook that match the given filetypes
				auto_attach = {
					enabled = true,
				},
			},
			integrations = {
				bufferline = {
					enabled = true,

					-- The file patterns to hook
					pattern = { "*.md" },

					-- The fields to fetch
					select = { "id", "title", "filenameStem" },
					-- Available fields are:
					--   filename, filenameStem, path, absPath, title, lead, body, snippets,
					--   rawContent, wordCount, tags, metadata, created, modified, checksum
					-- See https://zk-org.github.io/zk/tips/editors-integration.html#zk-list

					-- buffer name formatter
					-- Only the fields set by `select` option above are available.
					formatter = function(note)
						return note.title or note.filenameStem or note.id or nil
					end,
				},
			},
		})

Bufferline config

return {
	"akinsho/bufferline.nvim",
	version = "*",
	dependencies = "nvim-tree/nvim-web-devicons",
	config = function()
		require("bufferline").setup()
	end,
}

@mathias-ewald
Copy link

I had to make a few changes to get it to load without errors. You are using some globals that I don't have. Yet the bufferline still shows the filenames (id).

return {
  name = "zk-org/zk-nvim",
  dir = "/home/me/Source/riodelphino_zk-nvim",
  config = function()
    require("zk").setup({
      picker = "telescope",
      lsp = {
        config = {
          cmd = { "zk", "lsp", "--log", "/tmp/zk-lsp.log" },
          name = "zk",
          on_attach = function()
            local bufnr = vim.api.nvim_get_current_buf()
          end,
        },

        -- automatically attach buffers in a zk notebook that match the given filetypes
        auto_attach = {
          enabled = true,
        },
      },
      integrations = {
        bufferline = {
          enabled = true,

          -- The file patterns to hook
          pattern = { "*.md" },

          -- The fields to fetch
          select = { "id", "title", "filenameStem" },
          -- Available fields are:
          --   filename, filenameStem, path, absPath, title, lead, body, snippets,
          --   rawContent, wordCount, tags, metadata, created, modified, checksum
          -- See https://zk-org.github.io/zk/tips/editors-integration.html#zk-list

          -- buffer name formatter
          -- Only the fields set by `select` option above are available.
          formatter = function(note)
            return note.title or note.filenameStem or note.id or nil
          end,
        },
      },
    })
  end,
}

@riodelphino
Copy link
Author

riodelphino commented Nov 20, 2025

I had to make a few changes to get it to load without errors. You are using some globals that I don't have. Yet the bufferline still shows the filenames (id).

@mathias-ewald Thank you for your debugging !

I guess you added only this lines:

on_attach = function()
   local bufnr = vim.api.nvim_get_current_buf()
end,

I cannot find where I use raw bufnr or vim.bo.bufnr instead of buf.bufnr (buf is a table used in my bufferline.lua) .

And I cannot reproduce the issue with your config.

@riodelphino
Copy link
Author

riodelphino commented Nov 20, 2025

NOTE: What is buf?

:h bufferline-configuration shows:

--- name_formatter can be used to change the buffer's label in the bufferline.
--- Please note some names can/will break the
--- bufferline so use this at your discretion knowing that it has
--- some limitations that will *NOT* be fixed.
name_formatter = function(buf)  -- buf contains:
      -- name                | str        | the basename of the active file
      -- path                | str        | the full path of the active file
      -- bufnr               | int        | the number of the active buffer
      -- buffers (tabs only) | table(int) | the numbers of the buffers in the tab
      -- tabnr (tabs only)   | int        | the "handle" of the tab, can be converted to its ordinal number using: `vim.api.nvim_tabpage_get_number(buf.tabnr)`
end,

So, I use it often. (e.g. buf.bufnr)

Additionally, I guess above buf is based on these classes:

---@class bufferline.Buffer
---@class bufferline.Tab

@riodelphino
Copy link
Author

riodelphino commented Nov 20, 2025

@mathias-ewald
Humm... tjex's config has same lines too. So you meant that you modified the code (not config), right ?

Could you show me the error messages or the global name or the lines you modified?

@mathias-ewald
Copy link

@riodelphino I meant the config. Specifically:

  • picker = "telescope"
  • Use of keymaps in on_attach

I have no experience getting a lot of useful logging out of nvim. What I tried was nvim -v9 nvim.log but there's not much in it as far as I can tell. I attached the file nonetheless. Please advise.
mynvim.log

Here's the plugin loaded. Looks right to me. As you can see, bufferline is still the id.
screenshot-2025-11-20_16-26-41

@riodelphino
Copy link
Author

riodelphino commented Nov 20, 2025

Thank you for reporting.
I understand that you only changed the confg.

⭐️ Your config

  • picker = "telescope"

This does not have any effects on bufferline feature. It just decides which picker you use.

  • Use of keymaps in on_attach

I can't see any keymaps(???) about it in your config.
And I think this has no effects on bufferline feature too. It's a zk lsp config.

⭐️ Minimal config

Minimal config to use this feature (in my environment) is:

integrations = {
   bufferline = {
      enabled = true,
   },
},

That's all and it works fine for me.

⭐️ Log file

I saw your log file, but it contains only Vim Events. There is no informations about this feature.
And bufferline.nvim does not have effective logging functions at a glance.

⭐️ Ensure zk and zk-nvim works fine

Sorry, but please ensure the followings:

  • Is zk command installed in your system?
  • Did you surely initialize zk on your directory? (Can you find .zk dir and .zk/notebook.db and .zk/config.toml ?)
  • Other features like :ZkNew of :ZkNote work fine?

⭐️ What error? which variable?

I had to make a few changes to get it to load without errors. You are using some globals that I don't have.

I don't think it is concerned with this feature, but please let me know the error message you get and what global variable cause this error.

Procedure:

  1. Set the minimal config above. (I mean bufferline = enabled.)
  2. load nvim
  3. Copy the error messages shown in the nvim startup.
  4. Or, you can display it by :message later. Or use :enew | put =execute('messages') to show it in a buffer, then copy it.

🚀 Check with my zk & markdown test repo

Additionally, this is my zk and markdown collection for testing.
https://github.com/riodelphino/zk-md-tests

You can clone it and check this feature with them.

@mathias-ewald
Copy link

mathias-ewald commented Nov 20, 2025

ZK Setup

❯ pwd
/home/me/Documents/Notes
❯ ls -l .zk
Permissions Size User Date Modified Name
drwxr-xr-x     - me   19 Nov 01:05   snippets
drwxr-xr-x     - me   19 Nov 01:05   templates
.rw-r--r--  5.9k me   19 Nov 01:05   config.toml
.rw-r--r--  2.3M me   20 Nov 20:21   notebook.db
❯ zk list --format oneline | wc -l
868

Nvim Configuration

❯ cat ~/.config/nvim/lua/plugins/zk.lua 
return {
  name = "zk-org/zk-nvim",
  dir = "/home/me/Source/zk-nvim",
  config = function()
    require("zk").setup({
      integrations = {
        bufferline = {
          enabled = true,
        },
      },
    })
    require("telescope").load_extension("zk")
  end,
}

Repository

❯ pwd
/home/me/Source/zk-nvim
❯ git log --oneline HEAD | head -n 1
37ac31c cfg: Set default bufferline enabled as false / doc: Add Notes sections

What I Do / See

  1. Start nvim in the zk notebook directory
❯ git log --oneline HEAD | head -n 1
37ac31c cfg: Set default bufferline enabled as false / doc: Add Notes sections
❯ nvim
  1. Check zk-nvim plugin version
image
  1. Run ZkNotes and open a note
  2. See that the bufferline is oesz.md
image

What am I missing? One error visible via :messages, but not sure where that comes from:

E21: Cannot make changes, 'modifiable' is off

@riodelphino
Copy link
Author

riodelphino commented Nov 21, 2025

Thank you @mathias-ewald.

Everything looks fine.

E21: Cannot make changes, 'modifiable' is off

I'm not sure where it comes from too.
I saw it several times in modifying nvim or plugin config.
But in this PR or plugin, I did not see.

Executing :set modifiable in current? buffer might avoid that error. (It's not a fundamental solution.)

This error often belongs to opening floating|aside window or opening buffer, from my experiences. (Sorry, I'm not sure the cause.)

require("telescope").load_extension("zk")

This telescope extension is not recommended or maintained, I think.
The recommendation is setting picker = 'telescope' in config and using :ZkNote instead, as your first config.

⭐️ Need extra config !!!

And I have to give big apologize🙏

I've forgotten to put this quite important config in README.md:

return {
   'akinsho/bufferline.nvim',
   config = function()
      require('bufferline').setup({
         options = {
            ---@param buf table
            ---@return string?
            name_formatter = function(buf)
               local ext = vim.fn.fnamemodify(buf.name, ':e')
               if ext == 'md' then
                  return require('zk.integrations.bufferline').name_formatter(buf)
               else
                  -- Other ext
                  return nil
               end
            end,
         },
      },
   },
}

Of course, you should keep below config in zk-nvim (or leave it unset)

      formatter = function(note)
        return note.title or note.filenameStem or note.id or nil
      end,

Since I consider that some people are already using their own name_formatter() in bufferline.nvim, I decided to use such separated config between bufferline and zk-nvim.

When I comment out the name_formatter = ... lines in bufferline config, the buffer names turn into filenames.

Please test it !! 🙏

Also it might be able to modify this PR's code to override bufferline's name_formatter in zk-nvim itself, to make it work without the extra outside settings.

Something like integrations.bufferline.override:

  • true -> totally override in zk-nvim (no extra config outside)
  • false -> not override and users use bufferline's name_formatter() and modify it like above.

@mathias-ewald
Copy link

That works 🚀 But one minor change, you where missing an end in your bufferline config :)

return {
  "akinsho/bufferline.nvim",
  config = function()
    require("bufferline").setup({
      options = {
        ---@param buf table
        ---@return string?
        name_formatter = function(buf)
          local ext = vim.fn.fnamemodify(buf.name, ":e")
          if ext == "md" then
            return require("zk.integrations.bufferline").name_formatter(buf)
          else
            -- Other ext
            return nil
          end
        end,
      },
    })
  end,
}
image

@mathias-ewald
Copy link

Would be great to have it here, too :)

image

@riodelphino
Copy link
Author

riodelphino commented Nov 21, 2025

That works 🚀 But one minor change, you where missing an end in your bufferline config :)

I'm grad to hear that !

Additionally, I pushed a new commit.
It allows working without bufferline's name_formatter config.

Just put override = true, and remove bufferline's name_formatter which I let you set above.
See details in README.md in the latest commit.

(And the unused patterns = {"*.md"} config was removed.)

@riodelphino
Copy link
Author

riodelphino commented Nov 21, 2025

Would be great to have it here, too :)

I haven't seen it yet in either bufferline or zk-nvim.
Please let me know the command to show it.

(It seems like which-key. And you might using lazyvim or astrovim.)

@riodelphino
Copy link
Author

riodelphino commented Nov 22, 2025

Bingo. They are bufferline keymaps and commands, which come from lazyvim.

https://github.com/LazyVim/LazyVim/blob/c64a61734fc9d45470a72603395c02137802bc6f/lua/lazyvim/plugins/ui.lua

But I cannot find any static <leader>b0~9 keymaps.
They might be set dynamically with autocmd or something else.
Searching BufEnter or <leader>b in lazyvim repository might help.

It's totally out of scope for this PR.

I might be able to help it, but please create an new issue discussion, then give some feedback.
It will not be a zk-nvim's commit or PR. Just an extra config for which-key, I guess.

@mathias-ewald
Copy link

I haven't seen it yet in either bufferline or zk-nvim. Please let me know the command to show it.
(It seems like which-key. And you might using lazyvim or astrovim.)

You're right: lazyvim. Let's get this merged, as it's super valuable 🚀

@riodelphino
Copy link
Author

@tjex

E.g, From first install / try, it's not working for me. And my break is now done at work. So I have to put this aside again.

Thanks for taking the time to look into this during your break. I didn't realize that the feature wasn't working on your side.

I wasn't suggesting or expecting you to integrate / adapt for express_line!.. Just answering to your question as to what I use.

Yeah, I know.
Since English isn’t my first language, I tend to over-explain things when I write without AI help 😂

And thank you again -- your feedback and advice are really helpful for us🌈

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants