Skip to content

njhoffman/project.nvim

Repository files navigation

project.nvim

A Neovim plugin that detects your project root, tracks recent projects, and persists per-project sessions. Combines ideas from ahmedkhalf/project.nvim (LSP / pattern root detection) and coffebar/neovim-project (session integration, neo-tree state persistence).

Features

  • Root detection via LSP workspace folders or parent-directory pattern walk
  • Rich pattern DSL: =name, ^ancestor, >parent, !negation, or glob-as-file-marker
  • Per-project session save/restore through neovim-session-manager
  • Neo-tree expanded-directory state persisted inside the session file
  • History file with per-project metadata (detection method, last-opened time, session count)
  • Telescope extension for switching / deleting / searching projects

Requirements

The plugin will opportunistically use a logger module on the runtimepath (calling require("logger").init("project")), falling back to a vim.notify-based shim when none is available.

Install

With lazy.nvim:

{
  "njhoffman/project.nvim",
  dependencies = {
    "nvim-lua/plenary.nvim",
    "Shatur/neovim-session-manager",
    "echasnovski/mini.icons",
  },
  config = function()
    require("project").setup({
      -- options
    })
  end,
}

Configuration

Defaults (see lua/project/config.lua for the full list):

require("project").setup({
  manual_mode = false,
  detection_methods = { "lsp", "pattern" },
  patterns = { ".project", "courseleaf.cfg", ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile" },
  ignore_lsp = {},
  exclude_dirs = {},
  show_hidden = false,
  silent_chdir = true,
  paths = {
    history = vim.fn.stdpath("data") .. "/project/project_history",
    sessions = vim.fn.stdpath("data") .. "/project/project_sessions",
  },
  last_session_project_on_startup = true,
  last_session_other_on_startup = true,
})

Pattern DSL

Entries in patterns are walked up from the current buffer's directory:

Prefix Meaning Example
(none) A file matching this glob exists Makefile
= Directory name equals =src
^ Directory is descendant of this name ^projects
> Directory is immediate child of this >workspace
! Negation (skip this dir, keep going) !node_modules

List entries can also be tables — all patterns in a table are checked at every level before ascending to the parent, instead of one-pattern-per-walk.

Commands

Command Description
:ProjectWrite Flush in-memory session-project data to the history file
:ProjectLoadRecent [N] Load the Nth most recent project (default: last one)

Lua API

local project = require("project")
project.setup(opts)
project.get_project_root()    -- returns (dir, method_string)
project.get_recent_projects() -- returns (list, meta_table)

Telescope

require("telescope").load_extension("project")
-- pickers:
:Telescope project projects   -- all projects grouped by workspace
:Telescope project recent     -- recent only
:Telescope project nvim       -- filtered to 'nvim' workspace

Testing

make format-check   # stylua --check
make lint           # selene
make test           # plenary-busted headless
make check          # all three

A single spec:

make test-file FILE=tests/project/globtopattern_spec.lua

History-file validation

Each line in the history file must carry these fields:

  • path — exists as a directory at load time
  • method — the detection method string (e.g. pattern Makefile, lsp)
  • method_type — required when method == "lsp" (the LSP client name)
  • num — integer visit counter
  • last — positive Unix timestamp

On load, invalid lines are dropped with a vim.notify WARN describing why, and the on-disk file is rewritten without them. On save, invalid entries are likewise skipped with a warning so malformed data never lands in the file.

Upgrading

If you're moving off the author's personal-config version of this code, the default paths.history / paths.sessions are under stdpath("data")/project/... now (previously .../project_nvim/...). Either move the old files once or point paths.history / paths.sessions at the old location via setup().

Because validation is now strict, existing history entries that pre-date the num / last metadata fields will be dropped with a warning on the first load under 0.3.0+.

The logger dependency is optional: if a logger module is on the runtimepath the plugin will use it, otherwise it falls back to a vim.notify-based shim (see lua/project/utils/logger.lua).

License

MIT. See LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors