/markdown-oxide

Let's record your consciousness! Bring your own text editor! Implemented as a language server compatible with any text editor, Markdown-Oxide is attempting to be the best PKM system for software enthusiasts.

Primary LanguageRustCreative Commons Zero v1.0 UniversalCC0-1.0

Markdown Oxide

Markdown Oxide is attempting to be the best PKM system for software enthusiasts - people like me who (in addition to note-taking) are addicted to creating the best text editing experience.

Obsidian strongly inspires Markdown Oxide's PKM features - in fact, Markdown Oxide is fully compatible with your Obsidian vault. Markdown Oxide does not aim to fully replace Obsidian; it serves to provide a feature-rich and advanced note-taking experience. Obsidian remains a terrific front-end for your linked markdown notes. Also, in terms of features, Markdown Oxide and Obsidian are quite alligned.

Markdown Oxide's features are implemented in the form of a language server aiming to be fully compatible with your favorite text editor and its ecosystem. Read on to learn what Markdown Oxide provides and how to install and configure it.

Installation

(if you want to skip to the features, click here)

Neovim

  1. Given Neovim access to the binary.

    • Cargo Install (from source)
      cargo install --locked --git https://github.com/Feel-ix-343/markdown-oxide.git markdown-oxide
    • Cargo binstall (from hosted binary)
      cargo binstall --git 'https://github.com/feel-ix-343/markdown-oxide' markdown-oxide
    • AUR (from source)
      paru -S markdown-oxide-git
      yay -S markdown-oxide-git
    • Mason.nvim (from hosted binary)
    • Nix Unstable: pkgs.markdown-oxide
  2. Modify your Neovim Configuration

    • Modify LSP Config (making sure to adjust capabilities as follows)
      -- An example nvim-lspconfig capabilities setting
      local capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities())
      
      -- Ensure that dynamicRegistration is enabled! This allows the LS to take into account actions like the
      -- Create Unresolved File code action, resolving completions for unindexed code blocks, ...
      capabilities.workspace = {
          didChangeWatchedFiles = {
            dynamicRegistration = true,
          },
      }
      
      require("lspconfig").markdown_oxide.setup({
          capabilities = capabilities, -- again, ensure that capabilities.workspace.didChangeWatchedFiles.dynamicRegistration = true
          on_attach = on_attach -- configure your on attach config
      })
    • Modify your nvim-cmp configuration

      Modify your nvim-cmp source settings for nvim-lsp (note: you must have nvim-lsp installed)

      {
      name = 'nvim_lsp',
        option = {
          markdown_oxide = {
            keyword_pattern = [[\(\k\| \|\/\|#\)\+]]
          }
        }
      },
    • (optional) Enable Code Lens (eg for UI reference count)

      Modify your lsp on_attach function.

      -- refresh codelens on TextChanged and InsertLeave as well
      vim.api.nvim_create_autocmd({ 'TextChanged', 'InsertLeave', 'CursorHold', 'LspAttach' }, {
          buffer = bufnr,
          callback = vim.lsp.codelens.refresh,
      })
      
      -- trigger codelens refresh
      vim.api.nvim_exec_autocmds('User', { pattern = 'LspAttached' })

VSCode

Install the vscode extension (called Markdown Oxide). As for how the extension uses uses the language server, there are two options

  1. Recommended: the extension will download the server's binary and use that

  2. The extension will use markdown-oxide from path. To install to your path, there are the following methods for VSCode:

    • Cargo Install (from source)
      cargo install --locked --git https://github.com/Feel-ix-343/markdown-oxide.git markdown-oxide
    • Cargo binstall (from hosted binary)
      cargo binstall --git 'https://github.com/feel-ix-343/markdown-oxide' markdown-oxide
    • AUR (from source)
      paru -S markdown-oxide-git
      yay -S markdown-oxide-git
    • Nix Unstable: pkgs.markdown-oxide

Zed

Markdown Oxide is available as an extension titled Markdown Oxide. Similarly to VSCode, there are two methods for this extension to access the language server

  1. Recommended: the extension will download the server's binary and use that

  2. The extension will use markdown-oxide from path. To install to your path, there are the following methods for Zed:

    • Cargo Install (from source)
      cargo install --locked --git https://github.com/Feel-ix-343/markdown-oxide.git markdown-oxide
    • Cargo binstall (from hosted binary)
      cargo binstall --git 'https://github.com/feel-ix-343/markdown-oxide' markdown-oxide
    • AUR (from source)
      paru -S markdown-oxide-git
      yay -S markdown-oxide-git
    • Nix Unstable: pkgs.markdown-oxide

Note

Zed does not implement some of the language server protocol that this LS uses. Namely, unindexed block completions do not work at all. There are also other issues with the language server unique to Zed (such as completions being unexpectedly hidden). Over time, these issues will be resolved; for now, Zed provides an interesting exhibition for a potential (beautiful + fast) note-taking experience provided by markdown oxide

Helix

For Helix, all you must do is install the language server's binary to your path. The following installation methods are available:

  • Cargo Install (from source)
    cargo install --locked --git https://github.com/Feel-ix-343/markdown-oxide.git markdown-oxide
  • Cargo binstall (from hosted binary)
      ```bash
      cargo binstall --git 'https://github.com/feel-ix-343/markdown-oxide' markdown-oxide
      ```
    
  • AUR (from source)
    paru -S markdown-oxide-git
    yay -S markdown-oxide-git
  • Nix Unstable: pkgs.markdown-oxide

Note

There are some major issues with markdown oxide on helix as it does not fully implement the language server protocol. Most obtrusive is that helix does not implement is_incomplete for completions, and since completion filtering and sorting happens on the server (for performance), you must manually re-request completions after typing (one method I have found is to exit and re-enter insert mode)

Linking Syntax

The linking syntax is that of Obsidian's and can be found here https://help.obsidian.md/Linking+notes+and+files/Internal+links

Generally, this is [[relativeFilePath(#heading)?(|display text)?]] e.g. [[articles/markdown oxide#Features|Markdown Oxide Features]] to link to a heading in Markdown Oxide.md file in the articles folder or [[Obsidian]] for the Obsidian.md file in the root folder. Markdown oxide also supports markdown links

Features

Note

To interact with a file as a referenceable (for getting references, renaming, hover-view, ...), put your cursor/pointer anywhere on the markdown fide where there is not another referenceable (heading, tag, ...).

Completions

  • Wikilink Completions

    wikilinkcompletions

  • Markdown Link Completions

    markdownlinkcompletions

  • Unindexed Block Completions; Fuzzy search through the whole folder of files and link anywhere, following obsidian block linking syntax

    to use this, type [[, and after you press space, completions for every block in the vault will appear; continue typing to fuzzy match the block that you want; finally, select the block; a link will be inserted to the text document and an index (ex ^1j239) will be appended to the block in its respective file. In Neovim, this text will not be written yet into the file (it will be edited in an unsaved buffer) so type :wa, and it should be resolved (as long as you have dynamicRegistration = true as described here!

    blockcompletions

  • Tag Completions

    tagcompletions

  • Footnote Completions

    footnotecompletions

  • Unresolved File and Heading Completions

    For those who like to reference things before they are written, markdown-oxide has terrific support for unresolved references! It provides completions for unresolved references, provides lsp_references for them, and provides code actions to create files + append headings.

    unresolvedcompletions

  • Callout Completions

    calloutcompletions

  • Nested Callout Completions

    nestedcalloutcompletions

  • Alias Completions

    alias_completions

References

  • File References: Gets references to the file and all headings and blocks in the file

    filereferences

  • Heading References

    headingreferences

  • Tag References: Gets all references to the tag and subtags

    tagreferences

  • Indexed Block References

    indexedblockreferences

  • Footnote References

    footnotereferences

  • Unresolved file and heading references

    unresolvedreferences

Note

I strongly recommend using Lspsaga for references for two reasons. First because this LS sorts references by the date their files were modified and unlike vim.lsp.buf.references() and Telescope lsp_references, Lspsaga finder maintains this sorting order. Second it also allows you to edit the references in place, similar to Logseq

Hover

markdown-oxide provides a preview of the text for an item (if there is any) as well as a snapshot of the backlinks to the item (if applicable). You can hover over both references and referenceables -- hover over headings and links to headings; as well as files and links to files.

In the hover, several backlines to the referenceable are listed, ordered by date modified.

Note

I write most of the content for a note not in the note itself, but in backlinks to the note; I also write in notes at times. Assuming content is both in backlinks and in written text, hover packages text and backlinks together to give a true preview of a referenceable.

Gif of Hover for both references and referenceables

hover

Code Actions

  • Create file for unresolved file link

    codeactionsfile

  • Append heading to file and create the file if necessary

    codeactionsheading

  • Link suggestions (by text match or other)
  • Refactoring: Move headers or selections to a new file
  • Link an unlinked reference
  • Link all unlinked references to a referenceable

Diagnostics

  • Unresolved reference
  • Unlinked reference

Symbols

  • File symbols: Headings and subheadings
  • Workspace headings: everything linkable: files, headings, tags, ... Like a good search feature
  • Lists and indented lists

Rename

  • Rename File

    renamefile

  • Rename Heading

    renameheading

  • Rename Tag

    renametag

Daily Notes

Daily Note completions relative to the current date

  • ...for wikilinks

    dailynoteswiki

  • ...for markdown links

    dailynotesmd

Config

Markdown-Oxide supports several configuration options. All can be specified in a ~/.config/moxide/settings.toml or .moxide.toml file and moxide tries to import some settings (daily notes formatting) from Obsidian directly. Here are the options with the defaults

# Leave blank to try to import from Obsidian Daily Notes
# Formatting from https://docs.rs/chrono/latest/chrono/format/strftime/index.html
dailynote = "%Y-%m-%d" # this is akin to YYYY-MM-DD from Obsidian

# Fuzzy match file headings in completions
heading_completions = true

# Set true if you title your notes by the first heading
# Right now, if true this will cause completing a file link in the markdown style
# to insert the name of the first heading in the display text area
# [](file) -> [first heading of file.md](file)
# If false, [](file) -> [](file) (for example)
title_headings = true

# Show diagnostics for unresolved links; note that even if this is turned off, 
# special semantic tokens will be sent for the unresolved links, allowing you
# to visually identify unresolved links
unresolved_diagnostics = true

semantic_tokens = true

# Resolve tags in code blocks
tags_in_codeblocks = true
# Resolve references in code blocks
references_in_codeblocks = true

Alternatives

I love open-source and all open-source authors!! I also believe healthy competition is good! Markdown-Oxide is competing with some alternatives, and I want to make it the best at its job!!

Here are the alternatives (open source authors are welcome to make PRs to add their projects here!)

  • https://github.com/gw31415/obsidian-lsp: I have been in discussions with the author; The author doesn't have time to maintain the project. Also, I, of course, love the idea, but the current LS doesn't provide many obsidian-specific features yet.
  • https://github.com/WhiskeyJack96/logseqlsp: This is a cool project and a great inspiration for Logseq support (which is upcoming). status: it doesn't seem that it is maintained and it (obviously) does not provide support for all of the obsidian syntax
  • The og https://github.com/artempyanykh/marksman: I used this for a while, but it is not obsidian specific and didn't act well with my vault. Additionally, the block completions in markdown-oxide allow for a fuzzy/grep search of the entire vault to generate the completions; I don't think Markman has any features like this; (this is a feature that Logseq signified for PKM; the concept that anything is linkable is quite powerful)

---The--bottom--line--------------------------------------------------

Listen. I really like Vim motions. I also really love low-latency terminal editing. I very much so also like my Neovim LSP plugins, keymappings, and config. But Wow! I also like using Obsidian and Logseq. Can't I just have it all??? Can't I be whisked away by the flow of Neovim while also experiencing the beauty of Obsidian???? Can't I detail my tasks on the CLI while viewing them in Logseq????? Well, I thought I could; now for us all, there is markdown-oxide (which is still very pre-beta fyi)