1
0
Fork 0

trying to fix embedded git

This commit is contained in:
Luca Bilke 2022-07-04 23:08:05 +02:00
parent 15f8b52459
commit dcb2009f4c
268 changed files with 10605 additions and 0 deletions

32
.local/share/lunarvim/lvim/.gitignore vendored Normal file
View File

@ -0,0 +1,32 @@
plugin/
dein
tags*
.netrwhist
pythonpath.vim
nodepath.vim
autoload/plugged/*
vimspector-config/gadgets/*
paths.vim
session
wiki/
pack/
utils/java/*
lv-config.lua
lua-language-server/
eclipse.jdt.ls/
.language-servers/
.debuggers/
spell/
nv-settings.lua
lv-settings.lua
lua/lv-user/
lua/lv-user-config/
*.tmp
*.temp
*.bak
*.backup
*.old
.luarc.json
.luacheckcache

View File

@ -0,0 +1,42 @@
-- vim: ft=lua tw=80
stds.nvim = {
globals = {
"lvim",
vim = { fields = { "g" } },
"TERMINAL",
"USER",
"C",
"Config",
"WORKSPACE_PATH",
"JAVA_LS_EXECUTABLE",
"MUtils",
"USER_CONFIG_PATH",
os = { fields = { "capture" } },
},
read_globals = {
"jit",
"os",
"vim",
"join_paths",
"get_runtime_dir",
"get_config_dir",
"get_cache_dir",
"get_lvim_base_dir",
"require_clean",
},
}
std = "lua51+nvim"
files["tests/*_spec.lua"].std = "lua51+nvim+busted"
-- Don't report unused self arguments of methods.
self = false
-- Rerun tests only if their modification time changed.
cache = true
ignore = {
"631", -- max_line_length
"212/_.*", -- unused argument, for vars with "_" prefix
}

View File

@ -0,0 +1,34 @@
repos:
- repo: local
hooks:
- id: shfmt
name: shfmt
minimum_pre_commit_version: 2.4.0
language: system
types: [shell]
entry: bash
args: [-c, make lint-sh]
- id: shellcheck
name: shellcheck
language: system
types: [shell]
entry: bash
args: [-c, make style-sh]
- id: stylua
name: StyLua
language: rust
entry: stylua
types: [lua]
args: ["-"]
- id: luacheck
name: luacheck
language: system
entry: luacheck
types: [lua]
args: [.]
- id: commitlint
name: commitlint
language: system
entry: bash
args: [./utils/ci/run_commitlint.sh]
stages: [commit-msg]

View File

@ -0,0 +1,6 @@
column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
no_call_parentheses = true

View File

@ -0,0 +1,283 @@
# Changelog
All notable changes to this project will be documented in this file.
## [unreleased]
### <!-- 1 --> Features
- _(cmp)_ documentation is deprecated in favor of window.documentation ([#2461](https://github.com/lunarvim/lunarvim/pull/2461))
- _(cmp)_ add option to disable friendly-snippets ([#2660](https://github.com/lunarvim/lunarvim/pull/2660))
- _(codelens)_ cursorhold is too much intrusive for codelens ([#2600](https://github.com/lunarvim/lunarvim/pull/2600))
- _(icons)_ make it possible to disable icons ([#2529](https://github.com/lunarvim/lunarvim/pull/2529))
- _(installer)_ ensure correct responses when prompting user ([#2506](https://github.com/lunarvim/lunarvim/pull/2506))
- _(installer)_ add verify-plugins hook ([#2751](https://github.com/lunarvim/lunarvim/pull/2751))
- _(lua-dev)_ use the newer lua-dev branch till folke comes back ([#2538](https://github.com/lunarvim/lunarvim/pull/2538))
- _(neovim)_ neovim 0.8 compatibility ([#2544](https://github.com/lunarvim/lunarvim/pull/2544))
- _(peek)_ make sure max width and height are customizable ([#2492](https://github.com/lunarvim/lunarvim/pull/2492))
- _(plugins)_ add support for packer snapshots ([#2351](https://github.com/lunarvim/lunarvim/pull/2351))
- _(quit)_ make sure to ask before discarding changes ([#2554](https://github.com/lunarvim/lunarvim/pull/2554))
- _(which-key)_ added search command for colour highlights ([#2693](https://github.com/lunarvim/lunarvim/pull/2693))
- lock nvim <0.7 to a specific tag ([#2491](https://github.com/lunarvim/lunarvim/pull/2491))
- gitsigns yadm support ([#2535](https://github.com/lunarvim/lunarvim/pull/2535))
- add cmp-tmux to the list of sources ([#2542](https://github.com/lunarvim/lunarvim/pull/2542))
- prompt when closing modified/term buffers ([#2658](https://github.com/lunarvim/lunarvim/pull/2658))
- fix a couple of issues ([#2750](https://github.com/lunarvim/lunarvim/pull/2750))
### <!-- 2 --> Bugfix
- _(autocmd)_ actually use the format wrapper ([#2560](https://github.com/lunarvim/lunarvim/pull/2560))
- _(autocmds)_ make sure we are using codelens correctly ([#2576](https://github.com/lunarvim/lunarvim/pull/2576))
- _(autocmds)_ disable commentstring_calc on cursor-hold ([#2581](https://github.com/lunarvim/lunarvim/pull/2581))
- _(autocmds)_ toggle format-on-save properly ([#2659](https://github.com/lunarvim/lunarvim/pull/2659))
- _(cmp)_ update nvim-cmp to the latest version ([#2467](https://github.com/lunarvim/lunarvim/pull/2467))
- _(cmp)_ hotfix nvim-cmp version
- _(cmp)_ bring back default keybindings ([#2470](https://github.com/lunarvim/lunarvim/pull/2470))
- _(cmp)_ update nvim-cmp to the latest version ([#2467](https://github.com/lunarvim/lunarvim/pull/2467)) ([#2469](https://github.com/lunarvim/lunarvim/pull/2469))
- _(dap)_ temporarily use dap-buddy dev branch which has older code ([#2567](https://github.com/lunarvim/lunarvim/pull/2567))
- _(dap)_ pause key binding commmand ([#2573](https://github.com/lunarvim/lunarvim/pull/2573))
- _(impatient)_ avoid get_options in fast handler ([#2451](https://github.com/lunarvim/lunarvim/pull/2451))
- _(installer)_ latest and specified release version for neovim have different urls ([#2484](https://github.com/lunarvim/lunarvim/pull/2484))
- _(installer/pwsh)_ fixes some details on installer and uninstaller ([#2404](https://github.com/lunarvim/lunarvim/pull/2404))
- _(log)_ add date to the timestamp of logs ([#2669](https://github.com/lunarvim/lunarvim/pull/2669))
- _(lsp)_ undo stdpath overload to avoid datarace ([#2540](https://github.com/lunarvim/lunarvim/pull/2540))
- _(lualine)_ color theme gaps in some components ([#2465](https://github.com/lunarvim/lunarvim/pull/2465))
- _(lualine)_ unique buf client names ([#2683](https://github.com/lunarvim/lunarvim/pull/2683))
- _(luasnip)_ make sure all snippets are loaded ([#2447](https://github.com/lunarvim/lunarvim/pull/2447))
- _(luasnip)_ only use user snippets if the folder exists ([#2481](https://github.com/lunarvim/lunarvim/pull/2481))
- _(nvimtree)_ escape the dot character in custom filter ([#2493](https://github.com/lunarvim/lunarvim/pull/2493))
- _(nvimtree)_ make sure on_config_done is using the correct require ([#2509](https://github.com/lunarvim/lunarvim/pull/2509))
- _(nvimtree)_ add latest changes from nvimtree ([#2537](https://github.com/lunarvim/lunarvim/pull/2537))
- _(nvimtree)_ update nvim-tree setup ([#2681](https://github.com/lunarvim/lunarvim/pull/2681))
- _(readme)_ update lsp server ignore syntax
- _(readme)_ remove black as linter ([#2510](https://github.com/lunarvim/lunarvim/pull/2510))
- _(telescope)_ set <cr> binding to actions.select_default only ([#2395](https://github.com/lunarvim/lunarvim/pull/2395))
- _(theme)_ make sure the new theme is fully loaded ([#2392](https://github.com/lunarvim/lunarvim/pull/2392))
- _(windows)_ specify required powershell version for the installation script ([#2376](https://github.com/lunarvim/lunarvim/pull/2376))
- update deprecated methods in example configuration for trouble.nvim ([#2416](https://github.com/lunarvim/lunarvim/pull/2416))
- use correct cache path ([#2593](https://github.com/lunarvim/lunarvim/pull/2593))
- load notify's telescope extension properly ([#2586](https://github.com/lunarvim/lunarvim/pull/2586))
- skip calling nvim-tree.setup() more than once ([#2707](https://github.com/lunarvim/lunarvim/pull/2707))
### <!-- 3 --> Refactor
- _(lsp)_ replace deprecated ocamllsp with ocamlls ([#2402](https://github.com/lunarvim/lunarvim/pull/2402))
- _(lsp)_ cleanup servers' override configuration ([#2243](https://github.com/lunarvim/lunarvim/pull/2243))
- _(lsp)_ decouple the installer setup-hook ([#2536](https://github.com/lunarvim/lunarvim/pull/2536))
- _(telescope)_ don't overwrite default cmd to show hidden files
- re-enable packer.sync() in LvimReload ([#2410](https://github.com/lunarvim/lunarvim/pull/2410))
- update impatient ([#2477](https://github.com/lunarvim/lunarvim/pull/2477))
- lock new installations to nvim v0.7+ ([#2526](https://github.com/lunarvim/lunarvim/pull/2526))
- use api-autocmds for lsp functions ([#2549](https://github.com/lunarvim/lunarvim/pull/2549))
- [**breaking**] load the default options once ([#2592](https://github.com/lunarvim/lunarvim/pull/2592))
- remove redundant ftdetects ([#2651](https://github.com/lunarvim/lunarvim/pull/2651))
### <!-- 4 --> Documentation
- _(README)_ change forgotten breaking change in example ([#2377](https://github.com/lunarvim/lunarvim/pull/2377))
- _(windows)_ use alpha in config_win.example.lua ([#2452](https://github.com/lunarvim/lunarvim/pull/2452))
### <!-- 5 --> Revert
- do not run packer.sync() on every reload ([#2548](https://github.com/lunarvim/lunarvim/pull/2548))
## [1.1.3]
### <!-- 1 --> Features
- add alpha.nvim integration (#1906)
### <!-- 2 --> Bugfix
- _(alpha)_ globalstatus after openning files from dashboard (#2366)
- _(bufferline)_ add an additional space before diagnostics (#2367)
- _(lualine)_ conditional theme loading (#2363)
- _(peek)_ make sure popup_options are positive (#2373)
- _(peek)_ print error if lsp is unable to get file contents (#2379)
- _(terminal)_ whichkey -> which-key (#2380)
- _(terminal)_ weird lazygit commit message bug (#2382)
- _(windows)_ use correct validation for the alias (#2371)
- nvim-tree taking half the window on open (#2357)
- correct typo in backup function (#2358)
- automatically set colorscheme (#2370)
### <!-- 3 --> Refactor
- load onedarker theme externally (#2359)
### <!-- 4 --> Documentation
- update demo images on the main readme (#2386)
## [1.1.2]
### <!-- 1 --> Features
- _(installer)_ Use pnpm to install nodejs dependencies(#2279) (#2280)
- _(windows)_ Add custom config_win.example.lua (#2330)
- Add option to automatically answer 'yes' for sh install script (#2306)
- Enable nlsp-settings schemas (#2322)
### <!-- 2 --> Bugfix
- _(nlsp-settings)_ Cross platform issue (#2335)
- _(timeoutlen)_ This has caused way too many issues in the past (#2287)
- Disable the default intro message (#2340)
### <!-- 3 --> Refactor
- _(nvim-tree)_ Update settings structure (#2304)
### <!-- 4 --> Documentation
- _(readme)_ Fix typo in example config (#2333)
## [1.1.1]
### <!-- 2 --> Bugfix
- Add tsx to treesitter ensure_installed list (#2268)
- Correct a path to bufferline module (#2270)
## [1.1.0]
### <!-- 1 --> Features
- _(vue)_ Set volar as default language server instead of vuels (#2230)
- Use schemastore.nvim to provide extended json schema support (#2239)
- Use bufferline instead of barbar (#2254)
- Add a minimal implementation of bbye (#2267)
### <!-- 2 --> Bugfix
- _(autopairs)_ Remove weird tex rules from autopairs (#2206)
- _(diag)_ Show lsp-diag code in open_float (#2180)
- _(installer)_ Usernames can contain @ symbol (#2167)
- _(installer)_ Universal bash (#2241)
- _(logging)_ Disable insane amount of logging inside lvim.log (#2205)
- _(lsp)_ No need to stop clients on LvimReload (#2160)
- _(lsp)_ Use temporary fork of lua-dev (#2187)
- _(lsp)_ Avoid accessing undefined user_data (#2216)
- _(lualine)_ Add space to diff components (#1897)
- _(lualine)_ Compacter size for treesitter icon (#2247)
- _(lualine)_ Use 1-char width symbol for changed (#2246)
- _(which-key)_ The PR has been merged to the original repo (#2172)
- _(zsh)_ Don't set filetype to sh (#2035)
- Added -ScriptBlock to run commands ```install.ps1``` (#2188)
### <!-- 3 --> Refactor
- _(nvim-tree)_ Cleanup and update settings (#2182)
- _(nvim-tree)_ Remove unused code (#2266)
- Remove unused outdated files (#2184)
### <!-- 4 --> Documentation
- _(readme)_ Add powershell installer script for Windows (#2208)
## [1.0.0]
### <!-- 1 --> Features
- _(info)_ Display overridden servers for filetype (#2155)
- _(luadev)_ Better vim api completion (#2043)
- Add lualine config for darkplus
- Last updates before 1.0.0 (#1953)
- Use Telescope's git_files with fallback (#2089)
- Plugin version bump (#2120)
- Lazyload notify's configuration (#1855)
- Plugin version bump (#2131)
### <!-- 2 --> Bugfix
- _(gitsigns)_ Rounded border (#2142)
- _(install)_ Avoid data-races for `on_packer_complete` (#2157)
- _(installer)_ Backup linked files with rsync (#2081)
- _(installer)_ Check if npm-prefix is writable (#2091)
- _(installer)_ More robust yarn validation (#2113)
- _(lsp)_ Set the handlers opts for v0.6 as well (#2109)
- _(lsp)_ Formatter now use new null-ls api function (#2135)
- _(lsp)_ Formatter now use new null-ls api function (#2135)
- _(null-ls)_ Avoid sending invalid opts.args (#2154)
- _(which-key)_ Temporary solution for which-key (#2150)
- Remove autopairs cmp completion (#2083)
- Remove "error" message from git tag (#2141)
### <!-- 3 --> Refactor
- _(bootstrap)_ More robust git module (#2127)
- _(info)_ Use new null-ls api for sources (#2125)
- _(install.sh)_ Fix typo in node error message (#2107)
- _(null-ls)_ Allow passing full list of options for sources (#2137)
- _(settings)_ Add headless-mode settings (#2134)
- _(term)_ Leave the first few ids unassigned (#2156)
- _(test)_ Cleanup test utilities (#2132)
- Deprecate lvim.lang.FOO (#1913) (#1914)
- Remove unused old language configs (#2094)
- Uplift neovim's minimum version requirement to 0.6.0 (#2093)
- Avoid running ts.setup in headless (#2119)
- More consistent autocmds (#2133)
- Use a static lvim binary template (#1444)
## [1.0.0-rc]
### <!-- 1 --> Features
- _(installer)_ Nicer rsync output (#2067)
- _(terminal)_ Lazygit can now be toggled (#2039)
- Add lualine config for darkplus
- Last updates before 1.0.0 (#1953)
- Support new null-ls (#1955)
- Empty for empty buffers instead of Buffer <#>
- Improved LSP grouping in lualine
- Decrease hide in width limit for lualine
- Add support for fsharp (#2021)
- Add some messages in uninstall.sh (#1945)
- Null-ls code_actions interface (#2008)
- Full compatibility with neovim v0.6 (#2037)
- Multiple enhancements to lvim-reload (#2054)
- Bump plugin versions (#2064)
- Update lsp-installer and lspconfig hashes to enable solidity_ls language server (#2072)
### <!-- 2 --> Bugfix
- _(autopairs)_ Add missing configuration entries (#2030)
- _(bootstrap)_ Remove hard-coded spellfile option (#2061)
- _(cmp)_ Revert broken sequential loading (#2002)
- _(installer)_ Better handling of existing files (#2066)
- _(lsp)_ Avoid installing an overridden server (#1981)
- _(lsp)_ Prevent repeated setup call (#2048)
- _(lsp)_ Correct client_id parsing in lvim-info (#2071)
- _(lsp)_ Allow overriding servers with custom providers (#2070)
- _(lualine)_ Change `fg` of section `a` in onedarker (#1909)
- _(null-ls)_ Allow the same linter and formatter (#1968)
- _(nvimtree)_ Update settings (#2001)
- _(nvimtree)_ Restore default mappings + make them customizable (#2007)
- _(nvimtree)_ Handle paths containing spaces (#2027)
- _(plugins)_ Typo of pin commit of `treesitter` (#2046)
- _(terminal)_ Allow disabling the open binding for toggleterm
- _(windows)_ Autocmd requires forward slashes (#1967)
- _(windows)_ Remove redundant `resolve` call (#1974)
- Bump nvim-tree version
- Formatting
- Remove duplicate lint messages
- Allow LunarVim changelog to work outside the lvim directory (#1952)
- Use an indepdent shadafile from neovim (#1910)
- Packersync issue when you have large number of plugins (#1922)
- No idea why this breaks barbar
- Lsp root can get very annoying when working with multiple languages. User is still able to turn it on.
- Update jdtls script
- Correct order for cmp's setup (#1999)
- Dont close if next char is a close pair and no pairs in same line (#2017)
- More accessible changelog (#2019)
- Better default, ignore `.git` in `live_grep` (#2020)
- No restart required when changing colorscheme (#2026)
- No longer treat lazygit missing as an error (#2051)
### <!-- 3 --> Refactor
- Deprecate lvim.lang.FOO (#1913) (#1914)
- More configurable format-on-save (#1937)
- Load the default keymaps once (#1965)
<!-- generated by git-cliff -->

View File

@ -0,0 +1,115 @@
# Contributing to LunarVim
Welcome to the LunarVim contributing guide. We are excited about the prospect of you joining our [community](https://github.com/lunarvim/LunarVim/graphs/contributors)!
There are many opportunities to contributing to the project at any level. Every contribution is highly valued and no contribution is too small.
You do not need to write code to contribute to this project. Documentation, demos, and feature design advancements are a key part of this project's growth.
One of the best ways to begin contributing in a meaningful way is by helping find bugs and filing issues for them.
## Getting Started
1. Follow the [Installation](https://www.lunarvim.org/01-installing.html) guide
2. Link your fork with the repository `git remote add upstream https://github.com/lunarvim/LunarVim.git`, or use `gh fork`
3. That's it! You can now `git fetch upstream` and `git rebase [-i] upstream/rolling` to update your branches with the latest contributions.
<br />
## Setting up development tools
### For editing Lua files
1. Formatter: [stylua](https://github.com/johnnymorganz/stylua#installation).
2. Linter: [luacheck](https://github.com/luarocks/luacheck).
### For editing shell scripts
1. Formatter: [shfmt](https://github.com/mvdan/sh#shfmt).
2. Linter: [shellcheck](https://github.com/koalaman/shellcheck).
### (Optional)
Install [pre-commit](https://github.com/pre-commit/pre-commit) which will run all linters and formatters for you as a pre-commit-hook.
<br />
## Code Conventions
All lua code is formatted with [Stylua](https://github.com/JohnnyMorganz/StyLua).
```bash
# configurations are already stored in .stylua.toml
stylua -c .
```
All shell code is formatted according to [Google Shell Style Guide](https://google.github.io/styleguide/shellguide.html)
* use two spaces instead of tabs
```bash
shfmt -i 2 -ci -bn -l -d .
```
<br />
## Pull Requests (PRs)
- To avoid duplicate work, create a draft pull request.
- Your PR must pass all the [automated-ci-tests](https://github.com/neovim/neovim/actions).
- Use a [git-feature-branch](https://www.atlassian.com/git/tutorials/comparing-workflows) instead of the master/rolling branch.
- Use a [rebase-workflow](http://git-scm.com/book/en/v2/Git-Branching-Rebasing).
### Commit Messages
* Commit header is limited to 72 characters.
* Commit body and footer is limited to 100 characters per line.
**Commit header format:**
```
<type>(<scope>?): <summary>
│ │ │
│ │ └─> Present tense. 'add something...'(O) vs 'added something...'(X)
│ │ Imperative mood. 'move cursor to...'(O) vs 'moves cursor to...'(X)
│ │ Not capitalized.
│ │ No period at the end.
│ │
│ └─> Commit Scope is optional, but strongly recommended.
│ Use lower case.
│ 'plugin', 'file', or 'directory' name is suggested, but not limited.
└─> Commit Type: build|ci|docs|feat|fix|perf|refactor|test
```
##### Commit Type Guideline
* **build**: changes that affect the build system or external dependencies (example scopes: npm, pip, rg)
* **ci**: changes to CI configuration files and scripts (example scopes: format, lint, issue_templates)
* **docs**: changes to the documentation only
* **feat**: new feature for the user
* **fix**: bug fix
* **perf**: performance improvement
* **refactor**: code change that neither fixes a bug nor adds a feature
* **test**: adding missing tests or correcting existing tests
* **chore**: all the rest, including version bump for plugins
**Real world examples:**
```
feat(quickfix): add 'q' binding to quit quickfix window when focused
```
```
fix(installer): add missing "HOME" variable
```
### Branch Naming
Name your branches meaningfully.
ex)
```(feature|bugfix|hotfix)/what-my-pr-does```
<br />
## Communication
Members of the community have multiple ways to collaborate on the project.
We encourage you to join the community:
- [Discord server](https://discord.gg/Xb9B4Ny)
- [Matrix server](https://matrix.to/#/#atmachine-neovim:matrix.org)

View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -0,0 +1,42 @@
SHELL := /usr/bin/env bash
install:
@echo starting LunarVim installer
bash ./utils/installer/install.sh
install-bin:
@echo starting LunarVim bin-installer
bash ./utils/installer/install_bin.sh
install-neovim-binary:
@echo installing Neovim from github releases
bash ./utils/installer/install-neovim-from-release
uninstall:
@echo starting LunarVim uninstaller
bash ./utils/installer/uninstall.sh
generate_new_lockfile:
@echo generating core-plugins latest lockfile
bash ./utils/ci/generate_new_lockfile.sh
lint: lint-lua lint-sh
lint-lua:
luacheck *.lua lua/* tests/*
lint-sh:
shfmt -f . | grep -v jdtls | xargs shellcheck
style: style-lua style-sh
style-lua:
stylua --config-path .stylua.toml --check .
style-sh:
shfmt -f . | grep -v jdtls | xargs shfmt -i 2 -ci -bn -l -d
test:
bash ./utils/ci/run_test.sh "$(TEST)"
.PHONY: install install-neovim-binary uninstall lint style test

View File

@ -0,0 +1,167 @@
![lunarvim_logo_dark](https://user-images.githubusercontent.com/59826753/159940098-54284f26-f1da-4481-8b03-1deb34c57533.png)
<div align="center"><p>
<a href="https://github.com/lunarvim/LunarVim/releases/latest">
<img alt="Latest release" src="https://img.shields.io/github/v/release/lunarvim/LunarVim" />
</a>
<a href="https://github.com/lunarvim/LunarVim/pulse">
<img alt="Last commit" src="https://img.shields.io/github/last-commit/lunarvim/LunarVim"/>
</a>
<a href="https://github.com/lunarvim/LunarVim/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/lunarvim/lunarvim?style=flat-square&logo=GNU&label=License" alt="License"
/>
<a href="https://patreon.com/chrisatmachine" title="Donate to this project using Patreon">
<img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" />
</a>
<a href="https://twitter.com/intent/follow?screen_name=chrisatmachine">
<img src="https://img.shields.io/twitter/follow/chrisatmachine?style=social&logo=twitter" alt="follow on Twitter">
</a>
</p>
</div>
## Showcase
![intro1](https://user-images.githubusercontent.com/59826753/159939936-3a9a8e94-05ea-48fa-8c46-69378276451b.png)
![info](https://user-images.githubusercontent.com/59826753/159939984-ac0190d7-a3fb-46c0-95ca-a6fec626bbac.png)
![demo1](https://user-images.githubusercontent.com/59826753/159940004-84975294-5703-4bf1-aa98-2cc97cb38d96.png)
![demo2](https://user-images.githubusercontent.com/59826753/159940040-375a0a28-4c81-4fdf-80f2-62853edf9b4f.png)
## Install In One Command!
Make sure you have the release version of Neovim (0.7+).
### Linux:
```bash
bash <(curl -s https://raw.githubusercontent.com/lunarvim/lunarvim/master/utils/installer/install.sh)
```
To run the install script without any interaction you can pass the `-y` flag to automatically install all dependencies and have no prompts. This is particularly useful in automated installations.
The same way, you can use `--no-install-dependencies` to skip the dependency installation.
### Windows (Powershell 7+):
Powershell v7+ is required for this script. For instructions on how to install, [click here.](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.2)
```powershell
Invoke-WebRequest https://raw.githubusercontent.com/LunarVim/LunarVim/master/utils/installer/install.ps1 -UseBasicParsing | Invoke-Expression
```
## Automatic LSP support
By default, most supported language servers will get automatically installed once you open the supported file-type, e.g, opening a Python file for the first time will install `Pyright` and configure it automatically for you.
## Configuration file
To install plugins configure LunarVim use the `config.lua` located here: `~/.config/lvim/config.lua`
Example:
```lua
-- general
lvim.format_on_save = true
lvim.colorscheme = "onedarker"
lvim.leader = "space"
-- add your own keymapping
lvim.keys.normal_mode["<C-s>"] = ":w<cr>"
-- unmap a default keymapping
-- lvim.keys.normal_mode["<C-Up>"] = ""
-- edit a default keymapping
-- lvim.keys.normal_mode["<C-q>"] = ":q<cr>"
-- set keymap with custom opts
-- lvim.keys.insert_mode["po"] = {'<ESC>', { noremap = true }}
-- Use which-key to add extra bindings with the leader-key prefix
-- lvim.builtin.which_key.mappings["P"] = { "<cmd>Telescope projects<CR>", "Projects" }
-- Configure builtin plugins
lvim.builtin.alpha.active = true
lvim.builtin.notify.active = true
lvim.builtin.terminal.active = true
-- Treesitter parsers change this to a table of the languages you want i.e. {"java", "python", javascript}
lvim.builtin.treesitter.ensure_installed = "maintained"
lvim.builtin.treesitter.ignore_install = { "haskell" }
-- Disable virtual text
lvim.lsp.diagnostics.virtual_text = false
-- Select which servers should be configured manually. Requires `:LvimCacheReset` to take effect.
-- See the full default list `:lua print(vim.inspect(lvim.lsp.override))`
vim.list_extend(lvim.lsp.automatic_configuration.skipped_servers, { "pyright" })
-- set a formatter, this will override the language server formatting capabilities (if it exists)
local formatters = require "lvim.lsp.null-ls.formatters"
formatters.setup {
{ command = "black" },
{
command = "prettier",
---@usage specify which filetypes to enable. By default a providers will attach to all the filetypes it supports.
filetypes = { "typescript", "typescriptreact" },
},
}
-- set additional linters
local linters = require "lvim.lsp.null-ls.linters"
linters.setup {
{
command = "eslint_d",
---@usage specify which filetypes to enable. By default a providers will attach to all the filetypes it supports.
filetypes = { "javascript", "javascriptreact" },
},
}
-- Additional Plugins
lvim.plugins = {
{"lunarvim/colorschemes"},
{"folke/tokyonight.nvim"}, {
"ray-x/lsp_signature.nvim",
config = function() require"lsp_signature".on_attach() end,
event = "BufRead"
}
}
```
## Updating LunarVim
- inside LunarVim `:LvimUpdate`
- from the command-line `lvim +LvimUpdate +q`
### Update the plugins
- inside LunarVim `:PackerUpdate`
## Breaking changes
- `lvim.lang.FOO` is no longer supported. Refer to <https://www.lunarvim.org/languages> for up-to-date instructions.
- `lvim.lsp.popup_border` has been deprecated in favor of `lvim.lsp.float.border` and `lvim.lsp.diagnostics.float.border`.
- `lvim.builtin.dashboard` has been replaced with `lvim.builtin.alpha`, see <https://github.com/LunarVim/LunarVim/pull/1906>
## Resources
- [Documentation](https://www.lunarvim.org)
- [YouTube](https://www.youtube.com/channel/UCS97tchJDq17Qms3cux8wcA)
- [Discord](https://discord.gg/Xb9B4Ny)
- [Twitter](https://twitter.com/chrisatmachine)
## Testimonials
> "I have the processing power of a potato with 4 gb of ram and LunarVim runs perfectly."
>
> - @juanCortelezzi, LunarVim user.
> "My minimal config with a good amount less code than LunarVim loads 40ms slower. Time to switch."
>
> - @mvllow, Potential LunarVim user.
<div align="center" id="madewithlua">
[![Lua](https://img.shields.io/badge/Made%20with%20Lua-blue.svg?style=for-the-badge&logo=lua)](#madewithlua)
</div>

View File

@ -0,0 +1,3 @@
vim.cmd [[
au BufRead,BufNewFile tsconfig.json set filetype=jsonc
]]

View File

@ -0,0 +1 @@
vim.cmd [[ au BufRead,BufNewFile *.tex set filetype=tex ]]

View File

@ -0,0 +1,3 @@
vim.cmd [[
au BufRead,BufNewFile *.zir set filetype=zir
]]

View File

@ -0,0 +1,21 @@
local init_path = debug.getinfo(1, "S").source:sub(2)
local base_dir = init_path:match("(.*[/\\])"):sub(1, -2)
if not vim.tbl_contains(vim.opt.rtp:get(), base_dir) then
vim.opt.rtp:append(base_dir)
end
require("lvim.bootstrap"):init(base_dir)
require("lvim.config"):load()
local plugins = require "lvim.plugins"
require("lvim.plugin-loader").load { plugins, lvim.plugins }
local Log = require "lvim.core.log"
Log:debug "Starting LunarVim"
local commands = require "lvim.core.commands"
commands.load(commands.defaults)
require("lvim.lsp").setup()

View File

@ -0,0 +1,130 @@
local M = {}
if vim.fn.has "nvim-0.7" ~= 1 then
vim.notify("Please upgrade your Neovim base installation. Lunarvim requires v0.7+", vim.log.levels.WARN)
vim.wait(5000, function()
return false
end)
vim.cmd "cquit"
end
local uv = vim.loop
local path_sep = uv.os_uname().version:match "Windows" and "\\" or "/"
local in_headless = #vim.api.nvim_list_uis() == 0
---Join path segments that were passed as input
---@return string
function _G.join_paths(...)
local result = table.concat({ ... }, path_sep)
return result
end
---Require a module in protected mode without relying on its cached value
---@param module string
---@return any
function _G.require_clean(module)
package.loaded[module] = nil
_G[module] = nil
local _, requested = pcall(require, module)
return requested
end
---Get the full path to `$LUNARVIM_RUNTIME_DIR`
---@return string
function _G.get_runtime_dir()
local lvim_runtime_dir = os.getenv "LUNARVIM_RUNTIME_DIR"
if not lvim_runtime_dir then
-- when nvim is used directly
return vim.call("stdpath", "data")
end
return lvim_runtime_dir
end
---Get the full path to `$LUNARVIM_CONFIG_DIR`
---@return string
function _G.get_config_dir()
local lvim_config_dir = os.getenv "LUNARVIM_CONFIG_DIR"
if not lvim_config_dir then
return vim.call("stdpath", "config")
end
return lvim_config_dir
end
---Get the full path to `$LUNARVIM_CACHE_DIR`
---@return string
function _G.get_cache_dir()
local lvim_cache_dir = os.getenv "LUNARVIM_CACHE_DIR"
if not lvim_cache_dir then
return vim.call("stdpath", "cache")
end
return lvim_cache_dir
end
---Initialize the `&runtimepath` variables and prepare for startup
---@return table
function M:init(base_dir)
self.runtime_dir = get_runtime_dir()
self.config_dir = get_config_dir()
self.cache_dir = get_cache_dir()
self.pack_dir = join_paths(self.runtime_dir, "site", "pack")
self.packer_install_dir = join_paths(self.runtime_dir, "site", "pack", "packer", "start", "packer.nvim")
self.packer_cache_path = join_paths(self.config_dir, "plugin", "packer_compiled.lua")
---@meta overridden to use LUNARVIM_CACHE_DIR instead, since a lot of plugins call this function interally
---NOTE: changes to "data" are currently unstable, see #2507
vim.fn.stdpath = function(what)
if what == "cache" then
return _G.get_cache_dir()
end
return vim.call("stdpath", what)
end
---Get the full path to LunarVim's base directory
---@return string
function _G.get_lvim_base_dir()
return base_dir
end
if os.getenv "LUNARVIM_RUNTIME_DIR" then
-- vim.opt.rtp:append(os.getenv "LUNARVIM_RUNTIME_DIR" .. path_sep .. "lvim")
vim.opt.rtp:remove(join_paths(vim.call("stdpath", "data"), "site"))
vim.opt.rtp:remove(join_paths(vim.call("stdpath", "data"), "site", "after"))
vim.opt.rtp:prepend(join_paths(self.runtime_dir, "site"))
vim.opt.rtp:append(join_paths(self.runtime_dir, "site", "after"))
vim.opt.rtp:remove(vim.call("stdpath", "config"))
vim.opt.rtp:remove(join_paths(vim.call("stdpath", "config"), "after"))
vim.opt.rtp:prepend(self.config_dir)
vim.opt.rtp:append(join_paths(self.config_dir, "after"))
-- TODO: we need something like this: vim.opt.packpath = vim.opt.rtp
vim.cmd [[let &packpath = &runtimepath]]
end
-- FIXME: currently unreliable in unit-tests
if not in_headless then
_G.PLENARY_DEBUG = false
require "lvim.impatient"
end
require("lvim.config"):init()
require("lvim.plugin-loader").init {
package_root = self.pack_dir,
install_path = self.packer_install_dir,
}
return self
end
---Update LunarVim
---pulls the latest changes from github and, resets the startup cache
function M:update()
require_clean("lvim.utils.hooks").run_pre_update()
local ret = require_clean("lvim.utils.git").update_base_lvim()
if ret then
require_clean("lvim.utils.hooks").run_post_update()
end
end
return M

View File

@ -0,0 +1,42 @@
return {
leader = "space",
colorscheme = "onedarker",
transparent_window = false,
format_on_save = {
---@usage pattern string pattern used for the autocommand (Default: '*')
pattern = "*",
---@usage timeout number timeout in ms for the format request (Default: 1000)
timeout = 1000,
---@usage filter func to select client
filter = require("lvim.lsp.handlers").format_filter,
},
keys = {},
use_icons = true,
builtin = {},
plugins = {
-- use config.lua for this not put here
},
autocommands = {},
lang = {},
log = {
---@usage can be { "trace", "debug", "info", "warn", "error", "fatal" },
level = "warn",
viewer = {
---@usage this will fallback on "less +F" if not found
cmd = "lnav",
layout_config = {
---@usage direction = 'vertical' | 'horizontal' | 'window' | 'float',
direction = "horizontal",
open_mapping = "",
size = 40,
float_opts = {},
},
},
-- currently disabled due to instabilities
override_notify = false,
},
}

View File

@ -0,0 +1,149 @@
local utils = require "lvim.utils"
local Log = require "lvim.core.log"
local M = {}
local user_config_dir = get_config_dir()
local user_config_file = utils.join_paths(user_config_dir, "config.lua")
---Get the full path to the user configuration file
---@return string
function M:get_user_config_path()
return user_config_file
end
--- Initialize lvim default configuration and variables
function M:init()
lvim = vim.deepcopy(require "lvim.config.defaults")
require("lvim.keymappings").load_defaults()
local builtins = require "lvim.core.builtins"
builtins.config { user_config_file = user_config_file }
local settings = require "lvim.config.settings"
settings.load_defaults()
local autocmds = require "lvim.core.autocmds"
autocmds.load_defaults()
local lvim_lsp_config = require "lvim.lsp.config"
lvim.lsp = vim.deepcopy(lvim_lsp_config)
---@deprecated replaced with lvim.builtin.alpha
lvim.builtin.dashboard = {
active = false,
on_config_done = nil,
search_handler = "",
disable_at_vim_enter = 0,
session_directory = "",
custom_header = {},
custom_section = {},
footer = {},
}
lvim.builtin.luasnip = {
sources = {
friendly_snippets = true,
},
}
end
local function handle_deprecated_settings()
local function deprecation_notice(setting, new_setting)
local in_headless = #vim.api.nvim_list_uis() == 0
if in_headless then
return
end
local msg = string.format(
"Deprecation notice: [%s] setting is no longer supported. %s",
setting,
new_setting or "See https://github.com/LunarVim/LunarVim#breaking-changes"
)
vim.schedule(function()
vim.notify_once(msg, vim.log.levels.WARN)
end)
end
---lvim.lang.FOO.lsp
for lang, entry in pairs(lvim.lang) do
local deprecated_config = entry.formatters or entry.linters or {}
if not vim.tbl_isempty(deprecated_config) then
deprecation_notice(string.format("lvim.lang.%s", lang))
end
end
-- lvim.lsp.override
if lvim.lsp.override and not vim.tbl_isempty(lvim.lsp.override) then
deprecation_notice("lvim.lsp.override", "Use `lvim.lsp.automatic_configuration.skipped_servers` instead")
vim.tbl_map(function(c)
if not vim.tbl_contains(lvim.lsp.automatic_configuration.skipped_servers, c) then
table.insert(lvim.lsp.automatic_configuration.skipped_servers, c)
end
end, lvim.lsp.override)
end
-- lvim.lsp.popup_border
if vim.tbl_contains(vim.tbl_keys(lvim.lsp), "popup_border") then
deprecation_notice "lvim.lsp.popup_border"
end
-- dashboard.nvim
if lvim.builtin.dashboard.active then
deprecation_notice("lvim.builtin.dashboard", "Use `lvim.builtin.alpha` instead. See LunarVim#1906")
end
if lvim.autocommands.custom_groups then
deprecation_notice(
"lvim.autocommands.custom_groups",
"Use vim.api.nvim_create_autocmd instead or check LunarVim#2592 to learn about the new syntax"
)
end
end
--- Override the configuration with a user provided one
-- @param config_path The path to the configuration overrides
function M:load(config_path)
local autocmds = require "lvim.core.autocmds"
config_path = config_path or self:get_user_config_path()
local ok, err = pcall(dofile, config_path)
if not ok then
if utils.is_file(user_config_file) then
Log:warn("Invalid configuration: " .. err)
else
vim.notify_once(string.format("Unable to find configuration file [%s]", config_path), vim.log.levels.WARN)
end
end
handle_deprecated_settings()
autocmds.define_autocmds(lvim.autocommands)
vim.g.mapleader = (lvim.leader == "space" and " ") or lvim.leader
require("lvim.keymappings").load(lvim.keys)
if lvim.transparent_window then
autocmds.enable_transparent_mode()
end
end
--- Override the configuration with a user provided one
-- @param config_path The path to the configuration overrides
function M:reload()
vim.schedule(function()
require_clean("lvim.utils.hooks").run_pre_reload()
M:load()
require("lvim.core.autocmds").configure_format_on_save()
local plugins = require "lvim.plugins"
local plugin_loader = require "lvim.plugin-loader"
plugin_loader.reload { plugins, lvim.plugins }
require_clean("lvim.utils.hooks").run_post_reload()
end)
end
return M

View File

@ -0,0 +1,84 @@
local M = {}
M.load_default_options = function()
local utils = require "lvim.utils"
local join_paths = utils.join_paths
local undodir = join_paths(get_cache_dir(), "undo")
if not utils.is_directory(undodir) then
vim.fn.mkdir(undodir, "p")
end
local default_options = {
backup = false, -- creates a backup file
clipboard = "unnamedplus", -- allows neovim to access the system clipboard
cmdheight = 2, -- more space in the neovim command line for displaying messages
colorcolumn = "99999", -- fixes indentline for now
completeopt = { "menuone", "noselect" },
conceallevel = 0, -- so that `` is visible in markdown files
fileencoding = "utf-8", -- the encoding written to a file
foldmethod = "manual", -- folding, set to "expr" for treesitter based folding
foldexpr = "", -- set to "nvim_treesitter#foldexpr()" for treesitter based folding
guifont = "monospace:h17", -- the font used in graphical neovim applications
hidden = true, -- required to keep multiple buffers and open multiple buffers
hlsearch = true, -- highlight all matches on previous search pattern
ignorecase = true, -- ignore case in search patterns
mouse = "a", -- allow the mouse to be used in neovim
pumheight = 10, -- pop up menu height
showmode = false, -- we don't need to see things like -- INSERT -- anymore
showtabline = 2, -- always show tabs
smartcase = true, -- smart case
smartindent = true, -- make indenting smarter again
splitbelow = true, -- force all horizontal splits to go below current window
splitright = true, -- force all vertical splits to go to the right of current window
swapfile = false, -- creates a swapfile
termguicolors = true, -- set term gui colors (most terminals support this)
timeoutlen = 250, -- time to wait for a mapped sequence to complete (in milliseconds)
title = true, -- set the title of window to the value of the titlestring
-- opt.titlestring = "%<%F%=%l/%L - nvim" -- what the title of the window will be set to
undodir = undodir, -- set an undo directory
undofile = true, -- enable persistent undo
updatetime = 300, -- faster completion
writebackup = false, -- if a file is being edited by another program (or was written to file while editing with another program), it is not allowed to be edited
expandtab = true, -- convert tabs to spaces
shiftwidth = 2, -- the number of spaces inserted for each indentation
tabstop = 2, -- insert 2 spaces for a tab
cursorline = true, -- highlight the current line
number = true, -- set numbered lines
relativenumber = false, -- set relative numbered lines
numberwidth = 4, -- set number column width to 2 {default 4}
signcolumn = "yes", -- always show the sign column, otherwise it would shift the text each time
wrap = false, -- display lines as one long line
shadafile = join_paths(get_cache_dir(), "lvim.shada"),
scrolloff = 8, -- minimal number of screen lines to keep above and below the cursor.
sidescrolloff = 8, -- minimal number of screen lines to keep left and right of the cursor.
}
--- SETTINGS ---
vim.opt.shortmess:append "c" -- don't show redundant messages from ins-completion-menu
vim.opt.shortmess:append "I" -- don't show the default intro message
vim.opt.whichwrap:append "<,>,[,],h,l"
for k, v in pairs(default_options) do
vim.opt[k] = v
end
end
M.load_headless_options = function()
vim.opt.shortmess = "" -- try to prevent echom from cutting messages off or prompting
vim.opt.more = false -- don't pause listing when screen is filled
vim.opt.cmdheight = 9999 -- helps avoiding |hit-enter| prompts.
vim.opt.columns = 9999 -- set the widest screen possible
vim.opt.swapfile = false -- don't use a swap file
end
M.load_defaults = function()
if #vim.api.nvim_list_uis() == 0 then
M.load_headless_options()
return
end
M.load_default_options()
end
return M

View File

@ -0,0 +1,81 @@
local M = {}
function M.config()
local lvim_dashboard = require "lvim.core.alpha.dashboard"
local lvim_startify = require "lvim.core.alpha.startify"
lvim.builtin.alpha = {
dashboard = { config = {}, section = lvim_dashboard.get_sections() },
startify = { config = {}, section = lvim_startify.get_sections() },
active = true,
mode = "dashboard",
}
end
local function resolve_buttons(theme_name, entries)
local selected_theme = require("alpha.themes." .. theme_name)
local val = {}
for _, entry in pairs(entries) do
local on_press = function()
local sc_ = entry[1]:gsub("%s", ""):gsub("SPC", "<leader>")
local key = vim.api.nvim_replace_termcodes(sc_, true, false, true)
vim.api.nvim_feedkeys(key, "normal", false)
end
local button_element = selected_theme.button(entry[1], entry[2], entry[3])
-- this became necessary after recent changes in alpha.nvim (06ade3a20ca9e79a7038b98d05a23d7b6c016174)
button_element.on_press = on_press
table.insert(val, button_element)
end
return val
end
local function resolve_config(theme_name)
local selected_theme = require("alpha.themes." .. theme_name)
local resolved_section = selected_theme.section
local section = lvim.builtin.alpha[theme_name].section
for name, el in pairs(section) do
for k, v in pairs(el) do
if name:match "buttons" and k == "entries" then
resolved_section[name].val = resolve_buttons(theme_name, v)
elseif v then
resolved_section[name][k] = v
end
end
end
return selected_theme.config
end
local function configure_additional_autocmds()
local group = "_dashboard_settings"
vim.api.nvim_create_augroup(group, {})
vim.api.nvim_create_autocmd("FileType", {
group = group,
pattern = "alpha",
command = "set showtabline=0 | autocmd BufLeave <buffer> set showtabline=" .. vim.opt.showtabline._value,
})
if not lvim.builtin.lualine.options.globalstatus then
-- https://github.com/goolord/alpha-nvim/issues/42
vim.api.nvim_create_autocmd("FileType", {
group = group,
pattern = "alpha",
command = "set laststatus=0 | autocmd BufUnload <buffer> set laststatus=" .. vim.opt.laststatus._value,
})
end
end
function M.setup()
local alpha = require "alpha"
local mode = lvim.builtin.alpha.mode
local config = lvim.builtin.alpha[mode].config
-- this makes it easier to use a completely custom configuration
if vim.tbl_isempty(config) then
config = resolve_config(mode)
end
alpha.setup(config)
configure_additional_autocmds()
end
return M

View File

@ -0,0 +1,75 @@
local M = {}
function M.get_sections()
local header = {
type = "text",
val = {
"",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣶⣿⣿⣿⣷⣶⣤⡀⠀⠀⠀⠀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠀⠀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀",
"⠀⣀⣴⣶⣶⣶⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀",
"⣰⣿⣿⠿⠛⠿⢿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀",
"⣿⣿⡇⠀⠀⠀⠀⠈⠛⢿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀",
"⠹⣿⣧⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⡿⠛⠉⠀⢀⣿⣿⣿⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀",
"⠀⠙⢿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣷⣶⣶⣶⣶⣶⣿⣿⣿⣿⣿⣿⣿⣿⣷⣤⣤⣶⣿⣿⣿⣿⣿⡿⠟⠁⠀⠀⠀⠀⠀⠀",
"⠀⠀⠀⠉⠻⠷⡄⠀⠀⠀⠀⠀⠀⠀⠈⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⠉⠀⢀⣠⣤⣤⣄⡀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠋⠁⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣷⡀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⣄⡀⠀⠀⠀⠀⣿⠟⠉⠉⠙⢿⣿⣿⣷",
"⠀⠀⠀⣀⣠⣤⣤⣤⣶⣶⣶⣤⣤⠀⣴⣿⣿⣿⡿⠟⠛⠛⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠉⠀⠀⠀⢀⣼⣿⣿⡿",
"⠀⠀⠀⠈⠉⠉⠉⠉⠉⠉⠛⠻⠏⣼⣿⣿⡿⣋⣀⣤⣤⣴⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣄⣀⣠⣴⣾⣿⣿⡿⠁",
"⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⡿⠋⠘⠿⠟⠛⠛⢻⣿⣿⣿⠋⠁⠈⠉⢿⣿⣿⣧⠀⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠉⠀⠀",
"⠙⣷⣤⣀⠀⠀⠀⢀⣀⣤⣶⣿⡿⠋⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⡟⠀⠀⠀⢠⣿⣿⣿⡟⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀",
"⠀⠈⠛⠿⢿⣿⣿⣿⠿⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⡀⠀⢠⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⣷⣶⣶⣶⣶⣦⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣙⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⢶⣦⣤⣶⣾⣿⣿⡶⠈⠉⠛⠿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀",
"⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣤⣶⡿⠿⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀",
},
opts = {
position = "center",
hl = "Label",
},
}
local text = require "lvim.interface.text"
local lvim_version = require("lvim.utils.git").get_lvim_version()
local footer = {
type = "text",
val = text.align_center({ width = 0 }, {
"",
"lunarvim.org",
lvim_version,
}, 0.5),
opts = {
position = "center",
hl = "Number",
},
}
local buttons = {
entries = {
{ "SPC f", " Find File", "<CMD>Telescope find_files<CR>" },
{ "SPC n", " New File", "<CMD>ene!<CR>" },
{ "SPC P", " Recent Projects ", "<CMD>Telescope projects<CR>" },
{ "SPC s r", " Recently Used Files", "<CMD>Telescope oldfiles<CR>" },
{ "SPC s t", " Find Word", "<CMD>Telescope live_grep<CR>" },
{
"SPC L c",
" Configuration",
"<CMD>edit " .. require("lvim.config"):get_user_config_path() .. " <CR>",
},
},
}
return {
header = header,
buttons = buttons,
footer = footer,
}
end
return M

View File

@ -0,0 +1,48 @@
local M = {}
function M.get_sections()
local header = {
type = "text",
val = {
[[ __ _ ___ ]],
[[ / / __ ______ ____ _____| | / (_)___ ___ ]],
[[ / / / / / / __ \/ __ `/ ___/ | / / / __ `__ \]],
[[ / /___/ /_/ / / / / /_/ / / | |/ / / / / / / /]],
[[/_____/\__,_/_/ /_/\__,_/_/ |___/_/_/ /_/ /_/ ]],
},
opts = {
hl = "Label",
shrink_margin = false,
-- wrap = "overflow";
},
}
local top_buttons = {
entries = {
{ "e", " New File", "<CMD>ene!<CR>" },
},
val = {},
}
local bottom_buttons = {
entries = {
{ "q", "Quit", "<CMD>quit<CR>" },
},
val = {},
}
local footer = {
type = "group",
val = {},
}
return {
header = header,
top_buttons = top_buttons,
bottom_buttons = bottom_buttons,
-- this is probably broken
footer = footer,
}
end
return M

View File

@ -0,0 +1,191 @@
local M = {}
local Log = require "lvim.core.log"
--- Load the default set of autogroups and autocommands.
function M.load_defaults()
local user_config_file = require("lvim.config"):get_user_config_path()
if vim.loop.os_uname().version:match "Windows" then
-- autocmds require forward slashes even on windows
user_config_file = user_config_file:gsub("\\", "/")
end
local definitions = {
{
"TextYankPost",
{
group = "_general_settings",
pattern = "*",
desc = "Highlight text on yank",
callback = function()
require("vim.highlight").on_yank { higroup = "Search", timeout = 200 }
end,
},
},
{
"BufWritePost",
{
group = "_general_settings",
pattern = user_config_file,
desc = "Trigger LvimReload on saving " .. vim.fn.expand "%:~",
callback = function()
require("lvim.config"):reload()
end,
},
},
{
"FileType",
{
group = "_filetype_settings",
pattern = "qf",
command = "set nobuflisted",
},
},
{
"FileType",
{
group = "_filetype_settings",
pattern = { "gitcommit", "markdown" },
command = "setlocal wrap spell",
},
},
{
"FileType",
{
group = "_buffer_mappings",
pattern = { "qf", "help", "man", "floaterm", "lspinfo", "lsp-installer", "null-ls-info" },
command = "nnoremap <silent> <buffer> q :close<CR>",
},
},
{
{ "BufWinEnter", "BufRead", "BufNewFile" },
{
group = "_format_options",
pattern = "*",
command = "setlocal formatoptions-=c formatoptions-=r formatoptions-=o",
},
},
{
"VimResized",
{
group = "_auto_resize",
pattern = "*",
command = "tabdo wincmd =",
},
},
}
M.define_autocmds(definitions)
end
local get_format_on_save_opts = function()
local defaults = require("lvim.config.defaults").format_on_save
-- accept a basic boolean `lvim.format_on_save=true`
if type(lvim.format_on_save) ~= "table" then
return defaults
end
return {
pattern = lvim.format_on_save.pattern or defaults.pattern,
timeout = lvim.format_on_save.timeout or defaults.timeout,
}
end
function M.enable_format_on_save()
local opts = get_format_on_save_opts()
vim.api.nvim_create_augroup("lsp_format_on_save", {})
vim.api.nvim_create_autocmd("BufWritePre", {
group = "lsp_format_on_save",
pattern = opts.pattern,
callback = function()
require("lvim.lsp.utils").format { timeout_ms = opts.timeout, filter = opts.filter }
end,
})
Log:debug "enabled format-on-save"
end
function M.disable_format_on_save()
M.clear_augroup "lsp_format_on_save"
Log:debug "disabled format-on-save"
end
function M.configure_format_on_save()
if lvim.format_on_save then
M.enable_format_on_save()
else
M.disable_format_on_save()
end
end
function M.toggle_format_on_save()
local exists, autocmds = pcall(vim.api.nvim_get_autocmds, {
group = "lsp_format_on_save",
event = "BufWritePre",
})
if not exists or #autocmds == 0 then
M.enable_format_on_save()
else
M.disable_format_on_save()
end
end
function M.enable_transparent_mode()
vim.api.nvim_create_autocmd("ColorScheme", {
pattern = "*",
callback = function()
local hl_groups = {
"Normal",
"SignColumn",
"NormalNC",
"TelescopeBorder",
"NvimTreeNormal",
"EndOfBuffer",
"MsgArea",
}
for _, name in ipairs(hl_groups) do
vim.cmd(string.format("highlight %s ctermbg=none guibg=none", name))
end
end,
})
vim.opt.fillchars = "eob: "
end
--- Clean autocommand in a group if it exists
--- This is safer than trying to delete the augroup itself
---@param name string the augroup name
function M.clear_augroup(name)
-- defer the function in case the autocommand is still in-use
local exists, _ = pcall(vim.api.nvim_get_autocmds, { group = name })
if not exists then
Log:debug("ignoring request to clear autocmds from non-existent group " .. name)
return
end
vim.schedule(function()
local status_ok, _ = xpcall(function()
vim.api.nvim_clear_autocmds { group = name }
end, debug.traceback)
if not status_ok then
Log:warn("problems detected while clearing autocmds from " .. name)
Log:debug(debug.traceback())
end
end)
end
--- Create autocommand groups based on the passed definitions
--- Also creates the augroup automatically if it doesn't exist
---@param definitions table contains a tuple of event, opts, see `:h nvim_create_autocmd`
function M.define_autocmds(definitions)
for _, entry in ipairs(definitions) do
local event = entry[1]
local opts = entry[2]
if type(opts.group) == "string" and opts.group ~= "" then
local exists, _ = pcall(vim.api.nvim_get_autocmds, { group = opts.group })
if not exists then
vim.api.nvim_create_augroup(opts.group, {})
end
end
vim.api.nvim_create_autocmd(event, opts)
end
end
return M

View File

@ -0,0 +1,84 @@
local M = {}
function M.config()
lvim.builtin.autopairs = {
active = true,
on_config_done = nil,
---@usage modifies the function or method delimiter by filetypes
map_char = {
all = "(",
tex = "{",
},
---@usage check bracket in same line
enable_check_bracket_line = false,
---@usage check treesitter
check_ts = true,
ts_config = {
lua = { "string", "source" },
javascript = { "string", "template_string" },
java = false,
},
disable_filetype = { "TelescopePrompt", "spectre_panel" },
ignored_next_char = string.gsub([[ [%w%%%'%[%"%.] ]], "%s+", ""),
enable_moveright = true,
---@usage disable when recording or executing a macro
disable_in_macro = false,
---@usage add bracket pairs after quote
enable_afterquote = true,
---@usage map the <BS> key
map_bs = true,
---@usage map <c-w> to delete a pair if possible
map_c_w = false,
---@usage disable when insert after visual block mode
disable_in_visualblock = false,
---@usage change default fast_wrap
fast_wrap = {
map = "<M-e>",
chars = { "{", "[", "(", '"', "'" },
pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], "%s+", ""),
offset = 0, -- Offset from pattern match
end_key = "$",
keys = "qwertyuiopzxcvbnmasdfghjkl",
check_comma = true,
highlight = "Search",
highlight_grey = "Comment",
},
}
end
M.setup = function()
local autopairs = require "nvim-autopairs"
local Rule = require "nvim-autopairs.rule"
autopairs.setup {
check_ts = lvim.builtin.autopairs.check_ts,
enable_check_bracket_line = lvim.builtin.autopairs.enable_check_bracket_line,
ts_config = lvim.builtin.autopairs.ts_config,
disable_filetype = lvim.builtin.autopairs.disable_filetype,
disable_in_macro = lvim.builtin.autopairs.disable_in_macro,
ignored_next_char = lvim.builtin.autopairs.ignored_next_char,
enable_moveright = lvim.builtin.autopairs.enable_moveright,
enable_afterquote = lvim.builtin.autopairs.enable_afterquote,
map_c_w = lvim.builtin.autopairs.map_c_w,
map_bs = lvim.builtin.autopairs.map_bs,
disable_in_visualblock = lvim.builtin.autopairs.disable_in_visualblock,
fast_wrap = lvim.builtin.autopairs.fast_wrap,
}
require("nvim-treesitter.configs").setup { autopairs = { enable = true } }
local ts_conds = require "nvim-autopairs.ts-conds"
-- TODO: can these rules be safely added from "config.lua" ?
-- press % => %% is only inside comment or string
autopairs.add_rules {
Rule("%", "%", "lua"):with_pair(ts_conds.is_ts_node { "string", "comment" }),
Rule("$", "$", "lua"):with_pair(ts_conds.is_not_ts_node { "function" }),
}
if lvim.builtin.autopairs.on_config_done then
lvim.builtin.autopairs.on_config_done(autopairs)
end
end
return M

View File

@ -0,0 +1,221 @@
local M = {}
local function is_ft(b, ft)
return vim.bo[b].filetype == ft
end
local function diagnostics_indicator(num, _, diagnostics, _)
local result = {}
local symbols = { error = "", warning = "", info = "" }
if not lvim.use_icons then
return "(" .. num .. ")"
end
for name, count in pairs(diagnostics) do
if symbols[name] and count > 0 then
table.insert(result, symbols[name] .. " " .. count)
end
end
result = table.concat(result, " ")
return #result > 0 and result or ""
end
local function custom_filter(buf, buf_nums)
local logs = vim.tbl_filter(function(b)
return is_ft(b, "log")
end, buf_nums)
if vim.tbl_isempty(logs) then
return true
end
local tab_num = vim.fn.tabpagenr()
local last_tab = vim.fn.tabpagenr "$"
local is_log = is_ft(buf, "log")
if last_tab == 1 then
return true
end
-- only show log buffers in secondary tabs
return (tab_num == last_tab and is_log) or (tab_num ~= last_tab and not is_log)
end
M.config = function()
lvim.builtin.bufferline = {
active = true,
on_config_done = nil,
keymap = {
normal_mode = {},
},
highlights = {
background = {
gui = "italic",
},
buffer_selected = {
gui = "bold",
},
},
options = {
numbers = "none", -- can be "none" | "ordinal" | "buffer_id" | "both" | function
close_command = "bdelete! %d", -- can be a string | function, see "Mouse actions"
right_mouse_command = "vert sbuffer %d", -- can be a string | function, see "Mouse actions"
left_mouse_command = "buffer %d", -- can be a string | function, see "Mouse actions"
middle_mouse_command = nil, -- can be a string | function, see "Mouse actions"
-- NOTE: this plugin is designed with this icon in mind,
-- and so changing this is NOT recommended, this is intended
-- as an escape hatch for people who cannot bear it for whatever reason
indicator_icon = "",
buffer_close_icon = "",
modified_icon = "",
close_icon = "",
left_trunc_marker = "",
right_trunc_marker = "",
--- 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 a "name", "path" and "bufnr"
-- remove extension from markdown files for example
if buf.name:match "%.md" then
return vim.fn.fnamemodify(buf.name, ":t:r")
end
end,
max_name_length = 18,
max_prefix_length = 15, -- prefix used when a buffer is de-duplicated
tab_size = 18,
diagnostics = "nvim_lsp",
diagnostics_update_in_insert = false,
diagnostics_indicator = diagnostics_indicator,
-- NOTE: this will be called a lot so don't do any heavy processing here
custom_filter = custom_filter,
offsets = {
{
filetype = "undotree",
text = "Undotree",
highlight = "PanelHeading",
padding = 1,
},
{
filetype = "NvimTree",
text = "Explorer",
highlight = "PanelHeading",
padding = 1,
},
{
filetype = "DiffviewFiles",
text = "Diff View",
highlight = "PanelHeading",
padding = 1,
},
{
filetype = "flutterToolsOutline",
text = "Flutter Outline",
highlight = "PanelHeading",
},
{
filetype = "packer",
text = "Packer",
highlight = "PanelHeading",
padding = 1,
},
},
show_buffer_icons = lvim.use_icons, -- disable filetype icons for buffers
show_buffer_close_icons = lvim.use_icons,
show_close_icon = false,
show_tab_indicators = true,
persist_buffer_sort = true, -- whether or not custom sorted buffers should persist
-- can also be a table containing 2 custom separators
-- [focused and unfocused]. eg: { '|', '|' }
separator_style = "thin",
enforce_regular_tabs = false,
always_show_bufferline = false,
sort_by = "id",
},
}
end
M.setup = function()
require("lvim.keymappings").load(lvim.builtin.bufferline.keymap)
require("bufferline").setup {
options = lvim.builtin.bufferline.options,
highlights = lvim.builtin.bufferline.highlights,
}
if lvim.builtin.bufferline.on_config_done then
lvim.builtin.bufferline.on_config_done()
end
end
--stylua: ignore
-- Common kill function for bdelete and bwipeout
-- credits: based on bbye and nvim-bufdel
---@param kill_command? string defaults to "bd"
---@param bufnr? number defaults to the current buffer
---@param force? boolean defaults to false
function M.buf_kill(kill_command, bufnr, force)
kill_command = kill_command or "bd"
local bo = vim.bo
local api = vim.api
local fmt = string.format
local fnamemodify = vim.fn.fnamemodify
if bufnr == 0 or bufnr == nil then
bufnr = api.nvim_get_current_buf()
end
local bufname = api.nvim_buf_get_name(bufnr)
if not force then
local warning
if bo[bufnr].modified then
warning = fmt([[No write since last change for (%s)]], fnamemodify(bufname, ":t"))
elseif api.nvim_buf_get_option(bufnr, "buftype") == "terminal" then
warning = fmt([[Terminal %s will be killed]], bufname)
end
if warning then
vim.ui.input({
prompt = string.format([[%s. Close it anyway? [y]es or [n]o (default: no): ]], warning),
}, function(choice)
if choice:match "ye?s?" then force = true end
end)
if not force then return end
end
end
-- Get list of windows IDs with the buffer to close
local windows = vim.tbl_filter(function(win)
return api.nvim_win_get_buf(win) == bufnr
end, api.nvim_list_wins())
if #windows == 0 then return end
if force then
kill_command = kill_command .. "!"
end
-- Get list of active buffers
local buffers = vim.tbl_filter(function(buf)
return api.nvim_buf_is_valid(buf) and bo[buf].buflisted
end, api.nvim_list_bufs())
-- If there is only one buffer (which has to be the current one), vim will
-- create a new buffer on :bd.
-- For more than one buffer, pick the previous buffer (wrapping around if necessary)
if #buffers > 1 then
for i, v in ipairs(buffers) do
if v == bufnr then
local prev_buf_idx = i == 1 and (#buffers - 1) or (i - 1)
local prev_buffer = buffers[prev_buf_idx]
for _, win in ipairs(windows) do
api.nvim_win_set_buf(win, prev_buffer)
end
end
end
end
-- Check if buffer still exists, to ensure the target buffer wasn't killed
-- due to options like bufhidden=wipe.
if api.nvim_buf_is_valid(bufnr) and bo[bufnr].buflisted then
vim.cmd(string.format("%s %d", kill_command, bufnr))
end
end
return M

View File

@ -0,0 +1,28 @@
local M = {}
local builtins = {
"lvim.core.which-key",
"lvim.core.gitsigns",
"lvim.core.cmp",
"lvim.core.dap",
"lvim.core.terminal",
"lvim.core.telescope",
"lvim.core.treesitter",
"lvim.core.nvimtree",
"lvim.core.project",
"lvim.core.bufferline",
"lvim.core.autopairs",
"lvim.core.comment",
"lvim.core.notify",
"lvim.core.lualine",
"lvim.core.alpha",
}
function M.config(config)
for _, builtin_path in ipairs(builtins) do
local builtin = require(builtin_path)
builtin.config(config)
end
end
return M

View File

@ -0,0 +1,318 @@
local M = {}
M.methods = {}
---checks if the character preceding the cursor is a space character
---@return boolean true if it is a space character, false otherwise
local check_backspace = function()
local col = vim.fn.col "." - 1
return col == 0 or vim.fn.getline("."):sub(col, col):match "%s"
end
M.methods.check_backspace = check_backspace
local function T(str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end
---wraps vim.fn.feedkeys while replacing key codes with escape codes
---Ex: feedkeys("<CR>", "n") becomes feedkeys("^M", "n")
---@param key string
---@param mode string
local function feedkeys(key, mode)
vim.fn.feedkeys(T(key), mode)
end
M.methods.feedkeys = feedkeys
---checks if emmet_ls is available and active in the buffer
---@return boolean true if available, false otherwise
local is_emmet_active = function()
local clients = vim.lsp.buf_get_clients()
for _, client in pairs(clients) do
if client.name == "emmet_ls" then
return true
end
end
return false
end
M.methods.is_emmet_active = is_emmet_active
---when inside a snippet, seeks to the nearest luasnip field if possible, and checks if it is jumpable
---@param dir number 1 for forward, -1 for backward; defaults to 1
---@return boolean true if a jumpable luasnip field is found while inside a snippet
local function jumpable(dir)
local luasnip_ok, luasnip = pcall(require, "luasnip")
if not luasnip_ok then
return
end
local win_get_cursor = vim.api.nvim_win_get_cursor
local get_current_buf = vim.api.nvim_get_current_buf
local function inside_snippet()
-- for outdated versions of luasnip
if not luasnip.session.current_nodes then
return false
end
local node = luasnip.session.current_nodes[get_current_buf()]
if not node then
return false
end
local snip_begin_pos, snip_end_pos = node.parent.snippet.mark:pos_begin_end()
local pos = win_get_cursor(0)
pos[1] = pos[1] - 1 -- LuaSnip is 0-based not 1-based like nvim for rows
return pos[1] >= snip_begin_pos[1] and pos[1] <= snip_end_pos[1]
end
---sets the current buffer's luasnip to the one nearest the cursor
---@return boolean true if a node is found, false otherwise
local function seek_luasnip_cursor_node()
-- for outdated versions of luasnip
if not luasnip.session.current_nodes then
return false
end
local pos = win_get_cursor(0)
pos[1] = pos[1] - 1
local node = luasnip.session.current_nodes[get_current_buf()]
if not node then
return false
end
local snippet = node.parent.snippet
local exit_node = snippet.insert_nodes[0]
-- exit early if we're past the exit node
if exit_node then
local exit_pos_end = exit_node.mark:pos_end()
if (pos[1] > exit_pos_end[1]) or (pos[1] == exit_pos_end[1] and pos[2] > exit_pos_end[2]) then
snippet:remove_from_jumplist()
luasnip.session.current_nodes[get_current_buf()] = nil
return false
end
end
node = snippet.inner_first:jump_into(1, true)
while node ~= nil and node.next ~= nil and node ~= snippet do
local n_next = node.next
local next_pos = n_next and n_next.mark:pos_begin()
local candidate = n_next ~= snippet and next_pos and (pos[1] < next_pos[1])
or (pos[1] == next_pos[1] and pos[2] < next_pos[2])
-- Past unmarked exit node, exit early
if n_next == nil or n_next == snippet.next then
snippet:remove_from_jumplist()
luasnip.session.current_nodes[get_current_buf()] = nil
return false
end
if candidate then
luasnip.session.current_nodes[get_current_buf()] = node
return true
end
local ok
ok, node = pcall(node.jump_from, node, 1, true) -- no_move until last stop
if not ok then
snippet:remove_from_jumplist()
luasnip.session.current_nodes[get_current_buf()] = nil
return false
end
end
-- No candidate, but have an exit node
if exit_node then
-- to jump to the exit node, seek to snippet
luasnip.session.current_nodes[get_current_buf()] = snippet
return true
end
-- No exit node, exit from snippet
snippet:remove_from_jumplist()
luasnip.session.current_nodes[get_current_buf()] = nil
return false
end
if dir == -1 then
return inside_snippet() and luasnip.jumpable(-1)
else
return inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable()
end
end
M.methods.jumpable = jumpable
M.config = function()
local status_cmp_ok, cmp = pcall(require, "cmp")
if not status_cmp_ok then
return
end
local status_luasnip_ok, luasnip = pcall(require, "luasnip")
if not status_luasnip_ok then
return
end
lvim.builtin.cmp = {
confirm_opts = {
behavior = cmp.ConfirmBehavior.Replace,
select = false,
},
completion = {
---@usage The minimum length of a word to complete on.
keyword_length = 1,
},
experimental = {
ghost_text = true,
native_menu = false,
},
formatting = {
fields = { "kind", "abbr", "menu" },
max_width = 0,
kind_icons = {
Class = "",
Color = "",
Constant = "",
Constructor = "",
Enum = "",
EnumMember = "",
Event = "",
Field = "",
File = "",
Folder = "",
Function = "",
Interface = "",
Keyword = "",
Method = "",
Module = "",
Operator = "",
Property = "",
Reference = "",
Snippet = "",
Struct = "",
Text = "",
TypeParameter = "",
Unit = "",
Value = "",
Variable = "",
},
source_names = {
nvim_lsp = "(LSP)",
emoji = "(Emoji)",
path = "(Path)",
calc = "(Calc)",
cmp_tabnine = "(Tabnine)",
vsnip = "(Snippet)",
luasnip = "(Snippet)",
buffer = "(Buffer)",
tmux = "(TMUX)",
},
duplicates = {
buffer = 1,
path = 1,
nvim_lsp = 0,
luasnip = 1,
},
duplicates_default = 0,
format = function(entry, vim_item)
local max_width = lvim.builtin.cmp.formatting.max_width
if max_width ~= 0 and #vim_item.abbr > max_width then
vim_item.abbr = string.sub(vim_item.abbr, 1, max_width - 1) .. ""
end
if lvim.use_icons then
vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind]
end
vim_item.menu = lvim.builtin.cmp.formatting.source_names[entry.source.name]
vim_item.dup = lvim.builtin.cmp.formatting.duplicates[entry.source.name]
or lvim.builtin.cmp.formatting.duplicates_default
return vim_item
end,
},
snippet = {
expand = function(args)
require("luasnip").lsp_expand(args.body)
end,
},
window = {
completion = cmp.config.window.bordered(),
documentation = cmp.config.window.bordered(),
},
sources = {
{ name = "nvim_lsp" },
{ name = "path" },
{ name = "luasnip" },
{ name = "cmp_tabnine" },
{ name = "nvim_lua" },
{ name = "buffer" },
{ name = "calc" },
{ name = "emoji" },
{ name = "treesitter" },
{ name = "crates" },
{ name = "tmux" },
},
mapping = cmp.mapping.preset.insert {
["<C-k>"] = cmp.mapping.select_prev_item(),
["<C-j>"] = cmp.mapping.select_next_item(),
["<C-d>"] = cmp.mapping.scroll_docs(-4),
["<C-f>"] = cmp.mapping.scroll_docs(4),
-- TODO: potentially fix emmet nonsense
["<Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expandable() then
luasnip.expand()
elseif jumpable() then
luasnip.jump(1)
elseif check_backspace() then
fallback()
elseif is_emmet_active() then
return vim.fn["cmp#complete"]()
else
fallback()
end
end, {
"i",
"s",
}),
["<S-Tab>"] = cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end, {
"i",
"s",
}),
["<C-Space>"] = cmp.mapping.complete(),
["<C-e>"] = cmp.mapping.abort(),
["<CR>"] = cmp.mapping(function(fallback)
if cmp.visible() and cmp.confirm(lvim.builtin.cmp.confirm_opts) then
if jumpable() then
luasnip.jump(1)
end
return
end
if jumpable() then
if not luasnip.jump(1) then
fallback()
end
else
fallback()
end
end),
},
}
end
function M.setup()
require("cmp").setup(lvim.builtin.cmp)
end
return M

View File

@ -0,0 +1,78 @@
local M = {}
vim.cmd [[
function! QuickFixToggle()
if empty(filter(getwininfo(), 'v:val.quickfix'))
copen
else
cclose
endif
endfunction
]]
M.defaults = {
{
name = "BufferKill",
fn = function()
require("lvim.core.bufferline").buf_kill "bd"
end,
},
{
name = "LvimToggleFormatOnSave",
fn = function()
require("lvim.core.autocmds").toggle_format_on_save()
end,
},
{
name = "LvimInfo",
fn = function()
require("lvim.core.info").toggle_popup(vim.bo.filetype)
end,
},
{
name = "LvimCacheReset",
fn = function()
require("lvim.utils.hooks").reset_cache()
end,
},
{
name = "LvimReload",
fn = function()
require("lvim.config"):reload()
end,
},
{
name = "LvimUpdate",
fn = function()
require("lvim.bootstrap"):update()
end,
},
{
name = "LvimSyncCorePlugins",
fn = function()
require("lvim.plugin-loader").sync_core_plugins()
end,
},
{
name = "LvimChangelog",
fn = function()
require("lvim.core.telescope.custom-finders").view_lunarvim_changelog()
end,
},
{
name = "LvimVersion",
fn = function()
print(require("lvim.utils.git").get_lvim_version())
end,
},
}
function M.load(collection)
local common_opts = { force = true }
for _, cmd in pairs(collection) do
local opts = vim.tbl_deep_extend("force", common_opts, cmd.opts or {})
vim.api.nvim_create_user_command(cmd.name, cmd.fn, opts)
end
end
return M

View File

@ -0,0 +1,71 @@
local M = {}
function M.config()
local pre_hook = nil
if lvim.builtin.treesitter.context_commentstring.enable then
pre_hook = function(_ctx)
return require("ts_context_commentstring.internal").calculate_commentstring()
end
end
lvim.builtin.comment = {
active = true,
on_config_done = nil,
---Add a space b/w comment and the line
---@type boolean
padding = true,
---Lines to be ignored while comment/uncomment.
---Could be a regex string or a function that returns a regex string.
---Example: Use '^$' to ignore empty lines
---@type string|function
ignore = "^$",
---Whether to create basic (operator-pending) and extra mappings for NORMAL/VISUAL mode
---@type table
mappings = {
---operator-pending mapping
---Includes `gcc`, `gcb`, `gc[count]{motion}` and `gb[count]{motion}`
basic = true,
---extended mapping
---Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}`
extra = false,
},
---LHS of line and block comment toggle mapping in NORMAL/VISUAL mode
---@type table
toggler = {
---line-comment toggle
line = "gcc",
---block-comment toggle
block = "gbc",
},
---LHS of line and block comment operator-mode mapping in NORMAL/VISUAL mode
---@type table
opleader = {
---line-comment opfunc mapping
line = "gc",
---block-comment opfunc mapping
block = "gb",
},
---Pre-hook, called before commenting the line
---@type function|nil
pre_hook = pre_hook,
---Post-hook, called after commenting is done
---@type function|nil
post_hook = nil,
}
end
function M.setup()
local nvim_comment = require "Comment"
nvim_comment.setup(lvim.builtin.comment)
if lvim.builtin.comment.on_config_done then
lvim.builtin.comment.on_config_done(nvim_comment)
end
end
return M

View File

@ -0,0 +1,78 @@
local M = {}
M.config = function()
lvim.builtin.dap = {
active = false,
on_config_done = nil,
breakpoint = {
text = "",
texthl = "LspDiagnosticsSignError",
linehl = "",
numhl = "",
},
breakpoint_rejected = {
text = "",
texthl = "LspDiagnosticsSignHint",
linehl = "",
numhl = "",
},
stopped = {
text = "",
texthl = "LspDiagnosticsSignInformation",
linehl = "DiagnosticUnderlineInfo",
numhl = "LspDiagnosticsSignInformation",
},
}
end
M.setup = function()
local dap = require "dap"
if lvim.use_icons then
vim.fn.sign_define("DapBreakpoint", lvim.builtin.dap.breakpoint)
vim.fn.sign_define("DapBreakpointRejected", lvim.builtin.dap.breakpoint_rejected)
vim.fn.sign_define("DapStopped", lvim.builtin.dap.stopped)
end
dap.defaults.fallback.terminal_win_cmd = "50vsplit new"
lvim.builtin.which_key.mappings["d"] = {
name = "Debug",
t = { "<cmd>lua require'dap'.toggle_breakpoint()<cr>", "Toggle Breakpoint" },
b = { "<cmd>lua require'dap'.step_back()<cr>", "Step Back" },
c = { "<cmd>lua require'dap'.continue()<cr>", "Continue" },
C = { "<cmd>lua require'dap'.run_to_cursor()<cr>", "Run To Cursor" },
d = { "<cmd>lua require'dap'.disconnect()<cr>", "Disconnect" },
g = { "<cmd>lua require'dap'.session()<cr>", "Get Session" },
i = { "<cmd>lua require'dap'.step_into()<cr>", "Step Into" },
o = { "<cmd>lua require'dap'.step_over()<cr>", "Step Over" },
u = { "<cmd>lua require'dap'.step_out()<cr>", "Step Out" },
p = { "<cmd>lua require'dap'.pause()<cr>", "Pause" },
r = { "<cmd>lua require'dap'.repl.toggle()<cr>", "Toggle Repl" },
s = { "<cmd>lua require'dap'.continue()<cr>", "Start" },
q = { "<cmd>lua require'dap'.close()<cr>", "Quit" },
}
if lvim.builtin.dap.on_config_done then
lvim.builtin.dap.on_config_done(dap)
end
end
-- TODO put this up there ^^^ call in ftplugin
-- M.dap = function()
-- if lvim.plugin.dap.active then
-- local dap_install = require "dap-install"
-- dap_install.config("python_dbg", {})
-- end
-- end
--
-- M.dap = function()
-- -- gem install readapt ruby-debug-ide
-- if lvim.plugin.dap.active then
-- local dap_install = require "dap-install"
-- dap_install.config("ruby_vsc_dbg", {})
-- end
-- end
return M

View File

@ -0,0 +1,90 @@
local M = {}
M.config = function()
lvim.builtin.gitsigns = {
active = true,
on_config_done = nil,
opts = {
signs = {
add = {
hl = "GitSignsAdd",
text = "",
numhl = "GitSignsAddNr",
linehl = "GitSignsAddLn",
},
change = {
hl = "GitSignsChange",
text = "",
numhl = "GitSignsChangeNr",
linehl = "GitSignsChangeLn",
},
delete = {
hl = "GitSignsDelete",
text = "",
numhl = "GitSignsDeleteNr",
linehl = "GitSignsDeleteLn",
},
topdelete = {
hl = "GitSignsDelete",
text = "",
numhl = "GitSignsDeleteNr",
linehl = "GitSignsDeleteLn",
},
changedelete = {
hl = "GitSignsChange",
text = "",
numhl = "GitSignsChangeNr",
linehl = "GitSignsChangeLn",
},
},
numhl = false,
linehl = false,
keymaps = {
-- Default keymap options
noremap = true,
buffer = true,
},
signcolumn = true,
word_diff = false,
attach_to_untracked = true,
current_line_blame = false, -- Toggle with `:Gitsigns toggle_current_line_blame`
current_line_blame_opts = {
virt_text = true,
virt_text_pos = "eol", -- 'eol' | 'overlay' | 'right_align'
delay = 1000,
ignore_whitespace = false,
},
current_line_blame_formatter_opts = {
relative_time = false,
},
max_file_length = 40000,
preview_config = {
-- Options passed to nvim_open_win
border = "rounded",
style = "minimal",
relative = "cursor",
row = 0,
col = 1,
},
watch_gitdir = {
interval = 1000,
follow_files = true,
},
sign_priority = 6,
update_debounce = 200,
status_formatter = nil, -- Use default
yadm = { enable = false },
},
}
end
M.setup = function()
local gitsigns = require "gitsigns"
gitsigns.setup(lvim.builtin.gitsigns.opts)
if lvim.builtin.gitsigns.on_config_done then
lvim.builtin.gitsigns.on_config_done(gitsigns)
end
end
return M

View File

@ -0,0 +1,222 @@
local M = {
banner = {
"",
[[ __ _ ___ ]],
[[ / / __ ______ ____ _____| | / (_)___ ___ ]],
[[ / / / / / / __ \/ __ `/ ___/ | / / / __ `__ \]],
[[ / /___/ /_/ / / / / /_/ / / | |/ / / / / / / /]],
[[/_____/\__,_/_/ /_/\__,_/_/ |___/_/_/ /_/ /_/ ]],
},
}
local fmt = string.format
local text = require "lvim.interface.text"
local lsp_utils = require "lvim.lsp.utils"
local function str_list(list)
return #list == 1 and list[1] or fmt("[%s]", table.concat(list, ", "))
end
local function make_formatters_info(ft)
local null_formatters = require "lvim.lsp.null-ls.formatters"
local registered_formatters = null_formatters.list_registered(ft)
local supported_formatters = null_formatters.list_supported(ft)
local section = {
"Formatters info",
fmt(
"* Active: %s%s",
table.concat(registered_formatters, "  , "),
vim.tbl_count(registered_formatters) > 0 and "" or ""
),
fmt("* Supported: %s", str_list(supported_formatters)),
}
return section
end
local function make_code_actions_info(ft)
local null_actions = require "lvim.lsp.null-ls.code_actions"
local registered_actions = null_actions.list_registered(ft)
local section = {
"Code actions info",
fmt(
"* Active: %s%s",
table.concat(registered_actions, "  , "),
vim.tbl_count(registered_actions) > 0 and "" or ""
),
}
return section
end
local function make_linters_info(ft)
local null_linters = require "lvim.lsp.null-ls.linters"
local supported_linters = null_linters.list_supported(ft)
local registered_linters = null_linters.list_registered(ft)
local section = {
"Linters info",
fmt(
"* Active: %s%s",
table.concat(registered_linters, "  , "),
vim.tbl_count(registered_linters) > 0 and "" or ""
),
fmt("* Supported: %s", str_list(supported_linters)),
}
return section
end
local function tbl_set_highlight(terms, highlight_group)
for _, v in pairs(terms) do
vim.cmd('let m=matchadd("' .. highlight_group .. '", "' .. v .. "[ ,│']\")")
vim.cmd('let m=matchadd("' .. highlight_group .. '", ", ' .. v .. '")')
end
end
local function make_client_info(client)
if client.name == "null-ls" then
return
end
local client_enabled_caps = lsp_utils.get_client_capabilities(client.id)
local name = client.name
local id = client.id
local filetypes = lsp_utils.get_supported_filetypes(name)
local attached_buffers_list = str_list(vim.lsp.get_buffers_by_client_id(client.id))
local client_info = {
fmt("* name: %s", name),
fmt("* id: %s", tostring(id)),
fmt("* supported filetype(s): %s", str_list(filetypes)),
fmt("* attached buffers: %s", tostring(attached_buffers_list)),
fmt("* root_dir pattern: %s", tostring(attached_buffers_list)),
}
if not vim.tbl_isempty(client_enabled_caps) then
local caps_text = "* capabilities: "
local caps_text_len = caps_text:len()
local enabled_caps = text.format_table(client_enabled_caps, 3, " | ")
enabled_caps = text.shift_right(enabled_caps, caps_text_len)
enabled_caps[1] = fmt("%s%s", caps_text, enabled_caps[1]:sub(caps_text_len + 1))
vim.list_extend(client_info, enabled_caps)
end
return client_info
end
local function make_auto_lsp_info(ft)
local skipped_filetypes = lvim.lsp.automatic_configuration.skipped_filetypes
local skipped_servers = lvim.lsp.automatic_configuration.skipped_servers
local info_lines = { "Automatic LSP info" }
if vim.tbl_contains(skipped_filetypes, ft) then
vim.list_extend(info_lines, { "* Status: disabled for " .. ft })
return info_lines
end
local available = lsp_utils.get_supported_servers_per_filetype(ft)
local skipped = vim.tbl_filter(function(name)
return vim.tbl_contains(available, name)
end, skipped_servers)
if #skipped == 0 then
return { "" }
end
vim.list_extend(info_lines, { fmt("* Skipped servers: %s", str_list(skipped)) })
return info_lines
end
function M.toggle_popup(ft)
local clients = vim.lsp.get_active_clients()
local client_names = {}
local bufnr = vim.api.nvim_get_current_buf()
local ts_active_buffers = vim.tbl_keys(vim.treesitter.highlighter.active)
local is_treesitter_active = function()
local status = "inactive"
if vim.tbl_contains(ts_active_buffers, bufnr) then
status = "active"
end
return status
end
local header = {
"Buffer info",
fmt("* filetype: %s", ft),
fmt("* bufnr: %s", bufnr),
fmt("* treesitter status: %s", is_treesitter_active()),
}
local lsp_info = {
"Active client(s)",
}
for _, client in pairs(clients) do
local client_info = make_client_info(client)
if client_info then
vim.list_extend(lsp_info, client_info)
end
table.insert(client_names, client.name)
end
local auto_lsp_info = make_auto_lsp_info(ft)
local formatters_info = make_formatters_info(ft)
local linters_info = make_linters_info(ft)
local code_actions_info = make_code_actions_info(ft)
local content_provider = function(popup)
local content = {}
for _, section in ipairs {
M.banner,
{ "" },
{ "" },
header,
{ "" },
lsp_info,
{ "" },
auto_lsp_info,
{ "" },
formatters_info,
{ "" },
linters_info,
{ "" },
code_actions_info,
} do
vim.list_extend(content, section)
end
return text.align_left(popup, content, 0.5)
end
local function set_syntax_hl()
vim.cmd [[highlight LvimInfoIdentifier gui=bold]]
vim.cmd [[highlight link LvimInfoHeader Type]]
vim.fn.matchadd("LvimInfoHeader", "Buffer info")
vim.fn.matchadd("LvimInfoHeader", "Active client(s)")
vim.fn.matchadd("LvimInfoHeader", fmt("Overridden %s server(s)", ft))
vim.fn.matchadd("LvimInfoHeader", "Formatters info")
vim.fn.matchadd("LvimInfoHeader", "Linters info")
vim.fn.matchadd("LvimInfoHeader", "Code actions info")
vim.fn.matchadd("LvimInfoHeader", "Automatic LSP info")
vim.fn.matchadd("LvimInfoIdentifier", " " .. ft .. "$")
vim.fn.matchadd("string", "true")
vim.fn.matchadd("string", "active")
vim.fn.matchadd("string", "")
vim.fn.matchadd("boolean", "inactive")
vim.fn.matchadd("error", "false")
tbl_set_highlight(require("lvim.lsp.null-ls.formatters").list_registered(ft), "LvimInfoIdentifier")
tbl_set_highlight(require("lvim.lsp.null-ls.linters").list_registered(ft), "LvimInfoIdentifier")
tbl_set_highlight(require("lvim.lsp.null-ls.code_actions").list_registered(ft), "LvimInfoIdentifier")
end
local Popup = require("lvim.interface.popup"):new {
win_opts = { number = false },
buf_opts = { modifiable = false, filetype = "lspinfo" },
}
Popup:display(content_provider)
set_syntax_hl()
return Popup
end
return M

View File

@ -0,0 +1,207 @@
local Log = {}
Log.levels = {
TRACE = 1,
DEBUG = 2,
INFO = 3,
WARN = 4,
ERROR = 5,
}
vim.tbl_add_reverse_lookup(Log.levels)
local notify_opts = {}
function Log:set_level(level)
-- package.loaded["lvim.core.log"] = nil
local log_level = Log.levels[level:upper()]
local status_ok, logger = pcall(require("structlog").get_logger, "lvim")
if status_ok then
for _, s in ipairs(logger.sinks) do
s.level = log_level
end
end
package.loaded["packer.log"] = nil
require("packer.log").new { level = lvim.log.level }
end
function Log:init()
local status_ok, structlog = pcall(require, "structlog")
if not status_ok then
return nil
end
local log_level = Log.levels[(lvim.log.level):upper() or "WARN"]
local lvim_log = {
lvim = {
sinks = {
structlog.sinks.Console(log_level, {
async = false,
processors = {
structlog.processors.Namer(),
structlog.processors.StackWriter({ "line", "file" }, { max_parents = 0, stack_level = 2 }),
structlog.processors.Timestamper "%H:%M:%S",
},
formatter = structlog.formatters.FormatColorizer( --
"%s [%-5s] %s: %-30s",
{ "timestamp", "level", "logger_name", "msg" },
{ level = structlog.formatters.FormatColorizer.color_level() }
),
}),
structlog.sinks.File(log_level, self:get_path(), {
processors = {
structlog.processors.Namer(),
structlog.processors.StackWriter({ "line", "file" }, { max_parents = 3, stack_level = 2 }),
structlog.processors.Timestamper "%F %H:%M:%S",
},
formatter = structlog.formatters.Format( --
"%s [%-5s] %s: %-30s",
{ "timestamp", "level", "logger_name", "msg" }
),
}),
},
},
}
structlog.configure(lvim_log)
local logger = structlog.get_logger "lvim"
-- Overwrite `vim.notify` to use the logger
if lvim.log.override_notify then
vim.notify = function(msg, vim_log_level, opts)
notify_opts = opts or {}
-- vim_log_level can be omitted
if vim_log_level == nil then
vim_log_level = Log.levels["INFO"]
elseif type(vim_log_level) == "string" then
vim_log_level = Log.levels[(vim_log_level):upper()] or Log.levels["INFO"]
else
-- https://github.com/neovim/neovim/blob/685cf398130c61c158401b992a1893c2405cd7d2/runtime/lua/vim/lsp/log.lua#L5
vim_log_level = vim_log_level + 1
end
logger:log(vim_log_level, msg)
end
end
return logger
end
--- Configure the sink in charge of logging notifications
---@param notif_handle table The implementation used by the sink for displaying the notifications
function Log:configure_notifications(notif_handle)
local status_ok, structlog = pcall(require, "structlog")
if not status_ok then
return
end
local default_namer = function(logger, entry)
entry["title"] = logger.name
return entry
end
local notify_opts_injecter = function(_, entry)
for key, value in pairs(notify_opts) do
entry[key] = value
end
notify_opts = {}
return entry
end
local sink = structlog.sinks.NvimNotify(Log.levels.INFO, {
processors = {
default_namer,
notify_opts_injecter,
},
formatter = structlog.formatters.Format( --
"%s",
{ "msg" },
{ blacklist_all = true }
),
-- This should probably not be hard-coded
params_map = {
icon = "icon",
keep = "keep",
on_open = "on_open",
on_close = "on_close",
timeout = "timeout",
title = "title",
},
impl = notif_handle,
})
table.insert(self.__handle.sinks, sink)
end
--- Adds a log entry using Plenary.log
---@param msg any
---@param level string [same as vim.log.log_levels]
function Log:add_entry(level, msg, event)
local logger = self:get_logger()
if not logger then
return
end
logger:log(level, vim.inspect(msg), event)
end
---Retrieves the handle of the logger object
---@return table|nil logger handle if found
function Log:get_logger()
if self.__handle then
return self.__handle
end
local logger = self:init()
if not logger then
return
end
self.__handle = logger
return logger
end
---Retrieves the path of the logfile
---@return string path of the logfile
function Log:get_path()
return string.format("%s/%s.log", get_cache_dir(), "lvim")
end
---Add a log entry at TRACE level
---@param msg any
---@param event any
function Log:trace(msg, event)
self:add_entry(self.levels.TRACE, msg, event)
end
---Add a log entry at DEBUG level
---@param msg any
---@param event any
function Log:debug(msg, event)
self:add_entry(self.levels.DEBUG, msg, event)
end
---Add a log entry at INFO level
---@param msg any
---@param event any
function Log:info(msg, event)
self:add_entry(self.levels.INFO, msg, event)
end
---Add a log entry at WARN level
---@param msg any
---@param event any
function Log:warn(msg, event)
self:add_entry(self.levels.WARN, msg, event)
end
---Add a log entry at ERROR level
---@param msg any
---@param event any
function Log:error(msg, event)
self:add_entry(self.levels.ERROR, msg, event)
end
setmetatable({}, Log)
return Log

View File

@ -0,0 +1,16 @@
local colors = {
bg = "#202328",
fg = "#bbc2cf",
yellow = "#ECBE7B",
cyan = "#008080",
darkblue = "#081633",
green = "#98be65",
orange = "#FF8800",
violet = "#a9a1e1",
magenta = "#c678dd",
purple = "#c678dd",
blue = "#51afef",
red = "#ec5f67",
}
return colors

View File

@ -0,0 +1,155 @@
local conditions = require "lvim.core.lualine.conditions"
local colors = require "lvim.core.lualine.colors"
local function diff_source()
local gitsigns = vim.b.gitsigns_status_dict
if gitsigns then
return {
added = gitsigns.added,
modified = gitsigns.changed,
removed = gitsigns.removed,
}
end
end
return {
mode = {
function()
return " "
end,
padding = { left = 0, right = 0 },
color = {},
cond = nil,
},
branch = {
"b:gitsigns_head",
icon = "",
color = { gui = "bold" },
cond = conditions.hide_in_width,
},
filename = {
"filename",
color = {},
cond = nil,
},
diff = {
"diff",
source = diff_source,
symbols = { added = "", modified = "", removed = "" },
diff_color = {
added = { fg = colors.green },
modified = { fg = colors.yellow },
removed = { fg = colors.red },
},
cond = nil,
},
python_env = {
function()
local utils = require "lvim.core.lualine.utils"
if vim.bo.filetype == "python" then
local venv = os.getenv "CONDA_DEFAULT_ENV"
if venv then
return string.format("  (%s)", utils.env_cleanup(venv))
end
venv = os.getenv "VIRTUAL_ENV"
if venv then
return string.format("  (%s)", utils.env_cleanup(venv))
end
return ""
end
return ""
end,
color = { fg = colors.green },
cond = conditions.hide_in_width,
},
diagnostics = {
"diagnostics",
sources = { "nvim_diagnostic" },
symbols = { error = "", warn = "", info = "", hint = "" },
cond = conditions.hide_in_width,
},
treesitter = {
function()
local b = vim.api.nvim_get_current_buf()
if next(vim.treesitter.highlighter.active[b]) then
return ""
end
return ""
end,
color = { fg = colors.green },
cond = conditions.hide_in_width,
},
lsp = {
function(msg)
msg = msg or "LS Inactive"
local buf_clients = vim.lsp.buf_get_clients()
if next(buf_clients) == nil then
-- TODO: clean up this if statement
if type(msg) == "boolean" or #msg == 0 then
return "LS Inactive"
end
return msg
end
local buf_ft = vim.bo.filetype
local buf_client_names = {}
-- add client
for _, client in pairs(buf_clients) do
if client.name ~= "null-ls" then
table.insert(buf_client_names, client.name)
end
end
-- add formatter
local formatters = require "lvim.lsp.null-ls.formatters"
local supported_formatters = formatters.list_registered(buf_ft)
vim.list_extend(buf_client_names, supported_formatters)
-- add linter
local linters = require "lvim.lsp.null-ls.linters"
local supported_linters = linters.list_registered(buf_ft)
vim.list_extend(buf_client_names, supported_linters)
local unique_client_names = vim.fn.uniq(buf_client_names)
return "[" .. table.concat(unique_client_names, ", ") .. "]"
end,
color = { gui = "bold" },
cond = conditions.hide_in_width,
},
location = { "location", cond = conditions.hide_in_width, color = {} },
progress = { "progress", cond = conditions.hide_in_width, color = {} },
spaces = {
function()
if not vim.api.nvim_buf_get_option(0, "expandtab") then
return "Tab size: " .. vim.api.nvim_buf_get_option(0, "tabstop") .. " "
end
local size = vim.api.nvim_buf_get_option(0, "shiftwidth")
if size == 0 then
size = vim.api.nvim_buf_get_option(0, "tabstop")
end
return "Spaces: " .. size .. " "
end,
cond = conditions.hide_in_width,
color = {},
},
encoding = {
"o:encoding",
fmt = string.upper,
color = {},
cond = conditions.hide_in_width,
},
filetype = { "filetype", cond = conditions.hide_in_width },
scrollbar = {
function()
local current_line = vim.fn.line "."
local total_lines = vim.fn.line "$"
local chars = { "__", "▁▁", "▂▂", "▃▃", "▄▄", "▅▅", "▆▆", "▇▇", "██" }
local line_ratio = current_line / total_lines
local index = math.ceil(line_ratio * #chars)
return chars[index]
end,
padding = { left = 0, right = 0 },
color = { fg = colors.yellow, bg = colors.bg },
cond = nil,
},
}

View File

@ -0,0 +1,17 @@
local window_width_limit = 70
local conditions = {
buffer_not_empty = function()
return vim.fn.empty(vim.fn.expand "%:t") ~= 1
end,
hide_in_width = function()
return vim.fn.winwidth(0) > window_width_limit
end,
-- check_git_workspace = function()
-- local filepath = vim.fn.expand "%:p:h"
-- local gitdir = vim.fn.finddir(".git", filepath .. ";")
-- return gitdir and #gitdir > 0 and #gitdir < #filepath
-- end,
}
return conditions

View File

@ -0,0 +1,54 @@
local M = {}
M.config = function()
lvim.builtin.lualine = {
active = true,
style = "lvim",
options = {
icons_enabled = nil,
component_separators = nil,
section_separators = nil,
theme = nil,
disabled_filetypes = nil,
globalstatus = false,
},
sections = {
lualine_a = nil,
lualine_b = nil,
lualine_c = nil,
lualine_x = nil,
lualine_y = nil,
lualine_z = nil,
},
inactive_sections = {
lualine_a = nil,
lualine_b = nil,
lualine_c = nil,
lualine_x = nil,
lualine_y = nil,
lualine_z = nil,
},
tabline = nil,
extensions = nil,
on_config_done = nil,
}
end
M.setup = function()
-- avoid running in headless mode since it's harder to detect failures
if #vim.api.nvim_list_uis() == 0 then
local Log = require "lvim.core.log"
Log:debug "headless mode detected, skipping running setup for lualine"
return
end
require("lvim.core.lualine.styles").update()
local lualine = require "lualine"
lualine.setup(lvim.builtin.lualine)
if lvim.builtin.lualine.on_config_done then
lvim.builtin.lualine.on_config_done(lualine)
end
end
return M

View File

@ -0,0 +1,137 @@
local M = {}
local components = require "lvim.core.lualine.components"
local styles = {
lvim = nil,
default = nil,
none = nil,
}
styles.none = {
style = "none",
options = {
theme = "auto",
icons_enabled = lvim.use_icons,
component_separators = { left = "", right = "" },
section_separators = { left = "", right = "" },
disabled_filetypes = {},
},
sections = {
lualine_a = {},
lualine_b = {},
lualine_c = {},
lualine_x = {},
lualine_y = {},
lualine_z = {},
},
inactive_sections = {
lualine_a = {},
lualine_b = {},
lualine_c = {},
lualine_x = {},
lualine_y = {},
lualine_z = {},
},
tabline = {},
extensions = {},
}
styles.default = {
style = "default",
options = {
theme = "auto",
icons_enabled = lvim.use_icons,
component_separators = { left = "", right = "" },
section_separators = { left = "", right = "" },
disabled_filetypes = {},
},
sections = {
lualine_a = { "mode" },
lualine_b = { "branch" },
lualine_c = { "filename" },
lualine_x = { "encoding", "fileformat", "filetype" },
lualine_y = { "progress" },
lualine_z = { "location" },
},
inactive_sections = {
lualine_a = {},
lualine_b = {},
lualine_c = { "filename" },
lualine_x = { "location" },
lualine_y = {},
lualine_z = {},
},
tabline = {},
extensions = {},
}
styles.lvim = {
style = "lvim",
options = {
theme = "auto",
icons_enabled = lvim.use_icons,
component_separators = { left = "", right = "" },
section_separators = { left = "", right = "" },
disabled_filetypes = { "alpha", "NvimTree", "Outline" },
},
sections = {
lualine_a = {
components.mode,
},
lualine_b = {
components.branch,
components.filename,
},
lualine_c = {
components.diff,
components.python_env,
},
lualine_x = {
components.diagnostics,
components.treesitter,
components.lsp,
components.filetype,
},
lualine_y = {},
lualine_z = {
components.scrollbar,
},
},
inactive_sections = {
lualine_a = {
"filename",
},
lualine_b = {},
lualine_c = {},
lualine_x = {},
lualine_y = {},
lualine_z = {},
},
tabline = {},
extensions = { "nvim-tree" },
}
function M.get_style(style)
local style_keys = vim.tbl_keys(styles)
if not vim.tbl_contains(style_keys, style) then
local Log = require "lvim.core.log"
Log:error(
"Invalid lualine style"
.. string.format('"%s"', style)
.. "options are: "
.. string.format('"%s"', table.concat(style_keys, '", "'))
)
Log:debug '"lvim" style is applied.'
style = "lvim"
end
return vim.deepcopy(styles[style])
end
function M.update()
local style = M.get_style(lvim.builtin.lualine.style)
lvim.builtin.lualine = vim.tbl_deep_extend("keep", lvim.builtin.lualine, style)
end
return M

View File

@ -0,0 +1,14 @@
local M = {}
function M.env_cleanup(venv)
if string.find(venv, "/") then
local final_venv = venv
for w in venv:gmatch "([^/]+)" do
final_venv = w
end
venv = final_venv
end
return venv
end
return M

View File

@ -0,0 +1,68 @@
local M = {}
local Log = require "lvim.core.log"
local defaults = {
active = false,
on_config_done = nil,
opts = {
---@usage Animation style one of { "fade", "slide", "fade_in_slide_out", "static" }
stages = "slide",
---@usage Function called when a new window is opened, use for changing win settings/config
on_open = nil,
---@usage Function called when a window is closed
on_close = nil,
---@usage timeout for notifications in ms, default 5000
timeout = 5000,
-- Render function for notifications. See notify-render()
render = "default",
---@usage highlight behind the window for stages that change opacity
background_colour = "Normal",
---@usage minimum width for notification windows
minimum_width = 50,
---@usage Icons for the different levels
icons = {
ERROR = "",
WARN = "",
INFO = "",
DEBUG = "",
TRACE = "",
},
},
}
function M.config()
if not lvim.use_icons then
defaults.opts.icons = {
ERROR = "[ERROR]",
WARN = "[WARNING]",
INFO = "[INFo]",
DEBUG = "[DEBUG]",
TRACE = "[TRACE]",
}
end
lvim.builtin.notify = vim.tbl_deep_extend("force", defaults, lvim.builtin.notify or {})
end
function M.setup()
if #vim.api.nvim_list_uis() == 0 then
-- no need to configure notifications in headless
return
end
local opts = lvim.builtin.notify and lvim.builtin.notify.opts or defaults
local notify = require "notify"
notify.setup(opts)
vim.notify = notify
Log:configure_notifications(notify)
end
return M

View File

@ -0,0 +1,212 @@
local M = {}
local Log = require "lvim.core.log"
function M.config()
lvim.builtin.nvimtree = {
active = true,
on_config_done = nil,
setup = {
disable_netrw = true,
hijack_netrw = true,
open_on_setup = false,
open_on_setup_file = false,
sort_by = "name",
ignore_buffer_on_setup = false,
ignore_ft_on_setup = {
"startify",
"dashboard",
"alpha",
},
auto_reload_on_write = true,
hijack_unnamed_buffer_when_opening = false,
hijack_directories = {
enable = true,
auto_open = true,
},
open_on_tab = false,
hijack_cursor = false,
update_cwd = false,
diagnostics = {
enable = lvim.use_icons,
show_on_dirs = false,
icons = {
hint = "",
info = "",
warning = "",
error = "",
},
},
update_focused_file = {
enable = true,
update_cwd = true,
ignore_list = {},
},
system_open = {
cmd = nil,
args = {},
},
git = {
enable = true,
ignore = false,
timeout = 200,
},
view = {
width = 30,
height = 30,
hide_root_folder = false,
side = "left",
preserve_window_proportions = false,
mappings = {
custom_only = false,
list = {},
},
number = false,
relativenumber = false,
signcolumn = "yes",
},
renderer = {
indent_markers = {
enable = false,
icons = {
corner = "",
edge = "",
none = " ",
},
},
icons = {
webdev_colors = lvim.use_icons,
show = {
git = lvim.use_icons,
folder = lvim.use_icons,
file = lvim.use_icons,
folder_arrow = lvim.use_icons,
},
glyphs = {
default = "",
symlink = "",
git = {
unstaged = "",
staged = "S",
unmerged = "",
renamed = "",
deleted = "",
untracked = "U",
ignored = "",
},
folder = {
default = "",
open = "",
empty = "",
empty_open = "",
symlink = "",
},
},
},
highlight_git = true,
root_folder_modifier = ":t",
},
filters = {
dotfiles = false,
custom = { "node_modules", "\\.cache" },
exclude = {},
},
trash = {
cmd = "trash",
require_confirm = true,
},
log = {
enable = false,
truncate = false,
types = {
all = false,
config = false,
copy_paste = false,
diagnostics = false,
git = false,
profile = false,
},
},
actions = {
use_system_clipboard = true,
change_dir = {
enable = true,
global = false,
restrict_above_cwd = false,
},
open_file = {
quit_on_open = false,
resize_window = false,
window_picker = {
enable = true,
chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
exclude = {
filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" },
buftype = { "nofile", "terminal", "help" },
},
},
},
},
},
}
end
function M.setup()
local status_ok, nvim_tree = pcall(require, "nvim-tree")
if not status_ok then
Log:error "Failed to load nvim-tree"
return
end
if lvim.builtin.nvimtree._setup_called then
Log:debug "ignoring repeated setup call for nvim-tree, see kyazdani42/nvim-tree.lua#1308"
return
end
-- lvim.builtin.which_key.mappings["e"] = { "<cmd>NvimTreeToggle<CR>", "Explorer" }
lvim.builtin.nvimtree._setup_called = true
-- Implicitly update nvim-tree when project module is active
if lvim.builtin.project.active then
lvim.builtin.nvimtree.setup.respect_buf_cwd = true
lvim.builtin.nvimtree.setup.update_cwd = true
lvim.builtin.nvimtree.setup.update_focused_file = { enable = true, update_cwd = true }
end
local function telescope_find_files(_)
require("lvim.core.nvimtree").start_telescope "find_files"
end
local function telescope_live_grep(_)
require("lvim.core.nvimtree").start_telescope "live_grep"
end
-- Add useful keymaps
if #lvim.builtin.nvimtree.setup.view.mappings.list == 0 then
lvim.builtin.nvimtree.setup.view.mappings.list = {
{ key = { "l", "<CR>", "o" }, action = "edit", mode = "n" },
{ key = "h", action = "close_node" },
{ key = "v", action = "vsplit" },
{ key = "C", action = "cd" },
{ key = "gtf", action = "telescope_find_files", action_cb = telescope_find_files },
{ key = "gtg", action = "telescope_live_grep", action_cb = telescope_live_grep },
}
end
nvim_tree.setup(lvim.builtin.nvimtree.setup)
if lvim.builtin.nvimtree.on_config_done then
lvim.builtin.nvimtree.on_config_done(nvim_tree)
end
end
function M.start_telescope(telescope_mode)
local node = require("nvim-tree.lib").get_node_at_cursor()
local abspath = node.link_to or node.absolute_path
local is_folder = node.open ~= nil
local basedir = is_folder and abspath or vim.fn.fnamemodify(abspath, ":h")
require("telescope.builtin")[telescope_mode] {
cwd = basedir,
}
end
return M

View File

@ -0,0 +1,52 @@
local M = {}
function M.config()
lvim.builtin.project = {
---@usage set to false to disable project.nvim.
--- This is on by default since it's currently the expected behavior.
active = true,
on_config_done = nil,
---@usage set to true to disable setting the current-woriking directory
--- Manual mode doesn't automatically change your root directory, so you have
--- the option to manually do so using `:ProjectRoot` command.
manual_mode = false,
---@usage Methods of detecting the root directory
--- Allowed values: **"lsp"** uses the native neovim lsp
--- **"pattern"** uses vim-rooter like glob pattern matching. Here
--- order matters: if one is not detected, the other is used as fallback. You
--- can also delete or rearangne the detection methods.
-- detection_methods = { "lsp", "pattern" }, -- NOTE: lsp detection will get annoying with multiple langs in one project
detection_methods = { "pattern" },
---@usage patterns used to detect root dir, when **"pattern"** is in detection_methods
patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json" },
---@ Show hidden files in telescope when searching for files in a project
show_hidden = false,
---@usage When set to false, you will get a message when project.nvim changes your directory.
-- When set to false, you will get a message when project.nvim changes your directory.
silent_chdir = true,
---@usage list of lsp client names to ignore when using **lsp** detection. eg: { "efm", ... }
ignore_lsp = {},
---@type string
---@usage path to store the project history for use in telescope
datapath = get_cache_dir(),
}
end
function M.setup()
local project = require "project_nvim"
project.setup(lvim.builtin.project)
if lvim.builtin.project.on_config_done then
lvim.builtin.project.on_config_done(project)
end
end
return M

View File

@ -0,0 +1,150 @@
local M = {}
function M.config()
-- Define this minimal config so that it's available if telescope is not yet available.
lvim.builtin.telescope = {
---@usage disable telescope completely [not recommended]
active = true,
on_config_done = nil,
}
local ok, actions = pcall(require, "telescope.actions")
if not ok then
return
end
lvim.builtin.telescope = vim.tbl_extend("force", lvim.builtin.telescope, {
defaults = {
prompt_prefix = "",
selection_caret = "",
entry_prefix = " ",
initial_mode = "insert",
selection_strategy = "reset",
sorting_strategy = "descending",
layout_strategy = "horizontal",
layout_config = {
width = 0.75,
preview_cutoff = 120,
horizontal = {
preview_width = function(_, cols, _)
if cols < 120 then
return math.floor(cols * 0.5)
end
return math.floor(cols * 0.6)
end,
mirror = false,
},
vertical = { mirror = false },
},
vimgrep_arguments = {
"rg",
"--color=never",
"--no-heading",
"--with-filename",
"--line-number",
"--column",
"--smart-case",
"--hidden",
"--glob=!.git/",
},
mappings = {
i = {
["<C-n>"] = actions.move_selection_next,
["<C-p>"] = actions.move_selection_previous,
["<C-c>"] = actions.close,
["<C-j>"] = actions.cycle_history_next,
["<C-k>"] = actions.cycle_history_prev,
["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
["<CR>"] = actions.select_default,
},
n = {
["<C-n>"] = actions.move_selection_next,
["<C-p>"] = actions.move_selection_previous,
["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
},
},
file_ignore_patterns = {},
path_display = { shorten = 5 },
winblend = 0,
border = {},
borderchars = { "", "", "", "", "", "", "", "" },
color_devicons = true,
set_env = { ["COLORTERM"] = "truecolor" }, -- default = nil,
},
pickers = {
find_files = {
hidden = true,
},
live_grep = {
--@usage don't include the filename in the search results
only_sort_text = true,
},
},
extensions = {
fzf = {
fuzzy = true, -- false will only do exact matching
override_generic_sorter = true, -- override the generic sorter
override_file_sorter = true, -- override the file sorter
case_mode = "smart_case", -- or "ignore_case" or "respect_case"
},
},
})
end
function M.setup()
local previewers = require "telescope.previewers"
local sorters = require "telescope.sorters"
local actions = require "telescope.actions"
lvim.builtin.telescope = vim.tbl_extend("keep", {
file_previewer = previewers.vim_buffer_cat.new,
grep_previewer = previewers.vim_buffer_vimgrep.new,
qflist_previewer = previewers.vim_buffer_qflist.new,
file_sorter = sorters.get_fuzzy_file,
generic_sorter = sorters.get_generic_fuzzy_sorter,
---@usage Mappings are fully customizable. Many familiar mapping patterns are setup as defaults.
mappings = {
i = {
["<C-n>"] = actions.move_selection_next,
["<C-p>"] = actions.move_selection_previous,
["<C-c>"] = actions.close,
["<C-j>"] = actions.cycle_history_next,
["<C-k>"] = actions.cycle_history_prev,
["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
["<CR>"] = actions.select_default + actions.center,
},
n = {
["<C-n>"] = actions.move_selection_next,
["<C-p>"] = actions.move_selection_previous,
["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
},
},
}, lvim.builtin.telescope)
local telescope = require "telescope"
telescope.setup(lvim.builtin.telescope)
if lvim.builtin.project.active then
pcall(function()
require("telescope").load_extension "projects"
end)
end
if lvim.builtin.notify.active then
pcall(function()
require("telescope").load_extension "notify"
end)
end
if lvim.builtin.telescope.on_config_done then
lvim.builtin.telescope.on_config_done(telescope)
end
if lvim.builtin.telescope.extensions and lvim.builtin.telescope.extensions.fzf then
pcall(function()
require("telescope").load_extension "fzf"
end)
end
end
return M

View File

@ -0,0 +1,97 @@
local M = {}
local _, builtin = pcall(require, "telescope.builtin")
local _, finders = pcall(require, "telescope.finders")
local _, pickers = pcall(require, "telescope.pickers")
local _, sorters = pcall(require, "telescope.sorters")
local _, themes = pcall(require, "telescope.themes")
local _, actions = pcall(require, "telescope.actions")
local _, previewers = pcall(require, "telescope.previewers")
local _, make_entry = pcall(require, "telescope.make_entry")
local utils = require "lvim.utils"
function M.find_lunarvim_files(opts)
opts = opts or {}
local theme_opts = themes.get_ivy {
sorting_strategy = "ascending",
layout_strategy = "bottom_pane",
prompt_prefix = ">> ",
prompt_title = "~ LunarVim files ~",
cwd = get_runtime_dir(),
search_dirs = { utils.join_paths(get_runtime_dir(), "lvim"), lvim.lsp.templates_dir },
}
opts = vim.tbl_deep_extend("force", theme_opts, opts)
builtin.find_files(opts)
end
function M.grep_lunarvim_files(opts)
opts = opts or {}
local theme_opts = themes.get_ivy {
sorting_strategy = "ascending",
layout_strategy = "bottom_pane",
prompt_prefix = ">> ",
prompt_title = "~ search LunarVim ~",
cwd = get_runtime_dir(),
search_dirs = { utils.join_paths(get_runtime_dir(), "lvim"), lvim.lsp.templates_dir },
}
opts = vim.tbl_deep_extend("force", theme_opts, opts)
builtin.live_grep(opts)
end
local copy_to_clipboard_action = function(prompt_bufnr)
local _, action_state = pcall(require, "telescope.actions.state")
local entry = action_state.get_selected_entry()
local version = entry.value
vim.fn.setreg("+", version)
vim.fn.setreg('"', version)
vim.notify("Copied " .. version .. " to clipboard", vim.log.levels.INFO)
actions.close(prompt_bufnr)
end
function M.view_lunarvim_changelog()
local opts = themes.get_ivy {
cwd = get_lvim_base_dir(),
}
opts.entry_maker = make_entry.gen_from_git_commits(opts)
pickers.new(opts, {
prompt_title = "~ LunarVim Changelog ~",
finder = finders.new_oneshot_job(
vim.tbl_flatten {
"git",
"log",
"--pretty=oneline",
"--abbrev-commit",
},
opts
),
previewer = {
previewers.git_commit_diff_as_was.new(opts),
},
--TODO: consider opening a diff view when pressing enter
attach_mappings = function(_, map)
map("i", "<enter>", copy_to_clipboard_action)
map("n", "<enter>", copy_to_clipboard_action)
map("i", "<esc>", actions._close)
map("n", "<esc>", actions._close)
map("n", "q", actions._close)
return true
end,
sorter = sorters.generic_sorter,
}):find()
end
-- Smartly opens either git_files or find_files, depending on whether the working directory is
-- contained in a Git repo.
function M.find_project_files()
local ok = pcall(builtin.git_files)
if not ok then
builtin.find_files()
end
end
return M

View File

@ -0,0 +1,127 @@
local M = {}
local Log = require "lvim.core.log"
M.config = function()
lvim.builtin["terminal"] = {
on_config_done = nil,
-- size can be a number or function which is passed the current terminal
size = 20,
-- open_mapping = [[<c-\>]],
open_mapping = [[<c-t>]],
hide_numbers = true, -- hide the number column in toggleterm buffers
shade_filetypes = {},
shade_terminals = true,
shading_factor = 2, -- the degree by which to darken to terminal colour, default: 1 for dark backgrounds, 3 for light
start_in_insert = true,
insert_mappings = true, -- whether or not the open mapping applies in insert mode
persist_size = false,
-- direction = 'vertical' | 'horizontal' | 'window' | 'float',
direction = "float",
close_on_exit = true, -- close the terminal window when the process exits
shell = vim.o.shell, -- change the default shell
-- This field is only relevant if direction is set to 'float'
float_opts = {
-- The border key is *almost* the same as 'nvim_win_open'
-- see :h nvim_win_open for details on borders however
-- the 'curved' border is a custom border type
-- not natively supported but implemented in this plugin.
-- border = 'single' | 'double' | 'shadow' | 'curved' | ... other options supported by win open
border = "curved",
-- width = <value>,
-- height = <value>,
winblend = 0,
highlights = {
border = "Normal",
background = "Normal",
},
},
-- Add executables on the config.lua
-- { exec, keymap, name}
-- lvim.builtin.terminal.execs = {{}} to overwrite
-- lvim.builtin.terminal.execs[#lvim.builtin.terminal.execs+1] = {"gdb", "tg", "GNU Debugger"}
execs = {
{ "lazygit", "<leader>gg", "LazyGit", "float" },
{ "lazygit", "<c-\\><c-g>", "LazyGit", "float" },
},
}
end
M.setup = function()
local terminal = require "toggleterm"
terminal.setup(lvim.builtin.terminal)
for i, exec in pairs(lvim.builtin.terminal.execs) do
local opts = {
cmd = exec[1],
keymap = exec[2],
label = exec[3],
-- NOTE: unable to consistently bind id/count <= 9, see #2146
count = i + 100,
direction = exec[4] or lvim.builtin.terminal.direction,
size = lvim.builtin.terminal.size,
}
M.add_exec(opts)
end
if lvim.builtin.terminal.on_config_done then
lvim.builtin.terminal.on_config_done(terminal)
end
end
M.add_exec = function(opts)
local binary = opts.cmd:match "(%S+)"
if vim.fn.executable(binary) ~= 1 then
Log:debug("Skipping configuring executable " .. binary .. ". Please make sure it is installed properly.")
return
end
local exec_func = string.format(
"<cmd>lua require('lvim.core.terminal')._exec_toggle({ cmd = '%s', count = %d, direction = '%s'})<CR>",
opts.cmd,
opts.count,
opts.direction
)
require("lvim.keymappings").load {
normal_mode = { [opts.keymap] = exec_func },
term_mode = { [opts.keymap] = exec_func },
}
local wk_status_ok, wk = pcall(require, "which-key")
if not wk_status_ok then
return
end
wk.register({ [opts.keymap] = { opts.label } }, { mode = "n" })
end
M._exec_toggle = function(opts)
local Terminal = require("toggleterm.terminal").Terminal
local term = Terminal:new { cmd = opts.cmd, count = opts.count, direction = opts.direction }
term:toggle(lvim.builtin.terminal.size, opts.direction)
end
---Toggles a log viewer according to log.viewer.layout_config
---@param logfile string the fullpath to the logfile
M.toggle_log_view = function(logfile)
local log_viewer = lvim.log.viewer.cmd
if vim.fn.executable(log_viewer) ~= 1 then
log_viewer = "less +F"
end
Log:debug("attempting to open: " .. logfile)
log_viewer = log_viewer .. " " .. logfile
local term_opts = vim.tbl_deep_extend("force", lvim.builtin.terminal, {
cmd = log_viewer,
open_mapping = lvim.log.viewer.layout_config.open_mapping,
direction = lvim.log.viewer.layout_config.direction,
-- TODO: this might not be working as expected
size = lvim.log.viewer.layout_config.size,
float_opts = lvim.log.viewer.layout_config.float_opts,
})
local Terminal = require("toggleterm.terminal").Terminal
local log_view = Terminal:new(term_opts)
log_view:toggle()
end
return M

View File

@ -0,0 +1,97 @@
local M = {}
local Log = require "lvim.core.log"
M.config = function()
lvim.builtin.treesitter = {
on_config_done = nil,
ensure_installed = {}, -- one of "all", "maintained" (parsers with maintainers), or a list of languages
ignore_install = {},
matchup = {
enable = false, -- mandatory, false will disable the whole extension
-- disable = { "c", "ruby" }, -- optional, list of language that will be disabled
},
highlight = {
enable = true, -- false will disable the whole extension
additional_vim_regex_highlighting = false,
disable = { "latex" },
},
context_commentstring = {
enable = true,
enable_autocmd = false,
config = {
-- Languages that have a single comment style
typescript = "// %s",
css = "/* %s */",
scss = "/* %s */",
html = "<!-- %s -->",
svelte = "<!-- %s -->",
vue = "<!-- %s -->",
json = "",
},
},
indent = { enable = true, disable = { "yaml", "python" } },
autotag = { enable = false },
textobjects = {
swap = {
enable = false,
-- swap_next = textobj_swap_keymaps,
},
-- move = textobj_move_keymaps,
select = {
enable = false,
-- keymaps = textobj_sel_keymaps,
},
},
textsubjects = {
enable = false,
keymaps = { ["."] = "textsubjects-smart", [";"] = "textsubjects-big" },
},
playground = {
enable = false,
disable = {},
updatetime = 25, -- Debounced time for highlighting nodes in the playground from source code
persist_queries = false, -- Whether the query persists across vim sessions
keybindings = {
toggle_query_editor = "o",
toggle_hl_groups = "i",
toggle_injected_languages = "t",
toggle_anonymous_nodes = "a",
toggle_language_display = "I",
focus_language = "f",
unfocus_language = "F",
update = "R",
goto_node = "<cr>",
show_help = "?",
},
},
rainbow = {
enable = false,
extended_mode = true, -- Highlight also non-parentheses delimiters, boolean or table: lang -> boolean
max_file_lines = 1000, -- Do not enable for files with more than 1000 lines, int
},
}
end
M.setup = function()
-- avoid running in headless mode since it's harder to detect failures
if #vim.api.nvim_list_uis() == 0 then
Log:debug "headless mode detected, skipping running setup for treesitter"
return
end
local status_ok, treesitter_configs = pcall(require, "nvim-treesitter.configs")
if not status_ok then
Log:error "Failed to load nvim-treesitter.configs"
return
end
local opts = vim.deepcopy(lvim.builtin.treesitter)
treesitter_configs.setup(opts)
if lvim.builtin.treesitter.on_config_done then
lvim.builtin.treesitter.on_config_done(treesitter_configs)
end
end
return M

View File

@ -0,0 +1,286 @@
local M = {}
M.config = function()
lvim.builtin.which_key = {
---@usage disable which-key completely [not recommended]
active = true,
on_config_done = nil,
setup = {
plugins = {
marks = true, -- shows a list of your marks on ' and `
registers = true, -- shows your registers on " in NORMAL or <C-r> in INSERT mode
-- the presets plugin, adds help for a bunch of default keybindings in Neovim
-- No actual key bindings are created
presets = {
operators = false, -- adds help for operators like d, y, ...
motions = false, -- adds help for motions
text_objects = false, -- help for text objects triggered after entering an operator
windows = false, -- default bindings on <c-w>
nav = true, -- misc bindings to work with windows
z = true, -- bindings for folds, spelling and others prefixed with z
g = true, -- bindings for prefixed with g
},
spelling = { enabled = true, suggestions = 20 }, -- use which-key for spelling hints
},
icons = {
breadcrumb = "»", -- symbol used in the command line area that shows your active key combo
separator = "", -- symbol used between a key and it's label
group = "+", -- symbol prepended to a group
},
popup_mappings = {
scroll_down = "<c-d>", -- binding to scroll down inside the popup
scroll_up = "<c-u>", -- binding to scroll up inside the popup
},
window = {
border = "single", -- none, single, double, shadow
position = "bottom", -- bottom, top
margin = { 1, 0, 1, 0 }, -- extra window margin [top, right, bottom, left]
padding = { 2, 2, 2, 2 }, -- extra window padding [top, right, bottom, left]
winblend = 0,
},
layout = {
height = { min = 4, max = 25 }, -- min and max height of the columns
width = { min = 20, max = 50 }, -- min and max width of the columns
spacing = 3, -- spacing between columns
align = "left", -- align columns left, center or right
},
hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate
ignore_missing = false, -- enable this to hide mappings for which you didn't specify a label
show_help = true, -- show help message on the command line when the popup is visible
triggers = "auto", -- automatically setup triggers
-- triggers = {"<leader>"} -- or specify a list manually
triggers_blacklist = {
-- list of mode / prefixes that should never be hooked by WhichKey
-- this is mostly relevant for key maps that start with a native binding
-- most people should not need to change this
i = { "j", "k" },
v = { "j", "k" },
},
},
opts = {
mode = "n", -- NORMAL mode
prefix = "<leader>",
buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings
silent = true, -- use `silent` when creating keymaps
noremap = true, -- use `noremap` when creating keymaps
nowait = true, -- use `nowait` when creating keymaps
},
vopts = {
mode = "v", -- VISUAL mode
prefix = "<leader>",
buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings
silent = true, -- use `silent` when creating keymaps
noremap = true, -- use `noremap` when creating keymaps
nowait = true, -- use `nowait` when creating keymaps
},
-- NOTE: Prefer using : over <cmd> as the latter avoids going back in normal-mode.
-- see https://neovim.io/doc/user/map.html#:map-cmd
vmappings = {
["/"] = { "<ESC><CMD>lua require('Comment.api').toggle_linewise_op(vim.fn.visualmode())<CR>", "Comment" },
},
mappings = {
[";"] = { "<cmd>Alpha<CR>", "Dashboard" },
["w"] = { "<cmd>w!<CR>", "Save" },
["q"] = { "<cmd>lua require('lvim.utils.functions').smart_quit()<CR>", "Quit" },
["/"] = { "<cmd>lua require('Comment.api').toggle_current_linewise()<CR>", "Comment" },
["c"] = { "<cmd>BufferKill<CR>", "Close Buffer" },
["f"] = { require("lvim.core.telescope.custom-finders").find_project_files, "Find File" },
["h"] = { "<cmd>nohlsearch<CR>", "No Highlight" },
b = {
name = "Buffers",
j = { "<cmd>BufferLinePick<cr>", "Jump" },
f = { "<cmd>Telescope buffers<cr>", "Find" },
b = { "<cmd>BufferLineCyclePrev<cr>", "Previous" },
-- w = { "<cmd>BufferWipeout<cr>", "Wipeout" }, -- TODO: implement this for bufferline
e = {
"<cmd>BufferLinePickClose<cr>",
"Pick which buffer to close",
},
h = { "<cmd>BufferLineCloseLeft<cr>", "Close all to the left" },
l = {
"<cmd>BufferLineCloseRight<cr>",
"Close all to the right",
},
D = {
"<cmd>BufferLineSortByDirectory<cr>",
"Sort by directory",
},
L = {
"<cmd>BufferLineSortByExtension<cr>",
"Sort by language",
},
},
p = {
name = "Packer",
c = { "<cmd>PackerCompile<cr>", "Compile" },
i = { "<cmd>PackerInstall<cr>", "Install" },
r = { "<cmd>lua require('lvim.plugin-loader').recompile()<cr>", "Re-compile" },
s = { "<cmd>PackerSync<cr>", "Sync" },
S = { "<cmd>PackerStatus<cr>", "Status" },
u = { "<cmd>PackerUpdate<cr>", "Update" },
},
-- " Available Debug Adapters:
-- " https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/
-- " Adapter configuration and installation instructions:
-- " https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation
-- " Debug Adapter protocol:
-- " https://microsoft.github.io/debug-adapter-protocol/
-- " Debugging
g = {
name = "Git",
j = { "<cmd>lua require 'gitsigns'.next_hunk()<cr>", "Next Hunk" },
k = { "<cmd>lua require 'gitsigns'.prev_hunk()<cr>", "Prev Hunk" },
l = { "<cmd>lua require 'gitsigns'.blame_line()<cr>", "Blame" },
p = { "<cmd>lua require 'gitsigns'.preview_hunk()<cr>", "Preview Hunk" },
r = { "<cmd>lua require 'gitsigns'.reset_hunk()<cr>", "Reset Hunk" },
R = { "<cmd>lua require 'gitsigns'.reset_buffer()<cr>", "Reset Buffer" },
s = { "<cmd>lua require 'gitsigns'.stage_hunk()<cr>", "Stage Hunk" },
u = {
"<cmd>lua require 'gitsigns'.undo_stage_hunk()<cr>",
"Undo Stage Hunk",
},
o = { "<cmd>Telescope git_status<cr>", "Open changed file" },
b = { "<cmd>Telescope git_branches<cr>", "Checkout branch" },
c = { "<cmd>Telescope git_commits<cr>", "Checkout commit" },
C = {
"<cmd>Telescope git_bcommits<cr>",
"Checkout commit(for current file)",
},
d = {
"<cmd>Gitsigns diffthis HEAD<cr>",
"Git Diff",
},
},
l = {
name = "LSP",
a = { "<cmd>lua vim.lsp.buf.code_action()<cr>", "Code Action" },
d = { "<cmd>Telescope diagnostics bufnr=0 theme=get_ivy<cr>", "Buffer Diagnostics" },
w = { "<cmd>Telescope diagnostics<cr>", "Diagnostics" },
f = { require("lvim.lsp.utils").format, "Format" },
i = { "<cmd>LspInfo<cr>", "Info" },
I = { "<cmd>LspInstallInfo<cr>", "Installer Info" },
j = {
vim.diagnostic.goto_next,
"Next Diagnostic",
},
k = {
vim.diagnostic.goto_prev,
"Prev Diagnostic",
},
l = { vim.lsp.codelens.run, "CodeLens Action" },
p = {
name = "Peek",
d = { "<cmd>lua require('lvim.lsp.peek').Peek('definition')<cr>", "Definition" },
t = { "<cmd>lua require('lvim.lsp.peek').Peek('typeDefinition')<cr>", "Type Definition" },
i = { "<cmd>lua require('lvim.lsp.peek').Peek('implementation')<cr>", "Implementation" },
},
q = { vim.diagnostic.setloclist, "Quickfix" },
r = { vim.lsp.buf.rename, "Rename" },
s = { "<cmd>Telescope lsp_document_symbols<cr>", "Document Symbols" },
S = {
"<cmd>Telescope lsp_dynamic_workspace_symbols<cr>",
"Workspace Symbols",
},
e = { "<cmd>Telescope quickfix<cr>", "Telescope Quickfix" },
},
L = {
name = "+LunarVim",
c = {
"<cmd>edit " .. get_config_dir() .. "/config.lua<cr>",
"Edit config.lua",
},
f = {
"<cmd>lua require('lvim.core.telescope.custom-finders').find_lunarvim_files()<cr>",
"Find LunarVim files",
},
g = {
"<cmd>lua require('lvim.core.telescope.custom-finders').grep_lunarvim_files()<cr>",
"Grep LunarVim files",
},
k = { "<cmd>Telescope keymaps<cr>", "View LunarVim's keymappings" },
i = {
"<cmd>lua require('lvim.core.info').toggle_popup(vim.bo.filetype)<cr>",
"Toggle LunarVim Info",
},
I = {
"<cmd>lua require('lvim.core.telescope.custom-finders').view_lunarvim_changelog()<cr>",
"View LunarVim's changelog",
},
l = {
name = "+logs",
d = {
"<cmd>lua require('lvim.core.terminal').toggle_log_view(require('lvim.core.log').get_path())<cr>",
"view default log",
},
D = {
"<cmd>lua vim.fn.execute('edit ' .. require('lvim.core.log').get_path())<cr>",
"Open the default logfile",
},
l = {
"<cmd>lua require('lvim.core.terminal').toggle_log_view(vim.lsp.get_log_path())<cr>",
"view lsp log",
},
L = { "<cmd>lua vim.fn.execute('edit ' .. vim.lsp.get_log_path())<cr>", "Open the LSP logfile" },
n = {
"<cmd>lua require('lvim.core.terminal').toggle_log_view(os.getenv('NVIM_LOG_FILE'))<cr>",
"view neovim log",
},
N = { "<cmd>edit $NVIM_LOG_FILE<cr>", "Open the Neovim logfile" },
p = {
"<cmd>lua require('lvim.core.terminal').toggle_log_view(get_cache_dir() .. '/packer.nvim.log')<cr>",
"view packer log",
},
P = { "<cmd>edit $LUNARVIM_CACHE_DIR/packer.nvim.log<cr>", "Open the Packer logfile" },
},
n = { "<cmd>Telescope notify<cr>", "View Notifications" },
r = { "<cmd>LvimReload<cr>", "Reload LunarVim's configuration" },
u = { "<cmd>LvimUpdate<cr>", "Update LunarVim" },
},
s = {
name = "Search",
b = { "<cmd>Telescope git_branches<cr>", "Checkout branch" },
c = { "<cmd>Telescope colorscheme<cr>", "Colorscheme" },
f = { "<cmd>Telescope find_files<cr>", "Find File" },
h = { "<cmd>Telescope help_tags<cr>", "Find Help" },
H = { "<cmd>Telescope highlights<cr>", "Find highlight groups" },
M = { "<cmd>Telescope man_pages<cr>", "Man Pages" },
r = { "<cmd>Telescope oldfiles<cr>", "Open Recent File" },
R = { "<cmd>Telescope registers<cr>", "Registers" },
t = { "<cmd>Telescope live_grep<cr>", "Text" },
k = { "<cmd>Telescope keymaps<cr>", "Keymaps" },
C = { "<cmd>Telescope commands<cr>", "Commands" },
p = {
"<cmd>lua require('telescope.builtin.internal').colorscheme({enable_preview = true})<cr>",
"Colorscheme with Preview",
},
},
T = {
name = "Treesitter",
i = { ":TSConfigInfo<cr>", "Info" },
},
},
}
end
M.setup = function()
local which_key = require "which-key"
which_key.setup(lvim.builtin.which_key.setup)
local opts = lvim.builtin.which_key.opts
local vopts = lvim.builtin.which_key.vopts
local mappings = lvim.builtin.which_key.mappings
local vmappings = lvim.builtin.which_key.vmappings
which_key.register(mappings, opts)
which_key.register(vmappings, vopts)
if lvim.builtin.which_key.on_config_done then
lvim.builtin.which_key.on_config_done(which_key)
end
end
return M

View File

@ -0,0 +1,364 @@
-- modified version from https://github.com/lewis6991/impatient.nvim
local vim = vim
local api = vim.api
local uv = vim.loop
local _loadfile = loadfile
local get_runtime = api.nvim__get_runtime
local fs_stat = uv.fs_stat
local mpack = vim.mpack
local appdir = os.getenv "APPDIR"
local M = {
chunks = {
cache = {},
profile = nil,
dirty = false,
path = vim.fn.stdpath "cache" .. "/luacache_chunks",
},
modpaths = {
cache = {},
profile = nil,
dirty = false,
path = vim.fn.stdpath "cache" .. "/luacache_modpaths",
},
log = {},
}
_G.__luacache = M
if not get_runtime then
-- nvim 0.5 compat
get_runtime = function(paths, all, _)
local r = {}
for _, path in ipairs(paths) do
local found = api.nvim_get_runtime_file(path, all)
for i = 1, #found do
r[#r + 1] = found[i]
end
end
return r
end
end
local function log(...)
M.log[#M.log + 1] = table.concat({ string.format(...) }, " ")
end
function M.print_log()
for _, l in ipairs(M.log) do
print(l)
end
end
function M.enable_profile()
local P = require "lvim.impatient.profile"
M.chunks.profile = {}
M.modpaths.profile = {}
P.setup(M.modpaths.profile)
M.print_profile = function()
P.print_profile(M)
end
vim.cmd [[command! LuaCacheProfile lua _G.__luacache.print_profile()]]
end
local function hash(modpath)
local stat = fs_stat(modpath)
if stat then
return stat.mtime.sec .. stat.mtime.nsec .. stat.size
end
error("Could not hash " .. modpath)
end
local function modpath_mangle(modpath)
if appdir then
modpath = modpath:gsub(appdir, "/$APPDIR")
end
return modpath
end
local function modpath_unmangle(modpath)
if appdir then
modpath = modpath:gsub("/$APPDIR", appdir)
end
return modpath
end
local function profile(m, entry, name, loader)
if m.profile then
local mp = m.profile
mp[entry] = mp[entry] or {}
if not mp[entry].loader and loader then
mp[entry].loader = loader
end
if not mp[entry][name] then
mp[entry][name] = uv.hrtime()
end
end
end
local function mprofile(mod, name, loader)
profile(M.modpaths, mod, name, loader)
end
local function cprofile(path, name, loader)
profile(M.chunks, path, name, loader)
end
local function get_runtime_file(basename, paths)
-- Look in the cache to see if we have already loaded a parent module.
-- If we have then try looking in the parents directory first.
local parents = vim.split(basename, "/")
for i = #parents, 1, -1 do
local parent = table.concat(vim.list_slice(parents, 1, i), "/")
local ppath = M.modpaths.cache[parent]
if ppath then
if ppath:sub(-9) == "/init.lua" then
ppath = ppath:sub(1, -10) -- a/b/init.lua -> a/b
else
ppath = ppath:sub(1, -5) -- a/b.lua -> a/b
end
for _, path in ipairs(paths) do
-- path should be of form 'a/b/c.lua' or 'a/b/c/init.lua'
local modpath = ppath .. "/" .. path:sub(#("lua/" .. parent) + 2)
if fs_stat(modpath) then
return modpath, "cache(p)"
end
end
end
end
-- What Neovim does by default; slowest
local modpath = get_runtime(paths, false, { is_lua = true })[1]
return modpath, "standard"
end
local function get_runtime_file_cached(basename, paths)
local mp = M.modpaths
if mp.cache[basename] then
local modpath = mp.cache[basename]
if fs_stat(modpath) then
mprofile(basename, "resolve_end", "cache")
return modpath
end
mp.cache[basename] = nil
mp.dirty = true
end
local modpath, loader = get_runtime_file(basename, paths)
if modpath then
mprofile(basename, "resolve_end", loader)
log("Creating cache for module %s", basename)
mp.cache[basename] = modpath_mangle(modpath)
mp.dirty = true
end
return modpath
end
local function extract_basename(pats)
local basename
-- Deconstruct basename from pats
for _, pat in ipairs(pats) do
for i, npat in ipairs {
-- Ordered by most specific
"lua/(.*)/init%.lua",
"lua/(.*)%.lua",
} do
local m = pat:match(npat)
if i == 2 and m and m:sub(-4) == "init" then
m = m:sub(0, -6)
end
if not basename then
if m then
basename = m
end
elseif m and m ~= basename then
-- matches are inconsistent
return
end
end
end
return basename
end
local function get_runtime_cached(pats, all, opts)
local fallback = false
if all or not opts or not opts.is_lua then
-- Fallback
fallback = true
end
local basename
if not fallback then
basename = extract_basename(pats)
end
if fallback or not basename then
return get_runtime(pats, all, opts)
end
return { get_runtime_file_cached(basename, pats) }
end
-- Copied from neovim/src/nvim/lua/vim.lua with two lines changed
local function load_package(name)
local basename = name:gsub("%.", "/")
local paths = { "lua/" .. basename .. ".lua", "lua/" .. basename .. "/init.lua" }
-- Original line:
-- local found = vim.api.nvim__get_runtime(paths, false, {is_lua=true})
local found = { get_runtime_file_cached(basename, paths) }
if #found > 0 then
local f, err = loadfile(found[1])
return f or error(err)
end
local so_paths = {}
for _, trail in ipairs(vim._so_trails) do
local path = "lua" .. trail:gsub("?", basename) -- so_trails contains a leading slash
table.insert(so_paths, path)
end
-- Original line:
-- found = vim.api.nvim__get_runtime(so_paths, false, {is_lua=true})
found = { get_runtime_file_cached(basename, so_paths) }
if #found > 0 then
-- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
-- a) strip prefix up to and including the first dash, if any
-- b) replace all dots by underscores
-- c) prepend "luaopen_"
-- So "foo-bar.baz" should result in "luaopen_bar_baz"
local dash = name:find("-", 1, true)
local modname = dash and name:sub(dash + 1) or name
local f, err = package.loadlib(found[1], "luaopen_" .. modname:gsub("%.", "_"))
return f or error(err)
end
return nil
end
local function load_from_cache(path)
local mc = M.chunks
if not mc.cache[path] then
return nil, string.format("No cache for path %s", path)
end
local mhash, codes = unpack(mc.cache[path])
if mhash ~= hash(modpath_unmangle(path)) then
mc.cache[path] = nil
mc.dirty = true
return nil, string.format("Stale cache for path %s", path)
end
local chunk = loadstring(codes)
if not chunk then
mc.cache[path] = nil
mc.dirty = true
return nil, string.format("Cache error for path %s", path)
end
return chunk
end
local function loadfile_cached(path)
cprofile(path, "load_start")
local chunk, err = load_from_cache(path)
if chunk and not err then
log("Loaded cache for path %s", path)
cprofile(path, "load_end", "cache")
return chunk
end
log(err)
chunk, err = _loadfile(path)
if not err then
log("Creating cache for path %s", path)
M.chunks.cache[modpath_mangle(path)] = { hash(path), string.dump(chunk) }
M.chunks.dirty = true
end
cprofile(path, "load_end", "standard")
return chunk, err
end
function M.save_cache()
local function _save_cache(t)
if t.dirty then
log("Updating chunk cache file: %s", t.path)
local f = io.open(t.path, "w+b")
f:write(mpack.encode(t.cache))
f:flush()
t.dirty = false
end
end
_save_cache(M.chunks)
_save_cache(M.modpaths)
end
function M.clear_cache()
local function _clear_cache(t)
t.cache = {}
os.remove(t.path)
end
_clear_cache(M.chunks)
_clear_cache(M.modpaths)
end
local function init_cache()
local function _init_cache(t)
if fs_stat(t.path) then
log("Loading cache file %s", t.path)
local f = io.open(t.path, "rb")
local ok
ok, t.cache = pcall(function()
return mpack.decode(f:read "*a")
end)
if not ok then
log("Corrupted cache file, %s. Invalidating...", t.path)
os.remove(t.path)
t.cache = {}
end
t.dirty = not ok
end
end
_init_cache(M.chunks)
_init_cache(M.modpaths)
end
local function setup()
init_cache()
-- Override default functions
vim._load_package = load_package
vim.api.nvim__get_runtime = get_runtime_cached
-- luacheck: ignore 121
loadfile = loadfile_cached
vim.cmd [[
augroup impatient
autocmd VimEnter,VimLeave * lua _G.__luacache.save_cache()
augroup END
command! LuaCacheClear lua _G.__luacache.clear_cache()
command! LuaCacheLog lua _G.__luacache.print_log()
]]
end
setup()
return M

View File

@ -0,0 +1,242 @@
local M = {}
local api, uv = vim.api, vim.loop
local std_data = vim.fn.stdpath "data"
local std_config = vim.fn.stdpath "config"
local vimruntime = os.getenv "VIMRUNTIME"
local lvim_runtime = get_runtime_dir()
local lvim_config = get_config_dir()
local function load_buffer(title, lines)
local bufnr = api.nvim_create_buf(false, false)
api.nvim_buf_set_lines(bufnr, 0, 0, false, lines)
api.nvim_buf_set_option(bufnr, "bufhidden", "wipe")
api.nvim_buf_set_option(bufnr, "buftype", "nofile")
api.nvim_buf_set_option(bufnr, "swapfile", false)
api.nvim_buf_set_option(bufnr, "modifiable", false)
api.nvim_buf_set_name(bufnr, title)
api.nvim_set_current_buf(bufnr)
end
local function mod_path(path)
if not path then
return "?"
end
path = path:gsub(std_data .. "/site/pack/packer/", "<PACKER>/")
path = path:gsub(std_data .. "/", "<STD_DATA>/")
path = path:gsub(std_config .. "/", "<STD_CONFIG>/")
path = path:gsub(vimruntime .. "/", "<VIMRUNTIME>/")
path = path:gsub(lvim_runtime .. "/", "<LVIM_RUNTIME>/")
path = path:gsub(lvim_config .. "/", "<LVIM_CONFIG>/")
return path
end
local function time_tostr(x)
if x == 0 then
return "?"
end
return string.format("%8.3fms", x)
end
local function mem_tostr(x)
local unit = ""
for _, u in ipairs { "K", "M", "G" } do
if x < 1000 then
break
end
x = x / 1000
unit = u
end
return string.format("%1.1f%s", x, unit)
end
function M.print_profile(I)
local mod_profile = I.modpaths.profile
local chunk_profile = I.chunks.profile
if not mod_profile and not chunk_profile then
print "Error: profiling was not enabled"
return
end
local total_resolve = 0
local total_load = 0
local modules = {}
for path, m in pairs(chunk_profile) do
m.load = m.load_end - m.load_start
m.load = m.load / 1000000
m.path = mod_path(path)
end
local module_content_width = 0
for module, m in pairs(mod_profile) do
m.resolve = 0
if m.resolve_end then
m.resolve = m.resolve_end - m.resolve_start
m.resolve = m.resolve / 1000000
end
m.module = module:gsub("/", ".")
m.loader = m.loader or m.loader_guess
local path = I.modpaths.cache[module]
local path_prof = chunk_profile[path]
m.path = mod_path(path)
if path_prof then
chunk_profile[path] = nil
m.load = path_prof.load
m.ploader = path_prof.loader
else
m.load = 0
m.ploader = "NA"
end
total_resolve = total_resolve + m.resolve
total_load = total_load + m.load
if #module > module_content_width then
module_content_width = #module
end
modules[#modules + 1] = m
end
table.sort(modules, function(a, b)
return (a.resolve + a.load) > (b.resolve + b.load)
end)
local paths = {}
local total_paths_load = 0
for _, m in pairs(chunk_profile) do
paths[#paths + 1] = m
total_paths_load = total_paths_load + m.load
end
table.sort(paths, function(a, b)
return a.load > b.load
end)
local lines = {}
local function add(fmt, ...)
local args = { ... }
for i, a in ipairs(args) do
if type(a) == "number" then
args[i] = time_tostr(a)
end
end
lines[#lines + 1] = string.format(fmt, unpack(args))
end
local time_cell_width = 12
local loader_cell_width = 11
local time_content_width = time_cell_width - 2
local loader_content_width = loader_cell_width - 2
local module_cell_width = module_content_width + 2
local tcwl = string.rep("", time_cell_width)
local lcwl = string.rep("", loader_cell_width)
local mcwl = string.rep("", module_cell_width + 2)
local n = string.rep("", 200)
local module_cell_format = "%-" .. module_cell_width .. "s"
local loader_format = "%-" .. loader_content_width .. "s"
local line_format = "%s │ %s │ %s │ %s │ %s │ %s"
local row_fmt = line_format:format(
" %" .. time_content_width .. "s",
loader_format,
"%" .. time_content_width .. "s",
loader_format,
module_cell_format,
"%s"
)
local title_fmt = line_format:format(
" %-" .. time_content_width .. "s",
loader_format,
"%-" .. time_content_width .. "s",
loader_format,
module_cell_format,
"%s"
)
local title1_width = time_cell_width + loader_cell_width - 1
local title1_fmt = ("%s │ %s │"):format(" %-" .. title1_width .. "s", "%-" .. title1_width .. "s")
add "Note: this report is not a measure of startup time. Only use this for comparing"
add "between cached and uncached loads of Lua modules"
add ""
add "Cache files:"
for _, f in ipairs { I.chunks.path, I.modpaths.path } do
local size = vim.loop.fs_stat(f).size
add(" %s %s", f, mem_tostr(size))
end
add ""
add("%s─%s┬%s─%s┐", tcwl, lcwl, tcwl, lcwl)
add(title1_fmt, "Resolve", "Load")
add("%s┬%s┼%s┬%s┼%s┬%s", tcwl, lcwl, tcwl, lcwl, mcwl, n)
add(title_fmt, "Time", "Method", "Time", "Method", "Module", "Path")
add("%s┼%s┼%s┼%s┼%s┼%s", tcwl, lcwl, tcwl, lcwl, mcwl, n)
add(row_fmt, total_resolve, "", total_load, "", "Total", "")
add("%s┼%s┼%s┼%s┼%s┼%s", tcwl, lcwl, tcwl, lcwl, mcwl, n)
for _, p in ipairs(modules) do
add(row_fmt, p.resolve, p.loader, p.load, p.ploader, p.module, p.path)
end
add("%s┴%s┴%s┴%s┴%s┴%s", tcwl, lcwl, tcwl, lcwl, mcwl, n)
if #paths > 0 then
add ""
add(n)
local f3 = " %" .. time_content_width .. "s │ %" .. loader_content_width .. "s │ %s"
add "Files loaded with no associated module"
add("%s┬%s┬%s", tcwl, lcwl, n)
add(f3, "Time", "Loader", "Path")
add("%s┼%s┼%s", tcwl, lcwl, n)
add(f3, total_paths_load, "", "Total")
add("%s┼%s┼%s", tcwl, lcwl, n)
for _, p in ipairs(paths) do
add(f3, p.load, p.loader, p.path)
end
add("%s┴%s┴%s", tcwl, lcwl, n)
add ""
end
load_buffer("Impatient Profile Report", lines)
end
M.setup = function(profile)
local _require = require
-- luacheck: ignore 121
require = function(mod)
local basename = mod:gsub("%.", "/")
if not profile[basename] then
profile[basename] = {}
profile[basename].resolve_start = uv.hrtime()
profile[basename].loader_guess = "C"
end
return _require(mod)
end
-- Add profiling around all the loaders
local pl = package.loaders
for i = 1, #pl do
local l = pl[i]
pl[i] = function(mod)
local basename = mod:gsub("%.", "/")
profile[basename].loader_guess = i == 1 and "preloader" or "loader #" .. i
return l(mod)
end
end
end
return M

View File

@ -0,0 +1,64 @@
local Popup = {}
--- Create a new floating window
-- @param config The configuration passed to vim.api.nvim_open_win
-- @param win_opts The options registered with vim.api.nvim_win_set_option
-- @param buf_opts The options registered with vim.api.nvim_buf_set_option
-- @return A new popup
function Popup:new(opts)
opts = opts or {}
opts.layout = opts.layout or {}
opts.win_opts = opts.win_opts or {}
opts.buf_opts = opts.buf_opts or {}
Popup.__index = Popup
local editor_layout = {
height = vim.o.lines - vim.o.cmdheight - 2, -- Add margin for status and buffer line
width = vim.o.columns,
}
local popup_layout = {
relative = "editor",
height = math.floor(editor_layout.height * 0.9),
width = math.floor(editor_layout.width * 0.8),
style = "minimal",
border = "rounded",
}
popup_layout.row = math.floor((editor_layout.height - popup_layout.height) / 2)
popup_layout.col = math.floor((editor_layout.width - popup_layout.width) / 2)
local obj = {
buffer = vim.api.nvim_create_buf(false, true),
layout = vim.tbl_deep_extend("force", popup_layout, opts.layout),
win_opts = opts.win_opts,
buf_opts = opts.buf_opts,
}
setmetatable(obj, Popup)
return obj
end
--- Display the popup with the provided content
-- @param content_provider A function accepting the popup's layout and returning the content to display
function Popup:display(content_provider)
self.win_id = vim.api.nvim_open_win(self.buffer, true, self.layout)
vim.api.nvim_command(
string.format("autocmd BufHidden,BufLeave <buffer> ++once lua pcall(vim.api.nvim_win_close, %d, true)", self.win_id)
)
local lines = content_provider(self.layout)
vim.api.nvim_buf_set_lines(self.bufnr or 0, 0, -1, false, lines)
-- window options
for key, value in pairs(self.win_opts) do
vim.api.nvim_win_set_option(self.win_id or 0, key, value)
end
-- buffer options
for key, value in pairs(self.buf_opts) do
vim.api.nvim_buf_set_option(self.buffer, key, value)
end
end
return Popup

View File

@ -0,0 +1,95 @@
local M = {}
local function max_len_line(lines)
local max_len = 0
for _, line in ipairs(lines) do
local line_len = line:len()
if line_len > max_len then
max_len = line_len
end
end
return max_len
end
--- Left align lines relatively to the parent container
-- @param container The container where lines will be displayed
-- @param lines The text to align
-- @param alignment The alignment value, range: [0-1]
function M.align_left(container, lines, alignment)
local max_len = max_len_line(lines)
local indent_amount = math.ceil(math.max(container.width - max_len, 0) * alignment)
return M.shift_right(lines, indent_amount)
end
--- Center align lines relatively to the parent container
-- @param container The container where lines will be displayed
-- @param lines The text to align
-- @param alignment The alignment value, range: [0-1]
function M.align_center(container, lines, alignment)
local output = {}
local max_len = max_len_line(lines)
for _, line in ipairs(lines) do
local padding = string.rep(" ", (math.max(container.width, max_len) - line:len()) * alignment)
table.insert(output, padding .. line)
end
return output
end
--- Shift lines by a given amount
-- @params lines The lines the shift
-- @param amount The amount of spaces to add
function M.shift_right(lines, amount)
local output = {}
local padding = string.rep(" ", amount)
for _, line in ipairs(lines) do
table.insert(output, padding .. line)
end
return output
end
--- Pretty format tables
-- @param entries The table to format
-- @param col_count The number of column to span the table on
-- @param col_sep The separator between each column, default: " "
function M.format_table(entries, col_count, col_sep)
col_sep = col_sep or " "
local col_rows = math.ceil(vim.tbl_count(entries) / col_count)
local cols = {}
local count = 0
for i, entry in ipairs(entries) do
if ((i - 1) % col_rows) == 0 then
table.insert(cols, {})
count = count + 1
end
table.insert(cols[count], entry)
end
local col_max_len = {}
for _, col in ipairs(cols) do
table.insert(col_max_len, max_len_line(col))
end
local output = {}
for i, col in ipairs(cols) do
for j, entry in ipairs(col) do
if not output[j] then
output[j] = entry
else
local padding = string.rep(" ", col_max_len[i - 1] - cols[i - 1][j]:len())
output[j] = output[j] .. padding .. col_sep .. entry
end
end
end
return output
end
return M

View File

@ -0,0 +1,203 @@
local M = {}
local Log = require "lvim.core.log"
local generic_opts_any = { noremap = true, silent = true }
local generic_opts = {
insert_mode = generic_opts_any,
normal_mode = generic_opts_any,
visual_mode = generic_opts_any,
visual_block_mode = generic_opts_any,
command_mode = generic_opts_any,
term_mode = { silent = true },
}
local mode_adapters = {
insert_mode = "i",
normal_mode = "n",
term_mode = "t",
visual_mode = "v",
visual_block_mode = "x",
command_mode = "c",
}
---@class Keys
---@field insert_mode table
---@field normal_mode table
---@field terminal_mode table
---@field visual_mode table
---@field visual_block_mode table
---@field command_mode table
local defaults = {
insert_mode = {
-- 'jk' for quitting insert mode
["jk"] = "<ESC>",
-- 'kj' for quitting insert mode
["kj"] = "<ESC>",
-- 'jj' for quitting insert mode
["jj"] = "<ESC>",
-- Move current line / block with Alt-j/k ala vscode.
["<A-j>"] = "<Esc>:m .+1<CR>==gi",
-- Move current line / block with Alt-j/k ala vscode.
["<A-k>"] = "<Esc>:m .-2<CR>==gi",
-- navigation
["<A-Up>"] = "<C-\\><C-N><C-w>k",
["<A-Down>"] = "<C-\\><C-N><C-w>j",
["<A-Left>"] = "<C-\\><C-N><C-w>h",
["<A-Right>"] = "<C-\\><C-N><C-w>l",
},
normal_mode = {
-- Better window movement
["<C-h>"] = "<C-w>h",
["<C-j>"] = "<C-w>j",
["<C-k>"] = "<C-w>k",
["<C-l>"] = "<C-w>l",
-- Resize with arrows
["<C-Up>"] = ":resize -2<CR>",
["<C-Down>"] = ":resize +2<CR>",
["<C-Left>"] = ":vertical resize -2<CR>",
["<C-Right>"] = ":vertical resize +2<CR>",
-- Tab switch buffer
["<S-l>"] = ":BufferLineCycleNext<CR>",
["<S-h>"] = ":BufferLineCyclePrev<CR>",
-- Move current line / block with Alt-j/k a la vscode.
["<A-j>"] = ":m .+1<CR>==",
["<A-k>"] = ":m .-2<CR>==",
-- QuickFix
["]q"] = ":cnext<CR>",
["[q"] = ":cprev<CR>",
["<C-q>"] = ":call QuickFixToggle()<CR>",
},
term_mode = {
-- Terminal window navigation
["<C-h>"] = "<C-\\><C-N><C-w>h",
["<C-j>"] = "<C-\\><C-N><C-w>j",
["<C-k>"] = "<C-\\><C-N><C-w>k",
["<C-l>"] = "<C-\\><C-N><C-w>l",
},
visual_mode = {
-- Better indenting
["<"] = "<gv",
[">"] = ">gv",
-- ["p"] = '"0p',
-- ["P"] = '"0P',
},
visual_block_mode = {
-- Move selected line / block of text in visual mode
["K"] = ":move '<-2<CR>gv-gv",
["J"] = ":move '>+1<CR>gv-gv",
-- Move current line / block with Alt-j/k ala vscode.
["<A-j>"] = ":m '>+1<CR>gv-gv",
["<A-k>"] = ":m '<-2<CR>gv-gv",
},
command_mode = {
-- navigate tab completion with <c-j> and <c-k>
-- runs conditionally
["<C-j>"] = { 'pumvisible() ? "\\<C-n>" : "\\<C-j>"', { expr = true, noremap = true } },
["<C-k>"] = { 'pumvisible() ? "\\<C-p>" : "\\<C-k>"', { expr = true, noremap = true } },
},
}
if vim.fn.has "mac" == 1 then
defaults.normal_mode["<A-Up>"] = defaults.normal_mode["<C-Up>"]
defaults.normal_mode["<A-Down>"] = defaults.normal_mode["<C-Down>"]
defaults.normal_mode["<A-Left>"] = defaults.normal_mode["<C-Left>"]
defaults.normal_mode["<A-Right>"] = defaults.normal_mode["<C-Right>"]
Log:debug "Activated mac keymappings"
end
-- Unsets all keybindings defined in keymaps
-- @param keymaps The table of key mappings containing a list per mode (normal_mode, insert_mode, ..)
function M.clear(keymaps)
local default = M.get_defaults()
for mode, mappings in pairs(keymaps) do
local translated_mode = mode_adapters[mode] or mode
for key, _ in pairs(mappings) do
-- some plugins may override default bindings that the user hasn't manually overridden
if default[mode][key] ~= nil or (default[translated_mode] ~= nil and default[translated_mode][key] ~= nil) then
pcall(vim.keymap.del, translated_mode, key)
end
end
end
end
-- Unsets all keybindings defined in keymaps
-- @param keymaps The table of key mappings containing a list per mode (normal_mode, insert_mode, ..)
function M.clear(keymaps)
local default = M.get_defaults()
for mode, mappings in pairs(keymaps) do
local translated_mode = mode_adapters[mode] and mode_adapters[mode] or mode
for key, _ in pairs(mappings) do
-- some plugins may override default bindings that the user hasn't manually overriden
if default[mode][key] ~= nil or (default[translated_mode] ~= nil and default[translated_mode][key] ~= nil) then
pcall(vim.api.nvim_del_keymap, translated_mode, key)
end
end
end
end
-- Set key mappings individually
-- @param mode The keymap mode, can be one of the keys of mode_adapters
-- @param key The key of keymap
-- @param val Can be form as a mapping or tuple of mapping and user defined opt
function M.set_keymaps(mode, key, val)
local opt = generic_opts[mode] or generic_opts_any
if type(val) == "table" then
opt = val[2]
val = val[1]
end
if val then
vim.keymap.set(mode, key, val, opt)
else
pcall(vim.api.nvim_del_keymap, mode, key)
end
end
-- Load key mappings for a given mode
-- @param mode The keymap mode, can be one of the keys of mode_adapters
-- @param keymaps The list of key mappings
function M.load_mode(mode, keymaps)
mode = mode_adapters[mode] or mode
for k, v in pairs(keymaps) do
M.set_keymaps(mode, k, v)
end
end
-- Load key mappings for all provided modes
-- @param keymaps A list of key mappings for each mode
function M.load(keymaps)
keymaps = keymaps or {}
for mode, mapping in pairs(keymaps) do
M.load_mode(mode, mapping)
end
end
-- Load the default keymappings
function M.load_defaults()
M.load(M.get_defaults())
lvim.keys = lvim.keys or {}
for idx, _ in pairs(defaults) do
if not lvim.keys[idx] then
lvim.keys[idx] = {}
end
end
end
-- Get the default keymappings
function M.get_defaults()
return defaults
end
return M

View File

@ -0,0 +1,128 @@
local skipped_servers = {
"angularls",
"ansiblels",
"ccls",
"csharp_ls",
"cssmodules_ls",
"denols",
"ember",
"emmet_ls",
"eslint",
"eslintls",
"golangci_lint_ls",
"graphql",
"jedi_language_server",
"ltex",
"ocamlls",
"phpactor",
"psalm",
"pylsp",
"quick_lint_js",
"rome",
"reason_ls",
"scry",
"solang",
"solidity_ls",
"sorbet",
"sourcekit",
"sourcery",
"spectral",
"sqlls",
"sqls",
"stylelint_lsp",
"tailwindcss",
"tflint",
"svlangserver",
"verible",
"vuels",
}
local skipped_filetypes = { "markdown", "rst", "plaintext" }
return {
templates_dir = join_paths(get_runtime_dir(), "site", "after", "ftplugin"),
diagnostics = {
signs = {
active = true,
values = {
{ name = "DiagnosticSignError", text = "" },
{ name = "DiagnosticSignWarn", text = "" },
{ name = "DiagnosticSignHint", text = "" },
{ name = "DiagnosticSignInfo", text = "" },
},
},
virtual_text = true,
update_in_insert = false,
underline = true,
severity_sort = true,
float = {
focusable = false,
style = "minimal",
border = "rounded",
source = "always",
header = "",
prefix = "",
format = function(d)
local t = vim.deepcopy(d)
local code = d.code or (d.user_data and d.user_data.lsp.code)
if code then
t.message = string.format("%s [%s]", t.message, code):gsub("1. ", "")
end
return t.message
end,
},
},
document_highlight = true,
code_lens_refresh = true,
float = {
focusable = true,
style = "minimal",
border = "rounded",
},
peek = {
max_height = 15,
max_width = 30,
context = 10,
},
on_attach_callback = nil,
on_init_callback = nil,
automatic_servers_installation = true,
automatic_configuration = {
---@usage list of servers that the automatic installer will skip
skipped_servers = skipped_servers,
---@usage list of filetypes that the automatic installer will skip
skipped_filetypes = skipped_filetypes,
},
buffer_mappings = {
normal_mode = {
["K"] = { vim.lsp.buf.hover, "Show hover" },
["gd"] = { vim.lsp.buf.definition, "Goto Definition" },
["gD"] = { vim.lsp.buf.declaration, "Goto declaration" },
["gr"] = { vim.lsp.buf.references, "Goto references" },
["gI"] = { vim.lsp.buf.implementation, "Goto Implementation" },
["gs"] = { vim.lsp.buf.signature_help, "show signature help" },
["gp"] = {
function()
require("lvim.lsp.peek").Peek "definition"
end,
"Peek definition",
},
["gl"] = {
function()
local config = lvim.lsp.diagnostics.float
config.scope = "line"
vim.diagnostic.open_float(0, config)
end,
"Show line diagnostics",
},
},
insert_mode = {},
visual_mode = {},
},
null_ls = {
setup = {},
config = {},
},
---@deprecated use automatic_configuration.skipped_servers instead
override = {},
}

View File

@ -0,0 +1,19 @@
-- Set Default Prefix.
-- Note: You can set a prefix per lsp server in the lv-globals.lua file
local M = {}
function M.setup()
local config = { -- your config
virtual_text = lvim.lsp.diagnostics.virtual_text,
signs = lvim.lsp.diagnostics.signs,
underline = lvim.lsp.diagnostics.underline,
update_in_insert = lvim.lsp.diagnostics.update_in_insert,
severity_sort = lvim.lsp.diagnostics.severity_sort,
float = lvim.lsp.diagnostics.float,
}
vim.diagnostic.config(config)
vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, lvim.lsp.float)
vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, lvim.lsp.float)
end
return M

View File

@ -0,0 +1,135 @@
local M = {}
local Log = require "lvim.core.log"
local utils = require "lvim.utils"
local autocmds = require "lvim.core.autocmds"
local function add_lsp_buffer_keybindings(bufnr)
local mappings = {
normal_mode = "n",
insert_mode = "i",
visual_mode = "v",
}
if lvim.builtin.which_key.active then
-- Remap using which_key
local status_ok, wk = pcall(require, "which-key")
if not status_ok then
return
end
for mode_name, mode_char in pairs(mappings) do
wk.register(lvim.lsp.buffer_mappings[mode_name], { mode = mode_char, buffer = bufnr })
end
else
-- Remap using nvim api
for mode_name, mode_char in pairs(mappings) do
for key, remap in pairs(lvim.lsp.buffer_mappings[mode_name]) do
vim.api.nvim_buf_set_keymap(bufnr, mode_char, key, remap[1], { noremap = true, silent = true })
end
end
end
end
function M.common_capabilities()
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true
capabilities.textDocument.completion.completionItem.resolveSupport = {
properties = {
"documentation",
"detail",
"additionalTextEdits",
},
}
local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp")
if status_ok then
capabilities = cmp_nvim_lsp.update_capabilities(capabilities)
end
return capabilities
end
function M.common_on_exit(_, _)
if lvim.lsp.document_highlight then
autocmds.clear_augroup "lsp_document_highlight"
end
if lvim.lsp.code_lens_refresh then
autocmds.clear_augroup "lsp_code_lens_refresh"
end
end
function M.common_on_init(client, bufnr)
if lvim.lsp.on_init_callback then
lvim.lsp.on_init_callback(client, bufnr)
Log:debug "Called lsp.on_init_callback"
return
end
end
function M.common_on_attach(client, bufnr)
if lvim.lsp.on_attach_callback then
lvim.lsp.on_attach_callback(client, bufnr)
Log:debug "Called lsp.on_attach_callback"
end
local lu = require "lvim.lsp.utils"
if lvim.lsp.document_highlight then
lu.setup_document_highlight(client, bufnr)
end
if lvim.lsp.code_lens_refresh then
lu.setup_codelens_refresh(client, bufnr)
end
add_lsp_buffer_keybindings(bufnr)
end
local function bootstrap_nlsp(opts)
opts = opts or {}
local lsp_settings_status_ok, lsp_settings = pcall(require, "nlspsettings")
if lsp_settings_status_ok then
lsp_settings.setup(opts)
end
end
function M.get_common_opts()
return {
on_attach = M.common_on_attach,
on_init = M.common_on_init,
on_exit = M.common_on_exit,
capabilities = M.common_capabilities(),
}
end
function M.setup()
Log:debug "Setting up LSP support"
local lsp_status_ok, _ = pcall(require, "lspconfig")
if not lsp_status_ok then
return
end
if lvim.use_icons then
for _, sign in ipairs(lvim.lsp.diagnostics.signs.values) do
vim.fn.sign_define(sign.name, { texthl = sign.name, text = sign.text, numhl = sign.name })
end
end
require("lvim.lsp.handlers").setup()
if not utils.is_directory(lvim.lsp.templates_dir) then
require("lvim.lsp.templates").generate_templates()
end
bootstrap_nlsp {
config_home = utils.join_paths(get_config_dir(), "lsp-settings"),
append_default_schemas = true,
}
require("nvim-lsp-installer").setup {
-- use the default nvim_data_dir, since the server binaries are independent
install_root_dir = utils.join_paths(vim.call("stdpath", "data"), "lsp_servers"),
}
require("lvim.lsp.null-ls").setup()
autocmds.configure_format_on_save()
end
return M

View File

@ -0,0 +1,99 @@
local M = {}
local Log = require "lvim.core.log"
local lvim_lsp_utils = require "lvim.lsp.utils"
---Resolve the configuration for a server by merging with the default config
---@param server_name string
---@vararg any config table [optional]
---@return table
local function resolve_config(server_name, ...)
local defaults = {
on_attach = require("lvim.lsp").common_on_attach,
on_init = require("lvim.lsp").common_on_init,
on_exit = require("lvim.lsp").common_on_exit,
capabilities = require("lvim.lsp").common_capabilities(),
}
local has_custom_provider, custom_config = pcall(require, "lvim/lsp/providers/" .. server_name)
if has_custom_provider then
Log:debug("Using custom configuration for requested server: " .. server_name)
defaults = vim.tbl_deep_extend("force", defaults, custom_config)
end
defaults = vim.tbl_deep_extend("force", defaults, ...)
return defaults
end
-- manually start the server and don't wait for the usual filetype trigger from lspconfig
local function buf_try_add(server_name, bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
require("lspconfig")[server_name].manager.try_add_wrapper(bufnr)
end
-- check if the manager autocomd has already been configured since some servers can take a while to initialize
-- this helps guarding against a data-race condition where a server can get configured twice
-- which seems to occur only when attaching to single-files
local function client_is_configured(server_name, ft)
ft = ft or vim.bo.filetype
local active_autocmds = vim.split(vim.fn.execute("autocmd FileType " .. ft), "\n")
for _, result in ipairs(active_autocmds) do
if result:match(server_name) then
Log:debug(string.format("[%q] is already configured", server_name))
return true
end
end
return false
end
local function launch_server(server_name, config)
pcall(function()
require("lspconfig")[server_name].setup(config)
buf_try_add(server_name)
end)
end
---Setup a language server by providing a name
---@param server_name string name of the language server
---@param user_config table? when available it will take predence over any default configurations
function M.setup(server_name, user_config)
vim.validate { name = { server_name, "string" } }
user_config = user_config or {}
if lvim_lsp_utils.is_client_active(server_name) or client_is_configured(server_name) then
return
end
local servers = require "nvim-lsp-installer.servers"
local server_available, server = servers.get_server(server_name)
if not server_available then
local config = resolve_config(server_name, user_config)
launch_server(server_name, config)
return
end
local install_in_progress = false
if not server:is_installed() then
if lvim.lsp.automatic_servers_installation then
Log:debug "Automatic server installation detected"
server:install()
install_in_progress = true
else
Log:debug(server.name .. " is not managed by the automatic installer")
end
end
server:on_ready(function()
if install_in_progress then
vim.notify(string.format("Installation complete for [%s] server", server.name), vim.log.levels.INFO)
end
install_in_progress = false
local config = resolve_config(server_name, server:get_default_options(), user_config)
launch_server(server_name, config)
end)
end
return M

View File

@ -0,0 +1,26 @@
local M = {}
local Log = require "lvim.core.log"
local null_ls = require "null-ls"
local services = require "lvim.lsp.null-ls.services"
local method = null_ls.methods.CODE_ACTION
function M.list_registered(filetype)
local registered_providers = services.list_registered_providers_names(filetype)
return registered_providers[method] or {}
end
function M.setup(actions_configs)
if vim.tbl_isempty(actions_configs) then
return
end
local registered = services.register_sources(actions_configs, method)
if #registered > 0 then
Log:debug("Registered the following action-handlers: " .. unpack(registered))
end
end
return M

View File

@ -0,0 +1,33 @@
local M = {}
local Log = require "lvim.core.log"
local null_ls = require "null-ls"
local services = require "lvim.lsp.null-ls.services"
local method = null_ls.methods.FORMATTING
function M.list_registered(filetype)
local registered_providers = services.list_registered_providers_names(filetype)
return registered_providers[method] or {}
end
function M.list_supported(filetype)
local s = require "null-ls.sources"
local supported_formatters = s.get_supported(filetype, "formatting")
table.sort(supported_formatters)
return supported_formatters
end
function M.setup(formatter_configs)
if vim.tbl_isempty(formatter_configs) then
return
end
local registered = services.register_sources(formatter_configs, method)
if #registered > 0 then
Log:debug("Registered the following formatters: " .. unpack(registered))
end
end
return M

View File

@ -0,0 +1,16 @@
local M = {}
local Log = require "lvim.core.log"
function M.setup()
local status_ok, null_ls = pcall(require, "null-ls")
if not status_ok then
Log:error "Missing null-ls dependency"
return
end
local default_opts = require("lvim.lsp").get_common_opts()
null_ls.setup(vim.tbl_deep_extend("force", default_opts, lvim.lsp.null_ls.setup))
end
return M

View File

@ -0,0 +1,33 @@
local M = {}
local Log = require "lvim.core.log"
local null_ls = require "null-ls"
local services = require "lvim.lsp.null-ls.services"
local method = null_ls.methods.DIAGNOSTICS
function M.list_registered(filetype)
local registered_providers = services.list_registered_providers_names(filetype)
return registered_providers[method] or {}
end
function M.list_supported(filetype)
local s = require "null-ls.sources"
local supported_linters = s.get_supported(filetype, "diagnostics")
table.sort(supported_linters)
return supported_linters
end
function M.setup(linter_configs)
if vim.tbl_isempty(linter_configs) then
return
end
local registered = services.register_sources(linter_configs, method)
if #registered > 0 then
Log:debug("Registered the following linters: " .. unpack(registered))
end
end
return M

View File

@ -0,0 +1,104 @@
local M = {}
local Log = require "lvim.core.log"
local function find_root_dir()
local util = require "lspconfig/util"
local lsp_utils = require "lvim.lsp.utils"
local ts_client = lsp_utils.is_client_active "typescript"
if ts_client then
return ts_client.config.root_dir
end
local dirname = vim.fn.expand "%:p:h"
return util.root_pattern "package.json"(dirname)
end
local function from_node_modules(command)
local root_dir = find_root_dir()
if not root_dir then
return nil
end
local join_paths = require("lvim.utils").join_paths
return join_paths(root_dir, "node_modules", ".bin", command)
end
local local_providers = {
prettier = { find = from_node_modules },
prettierd = { find = from_node_modules },
prettier_d_slim = { find = from_node_modules },
eslint_d = { find = from_node_modules },
eslint = { find = from_node_modules },
stylelint = { find = from_node_modules },
}
function M.find_command(command)
if local_providers[command] then
local local_command = local_providers[command].find(command)
if local_command and vim.fn.executable(local_command) == 1 then
return local_command
end
end
if command and vim.fn.executable(command) == 1 then
return command
end
return nil
end
function M.list_registered_providers_names(filetype)
local s = require "null-ls.sources"
local available_sources = s.get_available(filetype)
local registered = {}
for _, source in ipairs(available_sources) do
for method in pairs(source.methods) do
registered[method] = registered[method] or {}
table.insert(registered[method], source.name)
end
end
return registered
end
function M.register_sources(configs, method)
local null_ls = require "null-ls"
local is_registered = require("null-ls.sources").is_registered
local sources, registered_names = {}, {}
for _, config in ipairs(configs) do
local cmd = config.exe or config.command
local name = config.name or cmd:gsub("-", "_")
local type = method == null_ls.methods.CODE_ACTION and "code_actions" or null_ls.methods[method]:lower()
local source = type and null_ls.builtins[type][name]
Log:debug(string.format("Received request to register [%s] as a %s source", name, type))
if not source then
Log:error("Not a valid source: " .. name)
elseif is_registered { name = source.name or name, method = method } then
Log:trace(string.format("Skipping registering [%s] more than once", name))
else
local command = M.find_command(source._opts.command) or source._opts.command
-- treat `args` as `extra_args` for backwards compatibility. Can otherwise use `generator_opts.args`
local compat_opts = vim.deepcopy(config)
if config.args then
compat_opts.extra_args = config.args or config.extra_args
compat_opts.args = nil
end
local opts = vim.tbl_deep_extend("keep", { command = command }, compat_opts)
Log:debug("Registering source " .. name)
Log:trace(vim.inspect(opts))
table.insert(sources, source.with(opts))
vim.list_extend(registered_names, { source.name })
end
end
if #sources > 0 then
null_ls.register { sources = sources }
end
return registered_names
end
return M

View File

@ -0,0 +1,157 @@
local M = {
floating_buf = nil,
floating_win = nil,
prev_result = nil,
}
local function create_floating_file(location, opts)
vim.validate {
location = { location, "t" },
opts = { opts, "t", true },
}
-- Set some defaults
opts = opts or {}
local close_events = opts.close_events or { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" }
-- location may be LocationLink or Location
local uri = location.targetUri or location.uri
if uri == nil then
return
end
local bufnr = vim.uri_to_bufnr(uri)
if not vim.api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
end
local range = location.targetRange or location.range
local contents = vim.api.nvim_buf_get_lines(
bufnr,
range.start.line,
math.min(
range["end"].line + 1 + (opts.context or lvim.lsp.peek.max_height),
range.start.line + (opts.max_height or lvim.lsp.peek.max_height)
),
false
)
if next(contents) == nil then
vim.notify("peek: Unable to get contents of the file!", vim.log.levels.WARN)
return
end
local width, height = vim.lsp.util._make_floating_popup_size(contents, opts)
local if_nil = vim.F.if_nil
opts = vim.lsp.util.make_floating_popup_options(
if_nil(width, lvim.lsp.peek.max_width),
if_nil(height, lvim.lsp.peek.max_height),
opts
)
-- Don't make it minimal as it is meant to be fully featured
opts["style"] = nil
vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe")
local winnr = vim.api.nvim_open_win(bufnr, false, opts)
vim.api.nvim_win_set_option(winnr, "winblend", 0)
vim.api.nvim_win_set_cursor(winnr, { range.start.line + 1, range.start.character })
vim.api.nvim_buf_set_var(bufnr, "lsp_floating_window", winnr)
-- Set some autocmds to close the window
vim.api.nvim_command(
string.format("autocmd %s <buffer> ++once lua pcall(vim.api.nvim_win_close, %d, true)", unpack(close_events), winnr)
)
return bufnr, winnr
end
local function preview_location_callback(result)
if result == nil or vim.tbl_isempty(result) then
return nil
end
local opts = {
border = "rounded",
context = lvim.lsp.peek.context,
}
if vim.tbl_islist(result) then
M.prev_result = result[1]
M.floating_buf, M.floating_win = create_floating_file(result[1], opts)
else
M.prev_result = result
M.floating_buf, M.floating_win = create_floating_file(result, opts)
end
end
local function preview_location_callback_new_signature(_, result)
return preview_location_callback(result)
end
function M.open_file()
-- Get the file currently open in the floating window
local filepath = vim.fn.expand "%:."
if not filepath then
vim.notify("peek: Unable to open the file!", vim.log.levels.ERROR)
return
end
-- Close the floating window
pcall(vim.api.nvim_win_close, M.floating_win, true)
-- Edit the file
vim.cmd("edit " .. filepath)
local winnr = vim.api.nvim_get_current_win()
-- Set the cursor at the right position
M.set_cursor_to_prev_pos(winnr)
end
function M.set_cursor_to_prev_pos(winnr)
-- Get position of the thing to peek at
local location = M.prev_result
local range = location.targetRange or location.range
local cursor_pos = { range.start.line + 1, range.start.character }
-- Set the winnr to the floating window if none was passed in
winnr = winnr or M.floating_win
-- Set the cursor at the correct position in the floating window
vim.api.nvim_win_set_cursor(winnr, cursor_pos)
end
function M.Peek(what)
-- If a window already exists, focus it at the right position!
if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then
local success_1, _ = pcall(vim.api.nvim_set_current_win, M.floating_win)
if not success_1 then
vim.notify("peek: You cannot edit the current file in a preview!", vim.log.levels.ERROR)
return
end
-- Set the cursor at the correct position in the floating window
M.set_cursor_to_prev_pos()
vim.api.nvim_buf_set_keymap(
M.floating_buf,
"n",
"<CR>",
":lua require('lvim.lsp.peek').open_file()<CR>",
{ noremap = true, silent = true }
)
else
-- Make a new request and then create the new window in the callback
local params = vim.lsp.util.make_position_params()
local preview_callback = preview_location_callback_new_signature
local success, _ = pcall(vim.lsp.buf_request, 0, "textDocument/" .. what, params, preview_callback)
if not success then
vim.notify(
'peek: Error calling LSP method "textDocument/' .. what .. '". The current language lsp might not support it.',
vim.log.levels.ERROR
)
end
end
end
return M

View File

@ -0,0 +1,23 @@
local full_schemas = vim.tbl_deep_extend(
"force",
require("schemastore").json.schemas(),
require("nlspsettings.jsonls").get_default_schemas()
)
local opts = {
settings = {
json = {
schemas = full_schemas,
},
},
setup = {
commands = {
Format = {
function()
vim.lsp.buf.range_formatting({}, { 0, 0 }, { vim.fn.line "$", 0 })
end,
},
},
},
}
return opts

View File

@ -0,0 +1,34 @@
local opts = {
settings = {
Lua = {
diagnostics = {
globals = { "vim", "lvim", "packer_plugins" },
},
workspace = {
library = {
[require("lvim.utils").join_paths(get_runtime_dir(), "lvim", "lua")] = true,
},
maxPreload = 100000,
preloadFileSize = 10000,
},
},
},
}
local lua_dev_loaded, lua_dev = pcall(require, "lua-dev")
if not lua_dev_loaded then
return opts
end
local dev_opts = {
library = {
vimruntime = true, -- runtime path
types = true, -- full signature, docs and completion of vim.api, vim.treesitter, vim.lsp and others
-- plugins = true, -- installed opt or start plugins in packpath
-- you can also specify the list of plugins to make available as a workspace library
plugins = { "plenary.nvim" },
},
lspconfig = opts,
}
return lua_dev.setup(dev_opts)

View File

@ -0,0 +1,26 @@
local opts = {
setup = {
root_dir = function(fname)
local util = require "lvim.lspconfig/util"
return util.root_pattern "package.json"(fname) or util.root_pattern "vue.config.js"(fname) or vim.fn.getcwd()
end,
init_options = {
config = {
vetur = {
completion = {
autoImport = true,
tagCasing = "kebab",
useScaffoldSnippets = true,
},
useWorkspaceDependencies = true,
validation = {
script = true,
style = true,
template = true,
},
},
},
},
},
}
return opts

View File

@ -0,0 +1,30 @@
local opts = {
settings = {
yaml = {
hover = true,
completion = true,
validate = true,
schemaStore = {
enable = true,
url = "https://www.schemastore.org/api/json/catalog.json",
},
schemas = {
kubernetes = {
"daemon.{yml,yaml}",
"manager.{yml,yaml}",
"restapi.{yml,yaml}",
"role.{yml,yaml}",
"role_binding.{yml,yaml}",
"*onfigma*.{yml,yaml}",
"*ngres*.{yml,yaml}",
"*ecre*.{yml,yaml}",
"*eployment*.{yml,yaml}",
"*ervic*.{yml,yaml}",
"kubectl-edit*.yaml",
},
},
},
},
}
return opts

View File

@ -0,0 +1,77 @@
local M = {}
local Log = require "lvim.core.log"
local utils = require "lvim.utils"
local lvim_lsp_utils = require "lvim.lsp.utils"
local ftplugin_dir = lvim.lsp.templates_dir
local join_paths = _G.join_paths
function M.remove_template_files()
-- remove any outdated files
for _, file in ipairs(vim.fn.glob(ftplugin_dir .. "/*.lua", 1, 1)) do
vim.fn.delete(file)
end
end
local skipped_filetypes = lvim.lsp.automatic_configuration.skipped_filetypes
local skipped_servers = lvim.lsp.automatic_configuration.skipped_servers
---Generates an ftplugin file based on the server_name in the selected directory
---@param server_name string name of a valid language server, e.g. pyright, gopls, tsserver, etc.
---@param dir string the full path to the desired directory
function M.generate_ftplugin(server_name, dir)
if vim.tbl_contains(skipped_servers, server_name) then
return
end
-- get the supported filetypes and remove any ignored ones
local filetypes = vim.tbl_filter(function(ft)
return not vim.tbl_contains(skipped_filetypes, ft)
end, lvim_lsp_utils.get_supported_filetypes(server_name) or {})
if not filetypes then
return
end
for _, filetype in ipairs(filetypes) do
local filename = join_paths(dir, filetype .. ".lua")
local setup_cmd = string.format([[require("lvim.lsp.manager").setup(%q)]], server_name)
-- print("using setup_cmd: " .. setup_cmd)
-- overwrite the file completely
utils.write_file(filename, setup_cmd .. "\n", "a")
end
end
---Generates ftplugin files based on a list of server_names
---The files are generated to a runtimepath: "$LUNARVIM_RUNTIME_DIR/site/after/ftplugin/template.lua"
---@param servers_names? table list of servers to be enabled. Will add all by default
function M.generate_templates(servers_names)
servers_names = servers_names or {}
Log:debug "Templates installation in progress"
M.remove_template_files()
if vim.tbl_isempty(servers_names) then
local available_servers = require("nvim-lsp-installer.servers").get_available_servers()
for _, server in pairs(available_servers) do
table.insert(servers_names, server.name)
table.sort(servers_names)
end
end
-- create the directory if it didn't exist
if not utils.is_directory(lvim.lsp.templates_dir) then
vim.fn.mkdir(ftplugin_dir, "p")
end
for _, server in ipairs(servers_names) do
M.generate_ftplugin(server, ftplugin_dir)
end
Log:debug "Templates installation is complete"
end
return M

View File

@ -0,0 +1,194 @@
local M = {}
local tbl = require "lvim.utils.table"
function M.is_client_active(name)
local clients = vim.lsp.get_active_clients()
return tbl.find_first(clients, function(client)
return client.name == name
end)
end
function M.get_active_clients_by_ft(filetype)
local matches = {}
local clients = vim.lsp.get_active_clients()
for _, client in pairs(clients) do
local supported_filetypes = client.config.filetypes or {}
if client.name ~= "null-ls" and vim.tbl_contains(supported_filetypes, filetype) then
table.insert(matches, client)
end
end
return matches
end
function M.get_client_capabilities(client_id)
local client
if not client_id then
local buf_clients = vim.lsp.buf_get_clients()
for _, buf_client in pairs(buf_clients) do
if buf_client.name ~= "null-ls" then
client = buf_client
break
end
end
else
client = vim.lsp.get_client_by_id(tonumber(client_id))
end
if not client then
error "Unable to determine client_id"
return
end
local enabled_caps = {}
for capability, status in pairs(client.server_capabilities or client.resolved_capabilities) do
if status == true then
table.insert(enabled_caps, capability)
end
end
return enabled_caps
end
---Get supported filetypes per server
---@param server_name string can be any server supported by nvim-lsp-installer
---@return table supported filestypes as a list of strings
function M.get_supported_filetypes(server_name)
local status_ok, lsp_installer_servers = pcall(require, "nvim-lsp-installer.servers")
if not status_ok then
return {}
end
local server_available, requested_server = lsp_installer_servers.get_server(server_name)
if not server_available then
return {}
end
return requested_server:get_supported_filetypes()
end
---Get supported servers per filetype
---@param filetype string
---@return table list of names of supported servers
function M.get_supported_servers_per_filetype(filetype)
local filetype_server_map = require "nvim-lsp-installer._generated.filetype_map"
return filetype_server_map[filetype]
end
---Get all supported filetypes by nvim-lsp-installer
---@return table supported filestypes as a list of strings
function M.get_all_supported_filetypes()
local status_ok, lsp_installer_filetypes = pcall(require, "nvim-lsp-installer._generated.filetype_map")
if not status_ok then
return {}
end
return vim.tbl_keys(lsp_installer_filetypes or {})
end
function M.setup_document_highlight(client, bufnr)
local status_ok, highlight_supported = pcall(function()
return client.supports_method "textDocument/documentHighlight"
end)
if not status_ok or not highlight_supported then
return
end
local augroup_exist, _ = pcall(vim.api.nvim_get_autocmds, {
group = "lsp_document_highlight",
})
if not augroup_exist then
vim.api.nvim_create_augroup("lsp_document_highlight", {})
end
vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, {
group = "lsp_document_highlight",
buffer = bufnr,
callback = vim.lsp.buf.document_highlight,
})
vim.api.nvim_create_autocmd("CursorMoved", {
group = "lsp_document_highlight",
buffer = bufnr,
callback = vim.lsp.buf.clear_references,
})
end
function M.setup_codelens_refresh(client, bufnr)
local status_ok, codelens_supported = pcall(function()
return client.supports_method "textDocument/codeLens"
end)
if not status_ok or not codelens_supported then
return
end
local augroup_exist, _ = pcall(vim.api.nvim_get_autocmds, {
group = "lsp_code_lens_refresh",
})
if not augroup_exist then
vim.api.nvim_create_augroup("lsp_code_lens_refresh", {})
end
vim.api.nvim_create_autocmd({ "BufEnter", "InsertLeave" }, {
group = "lsp_code_lens_refresh",
buffer = bufnr,
callback = vim.lsp.codelens.refresh,
})
end
---filter passed to vim.lsp.buf.format
---gives higher priority to null-ls
---@param clients table clients attached to a buffer
---@return table chosen clients
function M.format_filter(clients)
return vim.tbl_filter(function(client)
local status_ok, formatting_supported = pcall(function()
return client.supports_method "textDocument/formatting"
end)
-- give higher prio to null-ls
if status_ok and formatting_supported and client.name == "null-ls" then
return "null-ls"
else
return status_ok and formatting_supported and client.name
end
end, clients)
end
---Provide vim.lsp.buf.format for nvim <0.8
---@param opts table
function M.format(opts)
opts = opts or { filter = M.format_filter }
if vim.lsp.buf.format then
return vim.lsp.buf.format(opts)
end
local bufnr = opts.bufnr or vim.api.nvim_get_current_buf()
local clients = vim.lsp.buf_get_clients(bufnr)
if opts.filter then
clients = opts.filter(clients)
elseif opts.id then
clients = vim.tbl_filter(function(client)
return client.id == opts.id
end, clients)
elseif opts.name then
clients = vim.tbl_filter(function(client)
return client.name == opts.name
end, clients)
end
clients = vim.tbl_filter(function(client)
return client.supports_method "textDocument/formatting"
end, clients)
if #clients == 0 then
vim.notify_once "[LSP] Format request failed, no matching language servers."
end
local timeout_ms = opts.timeout_ms or 1000
for _, client in pairs(clients) do
local params = vim.lsp.util.make_formatting_params(opts.formatting_options)
local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, bufnr)
if result and result.result then
vim.lsp.util.apply_text_edits(result.result, bufnr, client.offset_encoding)
elseif err then
vim.notify(string.format("[LSP][%s] %s", client.name, err), vim.log.levels.WARN)
end
end
end
return M

View File

@ -0,0 +1,166 @@
local plugin_loader = {}
local utils = require "lvim.utils"
local Log = require "lvim.core.log"
local join_paths = utils.join_paths
local in_headless = #vim.api.nvim_list_uis() == 0
-- we need to reuse this outside of init()
local compile_path = join_paths(get_config_dir(), "plugin", "packer_compiled.lua")
local snapshot_path = join_paths(get_cache_dir(), "snapshots")
local default_snapshot = join_paths(get_lvim_base_dir(), "snapshots", "default.json")
function plugin_loader.init(opts)
opts = opts or {}
local install_path = opts.install_path
or join_paths(vim.fn.stdpath "data", "site", "pack", "packer", "start", "packer.nvim")
local init_opts = {
package_root = opts.package_root or join_paths(vim.fn.stdpath "data", "site", "pack"),
compile_path = compile_path,
snapshot_path = snapshot_path,
log = { level = "warn" },
git = {
clone_timeout = 300,
},
display = {
open_fn = function()
return require("packer.util").float { border = "rounded" }
end,
},
}
if in_headless then
init_opts.display = nil
end
if not utils.is_directory(install_path) then
vim.fn.system { "git", "clone", "--depth", "1", "https://github.com/wbthomason/packer.nvim", install_path }
vim.cmd "packadd packer.nvim"
-- IMPORTANT: we only set this the very first time to avoid constantly triggering the rollback function
-- https://github.com/wbthomason/packer.nvim/blob/c576ab3f1488ee86d60fd340d01ade08dcabd256/lua/packer.lua#L998-L995
init_opts.snapshot = default_snapshot
end
local status_ok, packer = pcall(require, "packer")
if status_ok then
packer.on_complete = vim.schedule_wrap(function()
require("lvim.utils.hooks").run_on_packer_complete()
end)
packer.init(init_opts)
end
end
-- packer expects a space separated list
local function pcall_packer_command(cmd, kwargs)
local status_ok, msg = pcall(function()
require("packer")[cmd](unpack(kwargs or {}))
end)
if not status_ok then
Log:warn(cmd .. " failed with: " .. vim.inspect(msg))
Log:trace(vim.inspect(vim.fn.eval "v:errmsg"))
end
end
function plugin_loader.cache_clear()
if vim.fn.delete(compile_path) == 0 then
Log:debug "deleted packer_compiled.lua"
end
end
function plugin_loader.recompile()
plugin_loader.cache_clear()
pcall_packer_command "compile"
if utils.is_file(compile_path) then
Log:debug "generated packer_compiled.lua"
end
end
function plugin_loader.reload(configurations)
_G.packer_plugins = _G.packer_plugins or {}
for k, v in pairs(_G.packer_plugins) do
if k ~= "packer.nvim" then
_G.packer_plugins[v] = nil
end
end
plugin_loader.load(configurations)
plugin_loader.ensure_plugins()
end
function plugin_loader.load(configurations)
Log:debug "loading plugins configuration"
local packer_available, packer = pcall(require, "packer")
if not packer_available then
Log:warn "skipping loading plugins until Packer is installed"
return
end
local status_ok, _ = xpcall(function()
packer.reset()
packer.startup(function(use)
for _, plugins in ipairs(configurations) do
for _, plugin in ipairs(plugins) do
use(plugin)
end
end
end)
-- colorscheme must get called after plugins are loaded or it will break new installs.
vim.g.colors_name = lvim.colorscheme
vim.cmd("colorscheme " .. lvim.colorscheme)
end, debug.traceback)
if not status_ok then
Log:warn "problems detected while loading plugins' configurations"
Log:trace(debug.traceback())
end
end
function plugin_loader.get_core_plugins()
local list = {}
local plugins = require "lvim.plugins"
for _, item in pairs(plugins) do
if not item.disable then
table.insert(list, item[1]:match "/(%S*)")
end
end
return list
end
function plugin_loader.load_snapshot(snapshot_file)
snapshot_file = snapshot_file or default_snapshot
if not in_headless then
vim.notify("Syncing core plugins is in progress..", vim.log.levels.INFO, { title = "lvim" })
end
Log:debug(string.format("Using snapshot file [%s]", snapshot_file))
local core_plugins = plugin_loader.get_core_plugins()
require("packer").rollback(snapshot_file, unpack(core_plugins))
end
function plugin_loader.sync_core_plugins()
-- problem: rollback() will get stuck if a plugin directory doesn't exist
-- solution: call sync() beforehand
-- see https://github.com/wbthomason/packer.nvim/issues/862
vim.api.nvim_create_autocmd("User", {
pattern = "PackerComplete",
once = true,
callback = function()
require("lvim.plugin-loader").load_snapshot(default_snapshot)
end,
})
pcall_packer_command "sync"
end
function plugin_loader.ensure_plugins()
vim.api.nvim_create_autocmd("User", {
pattern = "PackerComplete",
once = true,
callback = function()
Log:debug "calling packer.clean()"
pcall_packer_command "clean"
end,
})
Log:debug "calling packer.install()"
pcall_packer_command "install"
end
return plugin_loader

View File

@ -0,0 +1,265 @@
local core_plugins = {
-- Packer can manage itself as an optional plugin
{ "wbthomason/packer.nvim" },
{ "neovim/nvim-lspconfig" },
{ "tamago324/nlsp-settings.nvim" },
{
"jose-elias-alvarez/null-ls.nvim",
},
{ "antoinemadec/FixCursorHold.nvim" }, -- Needed while issue https://github.com/neovim/neovim/issues/12587 is still open
{
"williamboman/nvim-lsp-installer",
},
{
"lunarvim/onedarker.nvim",
config = function()
pcall(function()
if lvim and lvim.colorscheme == "onedarker" then
require("onedarker").setup()
lvim.builtin.lualine.options.theme = "onedarker"
end
end)
end,
disable = lvim.colorscheme ~= "onedarker",
},
{
"rcarriga/nvim-notify",
config = function()
require("lvim.core.notify").setup()
end,
requires = { "nvim-telescope/telescope.nvim" },
disable = not lvim.builtin.notify.active or not lvim.builtin.telescope.active,
},
{ "Tastyep/structlog.nvim" },
{ "nvim-lua/popup.nvim" },
{ "nvim-lua/plenary.nvim" },
-- Telescope
{
"nvim-telescope/telescope.nvim",
config = function()
require("lvim.core.telescope").setup()
end,
disable = not lvim.builtin.telescope.active,
},
{
"nvim-telescope/telescope-fzf-native.nvim",
requires = { "nvim-telescope/telescope.nvim" },
run = "make",
disable = not lvim.builtin.telescope.active,
},
-- Install nvim-cmp, and buffer source as a dependency
{
"hrsh7th/nvim-cmp",
config = function()
if lvim.builtin.cmp then
require("lvim.core.cmp").setup()
end
end,
requires = {
"L3MON4D3/LuaSnip",
},
},
{
"rafamadriz/friendly-snippets",
disable = not lvim.builtin.luasnip.sources.friendly_snippets,
},
{
"L3MON4D3/LuaSnip",
config = function()
local utils = require "lvim.utils"
local paths = {}
if lvim.builtin.luasnip.sources.friendly_snippets then
paths[#paths + 1] = utils.join_paths(get_runtime_dir(), "site", "pack", "packer", "start", "friendly-snippets")
end
local user_snippets = utils.join_paths(get_config_dir(), "snippets")
if utils.is_directory(user_snippets) then
paths[#paths + 1] = user_snippets
end
require("luasnip.loaders.from_lua").lazy_load()
require("luasnip.loaders.from_vscode").lazy_load {
paths = paths,
}
require("luasnip.loaders.from_snipmate").lazy_load()
end,
},
{
"hrsh7th/cmp-nvim-lsp",
},
{
"saadparwaiz1/cmp_luasnip",
},
{
"hrsh7th/cmp-buffer",
},
{
"hrsh7th/cmp-path",
},
{
-- NOTE: Temporary fix till folke comes back
"max397574/lua-dev.nvim",
module = "lua-dev",
},
-- Autopairs
{
"windwp/nvim-autopairs",
-- event = "InsertEnter",
config = function()
require("lvim.core.autopairs").setup()
end,
disable = not lvim.builtin.autopairs.active,
},
-- Treesitter
{
"nvim-treesitter/nvim-treesitter",
-- run = ":TSUpdate",
config = function()
require("lvim.core.treesitter").setup()
end,
},
{
"JoosepAlviste/nvim-ts-context-commentstring",
event = "BufReadPost",
},
-- NvimTree
{
"kyazdani42/nvim-tree.lua",
-- event = "BufWinOpen",
-- cmd = "NvimTreeToggle",
config = function()
require("lvim.core.nvimtree").setup()
end,
disable = not lvim.builtin.nvimtree.active,
},
{
"lewis6991/gitsigns.nvim",
config = function()
require("lvim.core.gitsigns").setup()
end,
event = "BufRead",
disable = not lvim.builtin.gitsigns.active,
},
-- Whichkey
{
"max397574/which-key.nvim",
config = function()
require("lvim.core.which-key").setup()
end,
event = "BufWinEnter",
disable = not lvim.builtin.which_key.active,
},
-- Comments
{
"numToStr/Comment.nvim",
event = "BufRead",
config = function()
require("lvim.core.comment").setup()
end,
disable = not lvim.builtin.comment.active,
},
-- project.nvim
{
"ahmedkhalf/project.nvim",
config = function()
require("lvim.core.project").setup()
end,
disable = not lvim.builtin.project.active,
},
-- Icons
{
"kyazdani42/nvim-web-devicons",
disable = not lvim.use_icons,
},
-- Status Line and Bufferline
{
-- "hoob3rt/lualine.nvim",
"nvim-lualine/lualine.nvim",
-- "Lunarvim/lualine.nvim",
config = function()
require("lvim.core.lualine").setup()
end,
disable = not lvim.builtin.lualine.active,
},
{
"akinsho/bufferline.nvim",
config = function()
require("lvim.core.bufferline").setup()
end,
branch = "main",
event = "BufWinEnter",
disable = not lvim.builtin.bufferline.active,
},
-- Debugging
{
"mfussenegger/nvim-dap",
-- event = "BufWinEnter",
config = function()
require("lvim.core.dap").setup()
end,
disable = not lvim.builtin.dap.active,
},
-- Debugger management
{
"Pocco81/dap-buddy.nvim",
branch = "dev",
-- event = "BufWinEnter",
-- event = "BufRead",
disable = not lvim.builtin.dap.active,
},
-- alpha
{
"goolord/alpha-nvim",
config = function()
require("lvim.core.alpha").setup()
end,
disable = not lvim.builtin.alpha.active,
},
-- Terminal
{
"akinsho/toggleterm.nvim",
event = "BufWinEnter",
branch = "main",
config = function()
require("lvim.core.terminal").setup()
end,
disable = not lvim.builtin.terminal.active,
},
-- SchemaStore
{
"b0o/schemastore.nvim",
},
}
local default_snapshot_path = join_paths(get_lvim_base_dir(), "snapshots", "default.json")
local content = vim.fn.readfile(default_snapshot_path)
local default_sha1 = vim.fn.json_decode(content)
local get_default_sha1 = function(spec)
local short_name, _ = require("packer.util").get_plugin_short_name(spec)
return default_sha1[short_name] and default_sha1[short_name].commit
end
for _, spec in ipairs(core_plugins) do
if not vim.env.LVIM_DEV_MODE then
-- Manually lock the commit hash since Packer's snapshots are unreliable in headless mode
spec["commit"] = get_default_sha1(spec)
end
end
return core_plugins

View File

@ -0,0 +1,107 @@
local M = {}
local uv = vim.loop
-- recursive Print (structure, limit, separator)
local function r_inspect_settings(structure, limit, separator)
limit = limit or 100 -- default item limit
separator = separator or "." -- indent string
if limit < 1 then
print "ERROR: Item limit reached."
return limit - 1
end
if structure == nil then
io.write("-- O", separator:sub(2), " = nil\n")
return limit - 1
end
local ts = type(structure)
if ts == "table" then
for k, v in pairs(structure) do
-- replace non alpha keys with ["key"]
if tostring(k):match "[^%a_]" then
k = '["' .. tostring(k) .. '"]'
end
limit = r_inspect_settings(v, limit, separator .. "." .. tostring(k))
if limit < 0 then
break
end
end
return limit
end
if ts == "string" then
-- escape sequences
structure = string.format("%q", structure)
end
separator = separator:gsub("%.%[", "%[")
if type(structure) == "function" then
-- don't print functions
io.write("-- lvim", separator:sub(2), " = function ()\n")
else
io.write("lvim", separator:sub(2), " = ", tostring(structure), "\n")
end
return limit - 1
end
function M.generate_settings()
-- Opens a file in append mode
local file = io.open("lv-settings.lua", "w")
-- sets the default output file as test.lua
io.output(file)
-- write all `lvim` related settings to `lv-settings.lua` file
r_inspect_settings(lvim, 10000, ".")
-- closes the open file
io.close(file)
end
--- Returns a table with the default values that are missing.
--- either parameter can be empty.
--@param config (table) table containing entries that take priority over defaults
--@param default_config (table) table contatining default values if found
function M.apply_defaults(config, default_config)
config = config or {}
default_config = default_config or {}
local new_config = vim.tbl_deep_extend("keep", vim.empty_dict(), config)
new_config = vim.tbl_deep_extend("keep", new_config, default_config)
return new_config
end
--- Checks whether a given path exists and is a file.
--@param path (string) path to check
--@returns (bool)
function M.is_file(path)
local stat = uv.fs_stat(path)
return stat and stat.type == "file" or false
end
--- Checks whether a given path exists and is a directory
--@param path (string) path to check
--@returns (bool)
function M.is_directory(path)
local stat = uv.fs_stat(path)
return stat and stat.type == "directory" or false
end
M.join_paths = _G.join_paths
---Write data to a file
---@param path string can be full or relative to `cwd`
---@param txt string|table text to be written, uses `vim.inspect` internally for tables
---@param flag string used to determine access mode, common flags: "w" for `overwrite` or "a" for `append`
function M.write_file(path, txt, flag)
local data = type(txt) == "string" and txt or vim.inspect(txt)
uv.fs_open(path, flag, 438, function(open_err, fd)
assert(not open_err, open_err)
uv.fs_write(fd, data, -1, function(write_err)
assert(not write_err, write_err)
uv.fs_close(fd, function(close_err)
assert(not close_err, close_err)
end)
end)
end)
end
return M

View File

@ -0,0 +1,19 @@
local M = {}
function M.smart_quit()
local bufnr = vim.api.nvim_get_current_buf()
local modified = vim.api.nvim_buf_get_option(bufnr, "modified")
if modified then
vim.ui.input({
prompt = "You have unsaved changes. Quit anyway? (y/n) ",
}, function(input)
if input == "y" then
vim.cmd "q!"
end
end)
else
vim.cmd "q!"
end
end
return M

View File

@ -0,0 +1,140 @@
local M = {}
local Log = require "lvim.core.log"
local if_nil = vim.F.if_nil
local function git_cmd(opts)
local plenary_loaded, Job = pcall(require, "plenary.job")
if not plenary_loaded then
return 1, { "" }
end
opts = opts or {}
opts.cwd = opts.cwd or get_lvim_base_dir()
local stderr = {}
local stdout, ret = Job
:new({
command = "git",
args = opts.args,
cwd = opts.cwd,
on_stderr = function(_, data)
table.insert(stderr, data)
end,
})
:sync()
if not vim.tbl_isempty(stderr) then
Log:debug(stderr)
end
if not vim.tbl_isempty(stdout) then
Log:debug(stdout)
end
return ret, stdout
end
local function safe_deep_fetch()
local ret, result = git_cmd { args = { "rev-parse", "--is-shallow-repository" } }
if ret ~= 0 then
Log:error "Git fetch failed! Check the log for further information"
return
end
-- git fetch --unshallow will cause an error on a a complete clone
local fetch_mode = result[1] == "true" and "--unshallow" or "--all"
ret = git_cmd { args = { "fetch", fetch_mode } }
if ret ~= 0 then
Log:error "Git fetch failed! Check the log for further information"
return
end
return true
end
---pulls the latest changes from github
function M.update_base_lvim()
Log:info "Checking for updates"
local ret = git_cmd { args = { "fetch" } }
if ret ~= 0 then
Log:error "Update failed! Check the log for further information"
return
end
ret = git_cmd { args = { "diff", "--quiet", "@{upstream}" } }
if ret == 0 then
Log:info "LunarVim is already up-to-date"
return
end
ret = git_cmd { args = { "merge", "--ff-only", "--progress" } }
if ret ~= 0 then
Log:error "Update failed! Please pull the changes manually instead."
return
end
return true
end
---Switch Lunarvim to the specified development branch
---@param branch string
function M.switch_lvim_branch(branch)
if not safe_deep_fetch() then
return
end
local args = { "switch", branch }
if branch:match "^[0-9]" then
-- avoids producing an error for tags
vim.list_extend(args, { "--detach" })
end
local ret = git_cmd { args = args }
if ret ~= 0 then
Log:error "Unable to switch branches! Check the log for further information"
return
end
return true
end
---Get the current Lunarvim development branch
---@return string|nil
function M.get_lvim_branch()
local _, results = git_cmd { args = { "rev-parse", "--abbrev-ref", "HEAD" } }
local branch = if_nil(results[1], "")
return branch
end
---Get currently checked-out tag of Lunarvim
---@return string
function M.get_lvim_tag()
local args = { "describe", "--tags", "--abbrev=0" }
local _, results = git_cmd { args = args }
local tag = if_nil(results[1], "")
return tag
end
---Get currently running version of Lunarvim
---@return string
function M.get_lvim_version()
local current_branch = M.get_lvim_branch()
local lvim_version
if current_branch ~= "HEAD" or "" then
lvim_version = current_branch .. "-" .. M.get_lvim_current_sha()
else
lvim_version = "v" .. M.get_lvim_tag()
end
return lvim_version
end
---Get the commit hash of currently checked-out commit of Lunarvim
---@return string|nil
function M.get_lvim_current_sha()
local _, log_results = git_cmd { args = { "log", "--pretty=format:%h", "-1" } }
local abbrev_version = if_nil(log_results[1], "")
return abbrev_version
end
return M

View File

@ -0,0 +1,87 @@
local M = {}
local Log = require "lvim.core.log"
local in_headless = #vim.api.nvim_list_uis() == 0
function M.run_pre_update()
Log:debug "Starting pre-update hook"
end
function M.run_pre_reload()
Log:debug "Starting pre-reload hook"
end
function M.run_on_packer_complete()
Log:debug "Packer operation complete"
vim.api.nvim_exec_autocmds("User", { pattern = "PackerComplete" })
vim.g.colors_name = lvim.colorscheme
pcall(vim.cmd, "colorscheme " .. lvim.colorscheme)
if M._reload_triggered then
Log:info "Reloaded configuration"
M._reload_triggered = nil
end
end
function M.run_post_reload()
Log:debug "Starting post-reload hook"
M.reset_cache()
M._reload_triggered = true
end
---Reset any startup cache files used by Packer and Impatient
---It also forces regenerating any template ftplugin files
---Tip: Useful for clearing any outdated settings
function M.reset_cache()
local impatient = _G.__luacache
if impatient then
impatient.clear_cache()
end
local lvim_modules = {}
for module, _ in pairs(package.loaded) do
if module:match "lvim.core" or module:match "lvim.lsp" then
package.loaded[module] = nil
table.insert(lvim_modules, module)
end
end
Log:trace(string.format("Cache invalidated for core modules: { %s }", table.concat(lvim_modules, ", ")))
require("lvim.lsp.templates").generate_templates()
end
function M.run_post_update()
Log:debug "Starting post-update hook"
if vim.fn.has "nvim-0.7" ~= 1 then
local compat_tag = "1.1.3"
vim.notify(
"Please upgrade your Neovim base installation. Newer version of Lunarvim requires v0.7+",
vim.log.levels.WARN
)
vim.wait(1000, function()
return false
end)
local ret = require_clean("lvim.utils.git").switch_lvim_branch(compat_tag)
if ret then
vim.notify("Reverted to the last known compatibile version: " .. compat_tag, vim.log.levels.WARN)
end
return
end
M.reset_cache()
Log:debug "Syncing core plugins"
require("lvim.plugin-loader").sync_core_plugins()
if not in_headless then
vim.schedule(function()
if package.loaded["nvim-treesitter"] then
vim.cmd [[ TSUpdateSync ]]
end
-- TODO: add a changelog
vim.notify("Update complete", vim.log.levels.INFO)
end)
end
end
return M

View File

@ -0,0 +1,24 @@
local Table = {}
--- Find the first entry for which the predicate returns true.
-- @param t The table
-- @param predicate The function called for each entry of t
-- @return The entry for which the predicate returned True or nil
function Table.find_first(t, predicate)
for _, entry in pairs(t) do
if predicate(entry) then
return entry
end
end
return nil
end
--- Check if the predicate returns True for at least one entry of the table.
-- @param t The table
-- @param predicate The function called for each entry of t
-- @return True if predicate returned True at least once, false otherwise
function Table.contains(t, predicate)
return Table.find_first(t, predicate) ~= nil
end
return Table

View File

@ -0,0 +1,113 @@
{
"Comment.nvim": {
"commit": "3c69bab"
},
"FixCursorHold.nvim": {
"commit": "1bfb32e"
},
"LuaSnip": {
"commit": "79b2019"
},
"alpha-nvim": {
"commit": "ef27a59"
},
"bufferline.nvim": {
"commit": "c78b3ec"
},
"cmp-buffer": {
"commit": "12463cf"
},
"cmp-nvim-lsp": {
"commit": "affe808"
},
"cmp-path": {
"commit": "466b6b8"
},
"cmp_luasnip": {
"commit": "a9de941"
},
"dap-buddy.nvim": {
"commit": "bbda2b0"
},
"friendly-snippets": {
"commit": "d27a83a"
},
"gitsigns.nvim": {
"commit": "c18e016"
},
"lua-dev.nvim": {
"commit": "54149d1"
},
"lualine.nvim": {
"commit": "3362b28"
},
"nlsp-settings.nvim": {
"commit": "62d72bc"
},
"null-ls.nvim": {
"commit": "ff40739"
},
"nvim-autopairs": {
"commit": "fa6876f"
},
"nvim-cmp": {
"commit": "df6734a"
},
"nvim-dap": {
"commit": "014ebd5"
},
"nvim-lsp-installer": {
"commit": "2408a0f"
},
"nvim-lspconfig": {
"commit": "10c3934"
},
"nvim-notify": {
"commit": "8960269"
},
"nvim-tree.lua": {
"commit": "bdb6d4a"
},
"nvim-treesitter": {
"commit": "518e275"
},
"nvim-ts-context-commentstring": {
"commit": "8834375"
},
"nvim-web-devicons": {
"commit": "8d2c533"
},
"onedarker.nvim": {
"commit": "b00dd21"
},
"packer.nvim": {
"commit": "00ec5ad"
},
"plenary.nvim": {
"commit": "968a4b9"
},
"popup.nvim": {
"commit": "b7404d3"
},
"project.nvim": {
"commit": "541115e"
},
"schemastore.nvim": {
"commit": "a32911d"
},
"structlog.nvim": {
"commit": "232a8e2"
},
"telescope-fzf-native.nvim": {
"commit": "6a33ece"
},
"telescope.nvim": {
"commit": "d96eaa9"
},
"toggleterm.nvim": {
"commit": "aaeed9e"
},
"which-key.nvim": {
"commit": "f03a259"
}
}

View File

@ -0,0 +1,48 @@
local M = {}
function M.search_file(file, args)
local Job = require "plenary.job"
local stderr = {}
local stdout, ret = Job
:new({
command = "grep",
args = { args, file },
cwd = get_cache_dir(),
on_stderr = function(_, data)
table.insert(stderr, data)
end,
})
:sync()
return ret, stdout, stderr
end
function M.file_contains(file, query)
local ret, stdout, stderr = M.search_file(file, query)
if ret == 0 then
return true
end
if not vim.tbl_isempty(stderr) then
error(vim.inspect(stderr))
end
if not vim.tbl_isempty(stdout) then
error(vim.inspect(stdout))
end
return false
end
function M.log_contains(query)
local logfile = require("lvim.core.log"):get_path()
local ret, stdout, stderr = M.search_file(logfile, query)
if ret == 0 then
return true
end
if not vim.tbl_isempty(stderr) then
error(vim.inspect(stderr))
end
if not vim.tbl_isempty(stdout) then
error(vim.inspect(stdout))
end
return false
end
return M

View File

@ -0,0 +1,12 @@
local path_sep = vim.loop.os_uname().version:match "Windows" and "\\" or "/"
local base_dir = os.getenv "LUNARVIM_RUNTIME_DIR" .. path_sep .. "lvim"
local tests_dir = base_dir .. path_sep .. "tests"
vim.opt.rtp:append(tests_dir)
vim.opt.rtp:append(base_dir)
require("lvim.bootstrap"):init(base_dir)
-- NOTE: careful about name collisions
-- see https://github.com/nvim-lualine/lualine.nvim/pull/621
require "tests.lvim.helpers"

View File

@ -0,0 +1,114 @@
local on_windows = vim.loop.os_uname().version:match "Windows"
local function join_paths(...)
local path_sep = on_windows and "\\" or "/"
local result = table.concat({ ... }, path_sep)
return result
end
vim.cmd [[set runtimepath=$VIMRUNTIME]]
local temp_dir = vim.loop.os_getenv "TEMP" or "/tmp"
vim.cmd("set packpath=" .. join_paths(temp_dir, "nvim", "site"))
local package_root = join_paths(temp_dir, "nvim", "site", "pack")
local install_path = join_paths(package_root, "packer", "start", "packer.nvim")
local compile_path = join_paths(install_path, "plugin", "packer_compiled.lua")
-- Choose whether to use the executable that's managed by lsp-installer
local use_lsp_installer = true
local function load_plugins()
require("packer").startup {
{
"wbthomason/packer.nvim",
"neovim/nvim-lspconfig",
{ "williamboman/nvim-lsp-installer", disable = not use_lsp_installer },
},
config = {
package_root = package_root,
compile_path = compile_path,
},
}
end
function _G.dump(...)
local objects = vim.tbl_map(vim.inspect, { ... })
print(unpack(objects))
return ...
end
_G.load_config = function()
vim.lsp.set_log_level "trace"
require("vim.lsp.log").set_format_func(vim.inspect)
local nvim_lsp = require "lspconfig"
local on_attach = function(_, bufnr)
local function buf_set_keymap(...)
vim.api.nvim_buf_set_keymap(bufnr, ...)
end
local function buf_set_option(...)
vim.api.nvim_buf_set_option(bufnr, ...)
end
buf_set_option("omnifunc", "v:lua.vim.lsp.omnifunc")
-- Mappings.
local opts = { noremap = true, silent = true }
buf_set_keymap("n", "gD", "<Cmd>lua vim.lsp.buf.declaration()<CR>", opts)
buf_set_keymap("n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>", opts)
buf_set_keymap("n", "K", "<Cmd>lua vim.lsp.buf.hover()<CR>", opts)
buf_set_keymap("n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", opts)
buf_set_keymap("n", "<C-k>", "<cmd>lua vim.lsp.buf.signature_help()<CR>", opts)
buf_set_keymap("n", "<space>wa", "<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>", opts)
buf_set_keymap("n", "<space>wr", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>", opts)
buf_set_keymap("n", "<space>wl", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>", opts)
buf_set_keymap("n", "<space>lD", "<cmd>lua vim.lsp.buf.type_definition()<CR>", opts)
buf_set_keymap("n", "<space>lr", "<cmd>lua vim.lsp.buf.rename()<CR>", opts)
buf_set_keymap("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>", opts)
buf_set_keymap("n", "gl", "<cmd>lua vim.diagnostic.open_float(0,{scope='line'})<CR>", opts)
buf_set_keymap("n", "<space>lk", "<cmd>lua vim.diagnostic.goto_prev()<CR>", opts)
buf_set_keymap("n", "<space>lj", "<cmd>lua vim.diagnostic.goto_next()<CR>", opts)
buf_set_keymap("n", "<space>lq", "<cmd>lua vim.diagnostic.setloclist()<CR>", opts)
buf_set_keymap("n", "<space>li", "<cmd>LspInfo<CR>", opts)
buf_set_keymap("n", "<space>lI", "<cmd>LspInstallInfo<CR>", opts)
end
-- Add the server that troubles you here, e.g. "clangd", "pyright", "tsserver"
local name = "sumneko_lua"
local setup_opts = {
on_attach = on_attach,
}
if use_lsp_installer then
local server_available, server = require("nvim-lsp-installer.servers").get_server(name)
if not server_available then
server:install()
end
local default_opts = server:get_default_options()
setup_opts = vim.tbl_deep_extend("force", setup_opts, default_opts)
end
if not name then
print "You have not defined a server name, please edit minimal_init.lua"
end
if not nvim_lsp[name].document_config.default_config.cmd and not setup_opts.cmd then
print [[You have not defined a server default cmd for a server
that requires it please edit minimal_init.lua]]
end
nvim_lsp[name].setup(setup_opts)
print [[You can find your log at $HOME/.cache/nvim/lsp.log. Please paste in a github issue under a details tag as described in the issue template.]]
end
if vim.fn.isdirectory(install_path) == 0 then
vim.fn.system { "git", "clone", "https://github.com/wbthomason/packer.nvim", install_path }
load_plugins()
require("packer").sync()
vim.cmd [[autocmd User PackerComplete ++once lua load_config()]]
else
load_plugins()
require("packer").sync()
_G.load_config()
end

View File

@ -0,0 +1,42 @@
local a = require "plenary.async_lib.tests"
local uv = vim.loop
local home_dir = uv.os_homedir()
a.describe("initial start", function()
local lvim_config_path = get_config_dir()
local lvim_runtime_path = get_runtime_dir()
local lvim_cache_path = get_cache_dir()
a.it("should be able to detect test environment", function()
assert.truthy(os.getenv "LVIM_TEST_ENV")
assert.falsy(package.loaded["lvim.impatient"])
end)
a.it("should be able to use lunarvim cache directory using vim.fn", function()
assert.equal(lvim_cache_path, vim.fn.stdpath "cache")
end)
a.it("should be to retrieve default neovim directories", function()
local xdg_config = os.getenv "XDG_CONFIG_HOME" or join_paths(home_dir, ".config")
assert.equal(join_paths(xdg_config, "nvim"), vim.call("stdpath", "config"))
end)
a.it("should be able to read lunarvim directories", function()
local rtp_list = vim.opt.rtp:get()
assert.truthy(vim.tbl_contains(rtp_list, lvim_runtime_path .. "/lvim"))
assert.truthy(vim.tbl_contains(rtp_list, lvim_config_path))
end)
a.it("should be able to run treesitter without errors", function()
assert.truthy(vim.treesitter.highlighter.active)
end)
a.it("should be able to pass basic checkhealth without errors", function()
vim.cmd "set cmdheight&"
vim.cmd "checkhealth nvim"
local errmsg = vim.fn.eval "v:errmsg"
local exception = vim.fn.eval "v:exception"
assert.equal("", errmsg) -- v:errmsg was not updated.
assert.equal("", exception)
end)
end)

View File

@ -0,0 +1,55 @@
local a = require "plenary.async_lib.tests"
local config = require "lvim.config"
local fmt = string.format
a.describe("config-loader", function()
local user_config_path = join_paths(get_config_dir(), "config.lua")
local default_config_path = join_paths(get_lvim_base_dir(), "utils", "installer", "config.example.lua")
before_each(function()
os.execute(fmt("cp -f %s %s", default_config_path, user_config_path))
vim.cmd [[
let v:errmsg = ""
let v:errors = []
]]
end)
after_each(function()
local errmsg = vim.fn.eval "v:errmsg"
local exception = vim.fn.eval "v:exception"
local errors = vim.fn.eval "v:errors"
assert.equal("", errmsg)
assert.equal("", exception)
assert.True(vim.tbl_isempty(errors))
end)
a.it("should be able to find user-config", function()
assert.equal(user_config_path, get_config_dir() .. "/config.lua")
end)
a.it("should be able to load user-config without errors", function()
config:load(user_config_path)
end)
a.it("should be able to reload user-config without errors", function()
config:load(user_config_path)
local test_path = "/tmp/lvim"
os.execute(string.format([[echo "vim.opt.undodir = '%s'" >> %s]], test_path, user_config_path))
config:reload()
vim.schedule(function()
assert.equal(vim.opt.undodir:get()[1], test_path)
end)
end)
a.it("should not get interrupted by errors in user-config", function()
local test_path = "/tmp/lunarvim"
os.execute(string.format([[echo "vim.opt.undodir = '%s'" >> %s]], test_path, user_config_path))
config:load(user_config_path)
assert.equal(vim.opt.undodir:get()[1], test_path)
require("lvim.core.log"):set_level "error"
os.execute(string.format("echo 'invalid_function()' >> %s", user_config_path))
config:load(user_config_path)
require("lvim.core.log"):set_level "error"
assert.equal(vim.opt.undodir:get()[1], test_path)
end)
end)

View File

@ -0,0 +1,82 @@
local a = require "plenary.async_lib.tests"
local utils = require "lvim.utils"
local helpers = require "tests.lvim.helpers"
local spy = require "luassert.spy"
a.describe("lsp workflow", function()
before_each(function()
vim.cmd [[
let v:errmsg = ""
let v:errors = []
]]
end)
after_each(function()
local errmsg = vim.fn.eval "v:errmsg"
local exception = vim.fn.eval "v:exception"
local errors = vim.fn.eval "v:errors"
assert.equal("", errmsg)
assert.equal("", exception)
assert.True(vim.tbl_isempty(errors))
end)
lvim.lsp.templates_dir = join_paths(get_cache_dir(), "artifacts")
a.it("should be able to delete ftplugin templates", function()
if utils.is_directory(lvim.lsp.templates_dir) then
assert.equal(vim.fn.delete(lvim.lsp.templates_dir, "rf"), 0)
end
assert.False(utils.is_directory(lvim.lsp.templates_dir))
end)
a.it("should be able to generate ftplugin templates", function()
if utils.is_directory(lvim.lsp.templates_dir) then
assert.equal(vim.fn.delete(lvim.lsp.templates_dir, "rf"), 0)
end
require("lvim.lsp").setup()
assert.True(utils.is_directory(lvim.lsp.templates_dir))
end)
a.it("should not include blacklisted servers in the generated templates", function()
require("lvim.lsp").setup()
for _, file in ipairs(vim.fn.glob(lvim.lsp.templates_dir .. "/*.lua", 1, 1)) do
for _, server_name in ipairs(lvim.lsp.override) do
local setup_cmd = string.format([[require("lvim.lsp.manager").setup(%q)]], server_name)
assert.False(helpers.file_contains(file, setup_cmd))
end
end
end)
a.it("should only include one server per generated template", function()
require("lvim.lsp").setup()
for _, file in ipairs(vim.fn.glob(lvim.lsp.templates_dir .. "/*.lua", 1, 1)) do
local content = {}
for entry in io.lines(file) do
table.insert(content, entry)
end
local err_msg = ""
if #content > 1 then
err_msg = string.format(
"found more than one server for [%q]: \n{\n %q \n}",
file:match "[^/]*.lua$",
table.concat(content, ", ")
)
end
assert.equal(err_msg, "")
end
end)
a.it("should not attempt to re-generate ftplugin templates", function()
local s = spy.on(require "lvim.lsp.templates", "generate_templates")
local plugins = require "lvim.plugins"
require("lvim.plugin-loader").load { plugins, lvim.plugins }
require("lvim.lsp").setup()
assert.spy(s).was_not_called()
s:revert()
end)
end)

View File

@ -0,0 +1,74 @@
local a = require "plenary.async_lib.tests"
a.describe("plugin-loader", function()
local plugins = require "lvim.plugins"
local loader = require "lvim.plugin-loader"
pcall(function()
lvim.log.level = "debug"
package.loaded["packer.log"] = nil
package.loaded["lvim.core.log"] = nil
end)
a.it("should be able to load default packages without errors", function()
loader.load { plugins, lvim.plugins }
-- TODO: maybe there's a way to avoid hard-coding the names of the modules?
local startup_plugins = {
"packer",
}
for _, plugin in ipairs(startup_plugins) do
assert.truthy(package.loaded[plugin])
end
end)
a.it("should be able to load lsp packages without errors", function()
loader.load { plugins, lvim.plugins }
require("lvim.lsp").setup()
local lsp_packages = {
"lspconfig",
"nlspsettings",
"null-ls",
}
for _, plugin in ipairs(lsp_packages) do
assert.truthy(package.loaded[plugin])
end
end)
pending("should be able to rollback plugins without errors", function()
local plugin = { name = "onedarker.nvim" }
plugin.path = vim.tbl_filter(function(package)
return package:match(plugin.name)
end, vim.api.nvim_list_runtime_paths())[1]
local get_current_sha = function(repo)
local res = vim.fn.system(string.format("git -C %s log -1 --pretty=%%h", repo)):gsub("\n", "")
return res
end
plugin.test_sha = "316b1c9"
_G.locked_sha = get_current_sha(plugin.path)
loader.load { plugins, lvim.plugins }
os.execute(string.format("git -C %s fetch --deepen 999 --quiet", plugin.path))
os.execute(string.format("git -C %s checkout %s --quiet", plugin.path, plugin.test_sha))
assert.equal(plugin.test_sha, get_current_sha(plugin.path))
_G.completed = false
_G.verify_sha = function()
if _G.locked_sha ~= get_current_sha(plugin.path) then
error "unmached results!"
else
_G.completed = true
end
end
vim.cmd [[autocmd User PackerComplete ++once lua _G.verify_sha()]]
loader.load_snapshot()
local ret = vim.wait(30 * 10 * 1000, function()
return _G.completed == true
end, 200)
assert.True(ret)
end)
end)

View File

@ -0,0 +1,62 @@
#!/usr/bin/env bash
# NOTE:
# This doesn't work as is on Windows. You'll need to create an equivalent `.bat` file instead
#
# NOTE:
# If you're not using Linux you'll need to adjust the `-configuration` option
# to point to the `config_mac' or `config_win` folders depending on your system.
case Darwin in
Linux)
CONFIG="$HOME/.local/share/nvim/lsp_servers/jdtls/config_linux"
;;
Darwin)
CONFIG="$HOME/.local/share/nvim/lsp_servers/jdtls/config_mac"
;;
esac
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ]; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# JAR="$HOME/.config/nvim/.language-servers/eclipse.jdt.ls/org.eclipse.jdt.ls.product/target/repository/plugins/org.eclipse.equinox.launcher_*.jar"
JAR="$HOME/.local/share/nvim/lsp_servers/jdtls/plugins/org.eclipse.equinox.launcher_*.jar"
GRADLE_HOME=$HOME/gradle "$JAVACMD" \
-Declipse.application=org.eclipse.jdt.ls.core.id1 \
-Dosgi.bundles.defaultStartLevel=4 \
-Declipse.product=org.eclipse.jdt.ls.core.product \
-Dlog.protocol=true \
-Dlog.level=ALL \
-javaagent:$HOME/.local/share/nvim/lsp_servers/jdtls/lombok.jar \
-Xms1g \
-Xmx2G \
-jar $(echo "$JAR") \
-configuration "$CONFIG" \
-data "${1:-$HOME/workspace}" \
--add-modules=ALL-SYSTEM \
--add-opens java.base/java.util=ALL-UNNAMED \
--add-opens java.base/java.lang=ALL-UNNAMED
# for older java versions if you wanna use lombok
# -Xbootclasspath/a:/usr/local/share/lombok/lombok.jar \
# -javaagent:/usr/local/share/lombok/lombok.jar \

View File

@ -0,0 +1,13 @@
#Requires -Version 7.1
$ErrorActionPreference = "Stop" # exit when command fails
$env:XDG_DATA_HOME = $env:XDG_DATA_HOME ?? $env:APPDATA
$env:XDG_CONFIG_HOME = $env:XDG_CONFIG_HOME ?? $env:LOCALAPPDATA
$env:XDG_CACHE_HOME = $env:XDG_CACHE_HOME ?? $env:TEMP
$env:LUNARVIM_RUNTIME_DIR = $env:LUNARVIM_RUNTIME_DIR ?? "$env:XDG_DATA_HOME\lunarvim"
$env:LUNARVIM_CONFIG_DIR = $env:LUNARVIM_CONFIG_DIR ?? "$env:XDG_CONFIG_HOME\lvim"
$env:LUNARVIM_CACHE_DIR = $env:LUNARVIM_CACHE_DIR ?? "$env:XDG_CACHE_HOME\lvim"
$env:LUNARVIM_BASE_DIR = $env:LUNARVIM_BASE_DIR ?? "$env:LUNARVIM_RUNTIME_DIR\lvim"
nvim -u "$env:LUNARVIM_RUNTIME_DIR\lvim\init.lua" @args

View File

@ -0,0 +1,7 @@
#!/bin/sh
export LUNARVIM_RUNTIME_DIR="${LUNARVIM_RUNTIME_DIR:-RUNTIME_DIR_VAR}"
export LUNARVIM_CONFIG_DIR="${LUNARVIM_CONFIG_DIR:-CONFIG_DIR_VAR}"
export LUNARVIM_CACHE_DIR="${LUNARVIM_CACHE_DIR:-CACHE_DIR_VAR}"
exec nvim -u "$LUNARVIM_RUNTIME_DIR/lvim/init.lua" "$@"

View File

@ -0,0 +1,115 @@
local sp = os.getenv "SNAPSHOT_PATH"
local function call_proc(process, opts, cb)
local output, error_output = "", ""
local handle_stdout = function(err, chunk)
assert(not err, err)
if chunk then
output = output .. chunk
end
end
local handle_stderr = function(err, chunk)
assert(not err, err)
if chunk then
error_output = error_output .. chunk
end
end
local uv = vim.loop
local handle
local stdout = uv.new_pipe(false)
local stderr = uv.new_pipe(false)
local stdio = { nil, stdout, stderr }
handle = uv.spawn(
process,
{ args = opts.args, cwd = opts.cwd or uv.cwd(), stdio = stdio },
vim.schedule_wrap(function(code)
if code ~= 0 then
stdout:read_stop()
stderr:read_stop()
end
local check = uv.new_check()
check:start(function()
for _, pipe in ipairs(stdio) do
if pipe and not pipe:is_closing() then
return
end
end
check:stop()
handle:close()
cb(code, output, error_output)
end)
end)
)
uv.read_start(stdout, handle_stdout)
uv.read_start(stderr, handle_stderr)
return handle
end
local plugins_list = {}
local completed = 0
local function write_lockfile(verbose)
local default_plugins = {}
local active_jobs = {}
local core_plugins = require "lvim.plugins"
for _, plugin in pairs(core_plugins) do
local name = plugin[1]:match "/(%S*)"
local url = "https://github.com/" .. plugin[1]
local commit = ""
table.insert(default_plugins, {
name = name,
url = url,
commit = commit,
})
end
table.sort(default_plugins, function(a, b)
return a.name < b.name
end)
for _, entry in pairs(default_plugins) do
local on_done = function(success, result, errors)
completed = completed + 1
if not success then
print("error: " .. errors)
return
end
local latest_sha = result:gsub("\tHEAD\n", ""):sub(1, 7)
plugins_list[entry.name] = {
commit = latest_sha,
}
end
local handle = call_proc("git", { args = { "ls-remote", entry.url, "HEAD" } }, on_done)
assert(handle)
table.insert(active_jobs, handle)
end
print("active: " .. #active_jobs)
print("plugins: " .. #default_plugins)
vim.wait(#active_jobs * 60 * 1000, function()
return completed == #active_jobs
end)
if verbose then
print(vim.inspect(plugins_list))
end
local fd = assert(io.open(sp, "w"))
fd:write(vim.json.encode(plugins_list), "\n")
fd:flush()
end
write_lockfile()
vim.cmd "q"

View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -e
REPO_DIR=$(git rev-parse --show-toplevel)
export SNAPSHOT_NAME="default.json"
export SNAPSHOT_DIR="${REPO_DIR}/snapshots"
mkdir -p "${SNAPSHOT_DIR}"
export SNAPSHOT_PATH="${REPO_DIR}/snapshots/${SNAPSHOT_NAME}"
time lvim --headless \
-c "luafile ./utils/ci/generate_new_lockfile.lua"
temp=$(mktemp)
jq --sort-keys . "${SNAPSHOT_PATH}" >"${temp}"
mv "${temp}" "${SNAPSHOT_PATH}"

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -eo pipefail
REPO_DIR="$(git rev-parse --show-toplevel)"
HELP_URL="https://github.com/LunarVim/LunarVim/blob/rolling/CONTRIBUTING.md#commit-messages"
CONFIG="$REPO_DIR/.github/workflows/commitlint.config.js"
if ! npx commitlint --edit --verbose --help-url "$HELP_URL" --config "$CONFIG"; then
exit 1
fi

View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -e
export LUNARVIM_RUNTIME_DIR="${LUNARVIM_RUNTIME_DIR:-"$HOME/.local/share/lunarvim"}"
export LVIM_TEST_ENV=true
# we should start with an empty configuration
LUNARVIM_CONFIG_DIR="$(mktemp -d)"
LUNARVIM_CACHE_DIR="$(mktemp -d)"
export LUNARVIM_CONFIG_DIR LUNARVIM_CACHE_DIR
echo "cache: $LUNARVIM_CACHE_DIR
config: $LUNARVIM_CONFIG_DIR"
lvim() {
nvim -u "$LUNARVIM_RUNTIME_DIR/lvim/tests/minimal_init.lua" --cmd "set runtimepath+=$LUNARVIM_RUNTIME_DIR/lvim" "$@"
}
if [ -n "$1" ]; then
lvim --headless -c "lua require('plenary.busted').run('$1')"
else
lvim --headless -c "PlenaryBustedDirectory tests/specs { minimal_init = './tests/minimal_init.lua' }"
fi

View File

@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -eo pipefail
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
if [ "$BRANCH" != "master" ]; then
exit 0
fi
REPO_DIR="$(git rev-parse --show-toplevel)"
LATEST_TAG="$(git describe --tags --abbrev=0)"
CONFIG_FILE="$REPO_DIR/.github/workflows/cliff.toml"
CHANGELOG="$REPO_DIR/CHANGELOG.md"
git -C "$REPO_DIR" cliff "$LATEST_TAG"..HEAD -u -c "$CONFIG_FILE" -p "$CHANGELOG"

View File

@ -0,0 +1,134 @@
local completed = 0
local collection = {}
local active_jobs = {}
local fmt = string.format
local core_plugins = require "lvim.plugins"
local default_snapshot_path = join_paths(get_lvim_base_dir(), "snapshots", "default.json")
local fd = io.open(default_snapshot_path, "rb")
local content
if fd then
content = fd:read "*a"
end
local default_sha1 = vim.json.decode(content)
local get_short_name = function(spec)
return spec[1]:match "/(%S*)"
end
local get_default_sha1 = function(spec)
local short_name, _ = get_short_name(spec)
assert(default_sha1[short_name])
return default_sha1[short_name].commit
end
local is_directory = require("lvim.utils").is_directory
-- see packer.init()
local packdir = join_paths(get_runtime_dir(), "site", "pack", "packer")
local packer_config = { opt_dir = join_paths(packdir, "opt"), start_dir = join_paths(packdir, "start") }
local is_optional = function(spec)
return spec.opt or spec.event or spec.cmd or spec.module
end
local get_install_path = function(spec)
local prefix = is_optional(spec) and packer_config.opt_dir or packer_config.start_dir
local path = join_paths(prefix, get_short_name(spec))
assert(is_directory(path))
return path
end
local function call_proc(process, opts, cb)
local output, error_output = "", ""
local handle_stdout = function(err, chunk)
assert(not err, err)
if chunk then
output = output .. chunk
end
end
local handle_stderr = function(err, chunk)
assert(not err, err)
if chunk then
error_output = error_output .. chunk
end
end
local uv = vim.loop
local handle
local stdout = uv.new_pipe(false)
local stderr = uv.new_pipe(false)
local stdio = { nil, stdout, stderr }
handle = uv.spawn(
process,
{ args = opts.args, cwd = opts.cwd or uv.cwd(), stdio = stdio },
vim.schedule_wrap(function(code)
if code ~= 0 then
stdout:read_stop()
stderr:read_stop()
end
local check = uv.new_check()
check:start(function()
for _, pipe in ipairs(stdio) do
if pipe and not pipe:is_closing() then
return
end
end
check:stop()
handle:close()
cb(code, output, error_output)
end)
end)
)
uv.read_start(stdout, handle_stdout)
uv.read_start(stderr, handle_stderr)
return handle
end
local function verify_core_plugins(verbose)
for _, spec in pairs(core_plugins) do
if not spec.disable then
table.insert(collection, {
name = get_short_name(spec),
commit = get_default_sha1(spec),
path = get_install_path(spec),
})
end
end
for _, entry in pairs(collection) do
local on_done = function(code, result, errors)
completed = completed + 1
if code ~= 0 then
io.write(errors .. "\n")
-- os.exit(code)
else
if verbose then
io.write(fmt("verified [%s]\n", entry.name))
end
end
local current_commit = result:gsub("\n", ""):gsub([[']], [[]])
-- just in case there are some extra qutoes or it's a longer commit hash
if current_commit ~= entry.commit then
io.write(fmt("mismatch at [%s]: expected [%s], got [%s]\n", entry.name, entry.commit, current_commit))
os.exit(1)
end
end
local handle = call_proc("git", { args = { "log", "--pretty='%h'", "-1" }, cwd = entry.path }, on_done)
assert(handle)
table.insert(active_jobs, handle)
end
vim.wait(#active_jobs * 60 * 1000, function()
return completed == #active_jobs
end)
end
verify_core_plugins()
vim.cmd "q"

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -e
BASEDIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
BASEDIR="$(dirname -- "$(dirname -- "$BASEDIR")")"
LUNARVIM_BASE_DIR="${LUNARVIM_BASE_DIR:-"$BASEDIR"}"
lvim --headless \
-c "luafile ${LUNARVIM_BASE_DIR}/utils/ci/verify_plugins.lua"

View File

@ -0,0 +1,13 @@
[Desktop Entry]
Name=LunarVim
GenericName=Text Editor
Comment=An IDE layer for Neovim with sane defaults. Completely free and community driven.
TryExec=lvim
Exec=lvim %F
Terminal=true
Type=Application
Keywords=Text;editor;
Icon=nvim
Categories=Utility;TextEditor;
StartupNotify=false
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;

View File

@ -0,0 +1,27 @@
# To run this file execute:
# docker build -f <Path to this file> <Path to Lunarvim basedir> -t Lunarvim:local
FROM ubuntu:latest
# Set environment correctly
ENV DEBIAN_FRONTEND=noninteractive
ENV PATH="/root/.local/bin:/root/.cargo/bin:/root/.npm-global/bin${PATH}"
# Copy in local directory
COPY --chown=root:root . /LunarVim
# Install dependencies and LunarVim
RUN apt update && \
apt -y install sudo curl build-essential git fzf python3-dev python3-pip cargo && \
curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
apt update && \
apt -y install nodejs && \
apt clean && rm -rf /var/lib/apt/lists/* /tmp/* && \
/LunarVim/utils/installer/install-neovim-from-release && \
/LunarVim/utils/installer/install.sh --local --no-install-dependencies
# Setup LVIM to run on startup
ENTRYPOINT ["/bin/bash"]
CMD ["lvim"]
# vim: ft=dockerfile:

View File

@ -0,0 +1,27 @@
# To run this file execute:
# docker build -f Dockerfile.remote . -t Lunarvim:remote
FROM ubuntu:latest
# Build argument to point to correct branch on GitHub
ARG LV_BRANCH=rolling
# Set environment correctly
ENV DEBIAN_FRONTEND=noninteractive
ENV PATH="/root/.local/bin:/root/.cargo/bin:/root/.npm-global/bin${PATH}"
# Install dependencies and LunarVim
RUN apt update && \
apt -y install sudo curl build-essential git fzf python3-dev python3-pip cargo && \
curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
apt update && \
apt -y install nodejs && \
apt clean && rm -rf /var/lib/apt/lists/* /tmp/* && \
curl -LSs https://raw.githubusercontent.com/lunarvim/lunarvim/${LV_BRANCH}/utils/installer/install-neovim-from-release | bash && \
LV_BRANCH=${LV_BRANCH} curl -LSs https://raw.githubusercontent.com/lunarvim/lunarvim/${LV_BRANCH}/utils/installer/install.sh | bash -s -- --no-install-dependencies
# Setup LVIM to run on startup
ENTRYPOINT ["/bin/bash"]
CMD ["lvim"]
# vim: ft=dockerfile:

View File

@ -0,0 +1,167 @@
--[[
lvim is the global options object
Linters should be
filled in as strings with either
a global executable or a path to
an executable
]]
-- THESE ARE EXAMPLE CONFIGS FEEL FREE TO CHANGE TO WHATEVER YOU WANT
-- general
lvim.log.level = "warn"
lvim.format_on_save = true
lvim.colorscheme = "onedarker"
-- to disable icons and use a minimalist setup, uncomment the following
-- lvim.use_icons = false
-- keymappings [view all the defaults by pressing <leader>Lk]
lvim.leader = "space"
-- add your own keymapping
lvim.keys.normal_mode["<C-s>"] = ":w<cr>"
-- unmap a default keymapping
-- vim.keymap.del("n", "<C-Up>")
-- override a default keymapping
-- lvim.keys.normal_mode["<C-q>"] = ":q<cr>" -- or vim.keymap.set("n", "<C-q>", ":q<cr>" )
-- Change Telescope navigation to use j and k for navigation and n and p for history in both input and normal mode.
-- we use protected-mode (pcall) just in case the plugin wasn't loaded yet.
-- local _, actions = pcall(require, "telescope.actions")
-- lvim.builtin.telescope.defaults.mappings = {
-- -- for input mode
-- i = {
-- ["<C-j>"] = actions.move_selection_next,
-- ["<C-k>"] = actions.move_selection_previous,
-- ["<C-n>"] = actions.cycle_history_next,
-- ["<C-p>"] = actions.cycle_history_prev,
-- },
-- -- for normal mode
-- n = {
-- ["<C-j>"] = actions.move_selection_next,
-- ["<C-k>"] = actions.move_selection_previous,
-- },
-- }
-- Use which-key to add extra bindings with the leader-key prefix
-- lvim.builtin.which_key.mappings["P"] = { "<cmd>Telescope projects<CR>", "Projects" }
-- lvim.builtin.which_key.mappings["t"] = {
-- name = "+Trouble",
-- r = { "<cmd>Trouble lsp_references<cr>", "References" },
-- f = { "<cmd>Trouble lsp_definitions<cr>", "Definitions" },
-- d = { "<cmd>Trouble document_diagnostics<cr>", "Diagnostics" },
-- q = { "<cmd>Trouble quickfix<cr>", "QuickFix" },
-- l = { "<cmd>Trouble loclist<cr>", "LocationList" },
-- w = { "<cmd>Trouble workspace_diagnostics<cr>", "Wordspace Diagnostics" },
-- }
-- TODO: User Config for predefined plugins
-- After changing plugin config exit and reopen LunarVim, Run :PackerInstall :PackerCompile
lvim.builtin.alpha.active = true
lvim.builtin.alpha.mode = "dashboard"
lvim.builtin.notify.active = true
lvim.builtin.terminal.active = true
lvim.builtin.nvimtree.setup.view.side = "left"
lvim.builtin.nvimtree.setup.renderer.icons.show.git = false
-- if you don't want all the parsers change this to a table of the ones you want
lvim.builtin.treesitter.ensure_installed = {
"bash",
"c",
"javascript",
"json",
"lua",
"python",
"typescript",
"tsx",
"css",
"rust",
"java",
"yaml",
}
lvim.builtin.treesitter.ignore_install = { "haskell" }
lvim.builtin.treesitter.highlight.enabled = true
-- generic LSP settings
-- ---@usage disable automatic installation of servers
-- lvim.lsp.automatic_servers_installation = false
-- ---configure a server manually. !!Requires `:LvimCacheReset` to take effect!!
-- ---see the full default list `:lua print(vim.inspect(lvim.lsp.automatic_configuration.skipped_servers))`
-- vim.list_extend(lvim.lsp.automatic_configuration.skipped_servers, { "pyright" })
-- local opts = {} -- check the lspconfig documentation for a list of all possible options
-- require("lvim.lsp.manager").setup("pyright", opts)
-- ---remove a server from the skipped list, e.g. eslint, or emmet_ls. !!Requires `:LvimCacheReset` to take effect!!
-- ---`:LvimInfo` lists which server(s) are skiipped for the current filetype
-- vim.tbl_map(function(server)
-- return server ~= "emmet_ls"
-- end, lvim.lsp.automatic_configuration.skipped_servers)
-- -- you can set a custom on_attach function that will be used for all the language servers
-- -- See <https://github.com/neovim/nvim-lspconfig#keybindings-and-completion>
-- lvim.lsp.on_attach_callback = function(client, bufnr)
-- local function buf_set_option(...)
-- vim.api.nvim_buf_set_option(bufnr, ...)
-- end
-- --Enable completion triggered by <c-x><c-o>
-- buf_set_option("omnifunc", "v:lua.vim.lsp.omnifunc")
-- end
-- -- set a formatter, this will override the language server formatting capabilities (if it exists)
-- local formatters = require "lvim.lsp.null-ls.formatters"
-- formatters.setup {
-- { command = "black", filetypes = { "python" } },
-- { command = "isort", filetypes = { "python" } },
-- {
-- -- each formatter accepts a list of options identical to https://github.com/jose-elias-alvarez/null-ls.nvim/blob/main/doc/BUILTINS.md#Configuration
-- command = "prettier",
-- ---@usage arguments to pass to the formatter
-- -- these cannot contain whitespaces, options such as `--line-width 80` become either `{'--line-width', '80'}` or `{'--line-width=80'}`
-- extra_args = { "--print-with", "100" },
-- ---@usage specify which filetypes to enable. By default a providers will attach to all the filetypes it supports.
-- filetypes = { "typescript", "typescriptreact" },
-- },
-- }
-- -- set additional linters
-- local linters = require "lvim.lsp.null-ls.linters"
-- linters.setup {
-- { command = "flake8", filetypes = { "python" } },
-- {
-- -- each linter accepts a list of options identical to https://github.com/jose-elias-alvarez/null-ls.nvim/blob/main/doc/BUILTINS.md#Configuration
-- command = "shellcheck",
-- ---@usage arguments to pass to the formatter
-- -- these cannot contain whitespaces, options such as `--line-width 80` become either `{'--line-width', '80'}` or `{'--line-width=80'}`
-- extra_args = { "--severity", "warning" },
-- },
-- {
-- command = "codespell",
-- ---@usage specify which filetypes to enable. By default a providers will attach to all the filetypes it supports.
-- filetypes = { "javascript", "python" },
-- },
-- }
-- Additional Plugins
-- lvim.plugins = {
-- {"folke/tokyonight.nvim"},
-- {
-- "folke/trouble.nvim",
-- cmd = "TroubleToggle",
-- },
-- }
-- Autocommands (https://neovim.io/doc/user/autocmd.html)
-- vim.api.nvim_create_autocmd("BufEnter", {
-- pattern = { "*.json", "*.jsonc" },
-- -- enable wrap mode for json files only
-- command = "setlocal wrap",
-- })
-- vim.api.nvim_create_autocmd("FileType", {
-- pattern = "zsh",
-- callback = function()
-- -- let treesitter use bash highlight for zsh files as well
-- require("nvim-treesitter.highlight").attach(0, "bash")
-- end,
-- })

View File

@ -0,0 +1,182 @@
--[[
THESE ARE EXAMPLE CONFIGS FEEL FREE TO CHANGE TO WHATEVER YOU WANT
`lvim` is the global options object
]]
-- Enable powershell as your default shell
vim.opt.shell = "pwsh.exe -NoLogo"
vim.opt.shellcmdflag =
"-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.Encoding]::UTF8;"
vim.cmd [[
let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s; exit $LastExitCode'
let &shellpipe = '2>&1 | Out-File -Encoding UTF8 %s; exit $LastExitCode'
set shellquote= shellxquote=
]]
-- Set a compatible clipboard manager
vim.g.clipboard = {
copy = {
["+"] = "win32yank.exe -i --crlf",
["*"] = "win32yank.exe -i --crlf",
},
paste = {
["+"] = "win32yank.exe -o --lf",
["*"] = "win32yank.exe -o --lf",
},
}
-- general
lvim.log.level = "warn"
lvim.format_on_save = true
lvim.colorscheme = "onedarker"
-- to disable icons and use a minimalist setup, uncomment the following
-- lvim.use_icons = false
-- keymappings [view all the defaults by pressing <leader>Lk]
lvim.leader = "space"
-- add your own keymapping
lvim.keys.normal_mode["<C-s>"] = ":w<cr>"
-- unmap a default keymapping
-- vim.keymap.del("n", "<C-Up>")
-- override a default keymapping
-- lvim.keys.normal_mode["<C-q>"] = ":q<cr>" -- or vim.keymap.set("n", "<C-q>", ":q<cr>" )
-- Change Telescope navigation to use j and k for navigation and n and p for history in both input and normal mode.
-- we use protected-mode (pcall) just in case the plugin wasn't loaded yet.
-- local _, actions = pcall(require, "telescope.actions")
-- lvim.builtin.telescope.defaults.mappings = {
-- -- for input mode
-- i = {
-- ["<C-j>"] = actions.move_selection_next,
-- ["<C-k>"] = actions.move_selection_previous,
-- ["<C-n>"] = actions.cycle_history_next,
-- ["<C-p>"] = actions.cycle_history_prev,
-- },
-- -- for normal mode
-- n = {
-- ["<C-j>"] = actions.move_selection_next,
-- ["<C-k>"] = actions.move_selection_previous,
-- },
-- }
-- Use which-key to add extra bindings with the leader-key prefix
-- lvim.builtin.which_key.mappings["P"] = { "<cmd>Telescope projects<CR>", "Projects" }
-- lvim.builtin.which_key.mappings["t"] = {
-- name = "+Trouble",
-- r = { "<cmd>Trouble lsp_references<cr>", "References" },
-- f = { "<cmd>Trouble lsp_definitions<cr>", "Definitions" },
-- d = { "<cmd>Trouble document_diagnostics<cr>", "Diagnostics" },
-- q = { "<cmd>Trouble quickfix<cr>", "QuickFix" },
-- l = { "<cmd>Trouble loclist<cr>", "LocationList" },
-- w = { "<cmd>Trouble workspace_diagnostics<cr>", "Workspace Diagnostics" },
-- }
-- After changing plugin config exit and reopen LunarVim, Run :PackerInstall :PackerCompile
lvim.builtin.alpha.active = true
lvim.builtin.alpha.mode = "dashboard"
lvim.builtin.notify.active = true
lvim.builtin.terminal.active = false
-- lvim.builtin.terminal.shell = "pwsh.exe -NoLogo"
-- nvim-tree has some performance issues on windows, see kyazdani42/nvim-tree.lua#549
lvim.builtin.nvimtree.setup.diagnostics.enable = false
lvim.builtin.nvimtree.setup.filters.custom = false
lvim.builtin.nvimtree.setup.git.enable = false
lvim.builtin.nvimtree.setup.update_cwd = false
lvim.builtin.nvimtree.setup.update_focused_file.update_cwd = false
lvim.builtin.nvimtree.setup.view.side = "left"
lvim.builtin.nvimtree.setup.renderer.highlight_git = false
lvim.builtin.nvimtree.setup.renderer.icons.show.git = false
-- if you don't want all the parsers change this to a table of the ones you want
lvim.builtin.treesitter.ensure_installed = {
"c",
"lua",
}
lvim.builtin.treesitter.ignore_install = { "haskell" }
lvim.builtin.treesitter.highlight.enabled = true
-- generic LSP settings
-- ---@usage disable automatic installation of servers
-- lvim.lsp.automatic_servers_installation = false
-- ---configure a server manually. !!Requires `:LvimCacheReset` to take effect!!
-- ---see the full default list `:lua print(vim.inspect(lvim.lsp.automatic_configuration.skipped_servers))`
-- vim.list_extend(lvim.lsp.automatic_configuration.skipped_servers, { "pyright" })
-- local opts = {} -- check the lspconfig documentation for a list of all possible options
-- require("lvim.lsp.manager").setup("pyright", opts)
-- ---remove a server from the skipped list, e.g. eslint, or emmet_ls. !!Requires `:LvimCacheReset` to take effect!!
-- ---`:LvimInfo` lists which server(s) are skiipped for the current filetype
-- vim.tbl_map(function(server)
-- return server ~= "emmet_ls"
-- end, lvim.lsp.automatic_configuration.skipped_servers)
-- -- you can set a custom on_attach function that will be used for all the language servers
-- -- See <https://github.com/neovim/nvim-lspconfig#keybindings-and-completion>
-- lvim.lsp.on_attach_callback = function(client, bufnr)
-- local function buf_set_option(...)
-- vim.api.nvim_buf_set_option(bufnr, ...)
-- end
-- --Enable completion triggered by <c-x><c-o>
-- buf_set_option("omnifunc", "v:lua.vim.lsp.omnifunc")
-- end
-- -- set a formatter, this will override the language server formatting capabilities (if it exists)
-- local formatters = require "lvim.lsp.null-ls.formatters"
-- formatters.setup {
-- { command = "black", filetypes = { "python" } },
-- { command = "isort", filetypes = { "python" } },
-- {
-- -- each formatter accepts a list of options identical to https://github.com/jose-elias-alvarez/null-ls.nvim/blob/main/doc/BUILTINS.md#Configuration
-- command = "prettier",
-- ---@usage arguments to pass to the formatter
-- -- these cannot contain whitespaces, options such as `--line-width 80` become either `{'--line-width', '80'}` or `{'--line-width=80'}`
-- extra_args = { "--print-with", "100" },
-- ---@usage specify which filetypes to enable. By default a providers will attach to all the filetypes it supports.
-- filetypes = { "typescript", "typescriptreact" },
-- },
-- }
-- -- set additional linters
-- local linters = require "lvim.lsp.null-ls.linters"
-- linters.setup {
-- { command = "flake8", filetypes = { "python" } },
-- {
-- -- each linter accepts a list of options identical to https://github.com/jose-elias-alvarez/null-ls.nvim/blob/main/doc/BUILTINS.md#Configuration
-- command = "shellcheck",
-- ---@usage arguments to pass to the formatter
-- -- these cannot contain whitespaces, options such as `--line-width 80` become either `{'--line-width', '80'}` or `{'--line-width=80'}`
-- extra_args = { "--severity", "warning" },
-- },
-- {
-- command = "codespell",
-- ---@usage specify which filetypes to enable. By default a providers will attach to all the filetypes it supports.
-- filetypes = { "javascript", "python" },
-- },
-- }
-- Additional Plugins
-- lvim.plugins = {
-- {"folke/tokyonight.nvim"},
-- {
-- "folke/trouble.nvim",
-- cmd = "TroubleToggle",
-- },
-- }
-- Autocommands (https://neovim.io/doc/user/autocmd.html)
-- vim.api.nvim_create_autocmd("BufEnter", {
-- pattern = { "*.json", "*.jsonc" },
-- -- enable wrap mode for json files only
-- command = "setlocal wrap",
-- })
-- vim.api.nvim_create_autocmd("FileType", {
-- pattern = "zsh",
-- callback = function()
-- -- let treesitter use bash highlight for zsh files as well
-- require("nvim-treesitter.highlight").attach(0, "bash")
-- end,
-- })

View File

@ -0,0 +1,87 @@
#!/usr/bin/env bash
set -eu pipefall
declare -r LV_INSTALL_PREFIX="${INSTALL_PREFIX:-"$HOME/.local"}"
declare -r RELEASE_VER="${RELEASE_VER:-latest}" # can be set to nightly
declare ARCHIVE_NAME
declare RELEASE_NAME
declare OS
OS="$(uname -s)"
if [ "$OS" == "Linux" ]; then
ARCHIVE_NAME="nvim-linux64"
RELEASE_NAME="nvim-linux64"
elif [ "$OS" == "Darwin" ]; then
ARCHIVE_NAME="nvim-macos"
# for some reason the archive has a different name
RELEASE_NAME="nvim-osx64"
else
echo "$OS platform is not supported currently"
exit 1
fi
if [[ "${RELEASE_VER}" == "latest" ]]; then
declare -r RELEASE_URL="https://github.com/neovim/neovim/releases/${RELEASE_VER}/download/${ARCHIVE_NAME}.tar.gz"
else
declare -r RELEASE_URL="https://github.com/neovim/neovim/releases/download/${RELEASE_VER}/${ARCHIVE_NAME}.tar.gz"
fi
declare -r CHECKSUM_URL="$RELEASE_URL.sha256sum"
DOWNLOAD_DIR="$(mktemp -d)"
readonly DOWNLOAD_DIR
RELEASE_SHA="$(curl -Ls "$CHECKSUM_URL" | awk '{print $1}')"
readonly RELEASE_SHA
function main() {
if [ ! -d "$LV_INSTALL_PREFIX" ]; then
mkdir -p "$LV_INSTALL_PREFIX" || __invalid__prefix__handler
fi
download_neovim
verify_neovim
install_neovim
}
function download_neovim() {
echo "Downloading Neovim's binary from $RELEASE_VER release.."
if ! curl --progress-bar --fail -L "$RELEASE_URL" -o "$DOWNLOAD_DIR/$ARCHIVE_NAME.tar.gz"; then
echo "Download failed. Check that the release/filename are correct."
exit 1
fi
echo "Download complete!"
}
function verify_neovim() {
echo "Verifying the installation.."
DOWNLOADED_SHA="$(openssl dgst -sha256 "$DOWNLOAD_DIR/$ARCHIVE_NAME.tar.gz" | awk '{print $2}')"
if [ "$RELEASE_SHA" != "$DOWNLOADED_SHA" ]; then
echo "Error! checksum mismatch."
echo "Expected: $RELEASE_SHA but got: $DOWNLOADED_SHA"
exit 1
fi
echo "Verification complete!"
}
function install_neovim() {
echo "Installing Neovim.."
pushd "$DOWNLOAD_DIR"
tar -xzf "$DOWNLOAD_DIR/$ARCHIVE_NAME.tar.gz"
popd
# https://dev.to/ackshaey/macos-vs-linux-the-cp-command-will-trip-you-up-2p00
cp -r "$DOWNLOAD_DIR/$RELEASE_NAME/." "$LV_INSTALL_PREFIX"
echo "Installation complete!"
echo "Now you can run $LV_INSTALL_PREFIX/bin/nvim"
}
function __invalid__prefix__handler() {
echo "Error! Invalid value for LV_INSTALL_PREFIX: [$INSTALL_PREFIX]"
echo "Please verify that the folder exists and re-run the installer!"
exit 1
}
main "$@"

View File

@ -0,0 +1,290 @@
#Requires -Version 7.1
$ErrorActionPreference = "Stop" # exit when command fails
# set script variables
$LV_BRANCH = $LV_BRANCH ?? "rolling"
$LV_REMOTE = $LV_REMOTE ?? "lunarvim/lunarvim.git"
$INSTALL_PREFIX = $INSTALL_PREFIX ?? "$HOME\.local"
$env:XDG_DATA_HOME = $env:XDG_DATA_HOME ?? $env:APPDATA
$env:XDG_CONFIG_HOME = $env:XDG_CONFIG_HOME ?? $env:LOCALAPPDATA
$env:XDG_CACHE_HOME = $env:XDG_CACHE_HOME ?? $env:TEMP
$env:LUNARVIM_RUNTIME_DIR = $env:LUNARVIM_RUNTIME_DIR ?? "$env:XDG_DATA_HOME\lunarvim"
$env:LUNARVIM_CONFIG_DIR = $env:LUNARVIM_CONFIG_DIR ?? "$env:XDG_CONFIG_HOME\lvim"
$env:LUNARVIM_CACHE_DIR = $env:LUNARVIM_CACHE_DIR ?? "$env:XDG_CACHE_HOME\lvim"
$env:LUNARVIM_BASE_DIR = $env:LUNARVIM_BASE_DIR ?? "$env:LUNARVIM_RUNTIME_DIR\lvim"
$__lvim_dirs = (
$env:LUNARVIM_BASE_DIR,
$env:LUNARVIM_RUNTIME_DIR,
$env:LUNARVIM_CONFIG_DIR,
$env:LUNARVIM_CACHE_DIR
)
function __add_separator($div_width) {
"-" * $div_width
Write-Output ""
}
function msg($text){
Write-Output $text
__add_separator "80"
}
function main($cliargs) {
print_logo
verify_lvim_dirs
if ($cliargs.Contains("--overwrite")) {
Write-Output "!!Warning!! -> Removing all lunarvim related config because of the --overwrite flag"
$answer = Read-Host "Would you like to continue? [y]es or [n]o "
if ("$answer" -ne "y" -and "$answer" -ne "Y") {
exit 1
}
uninstall_lvim
}
if ($cliargs.Contains("--local") -or $cliargs.Contains("--testing")) {
msg "Using local LunarVim installation"
local_install
exit
}
msg "Checking dependencies.."
check_system_deps
$answer = Read-Host "Would you like to check lunarvim's NodeJS dependencies? [y]es or [n]o (default: no) "
if ("$answer" -eq "y" -or "$answer" -eq "Y") {
install_nodejs_deps
}
$answer = Read-Host "Would you like to check lunarvim's Python dependencies? [y]es or [n]o (default: no) "
if ("$answer" -eq "y" -or "$answer" -eq "Y") {
install_python_deps
}
if (Test-Path "$env:LUNARVIM_BASE_DIR\init.lua" ) {
msg "Updating LunarVim"
validate_lunarvim_files
}
else {
msg "Cloning Lunarvim"
clone_lvim
setup_lvim
}
}
function print_missing_dep_msg($dep) {
Write-Output "[ERROR]: Unable to find dependency [$dep]"
Write-Output "Please install it first and re-run the installer."
}
$winget_package_matrix=@{"git" = "Git.Git"; "nvim" = "Neovim.Neovim"; "make" = "GnuWin32.Make"; "node" = "OpenJS.NodeJS"; "pip" = "Python.Python.3"}
$scoop_package_matrix=@{"git" = "git"; "nvim" = "neovim-nightly"; "make" = "make"; "node" = "nodejs"; "pip" = "python3"}
function install_system_package($dep) {
if (Get-Command -Name "winget" -ErrorAction SilentlyContinue) {
Write-Output "Attempting to install dependency [$dep] with winget"
$install_cmd = "winget install --interactive $winget_package_matrix[$dep]"
}
elseif (Get-Command -Name "scoop" -ErrorAction SilentlyContinue) {
Write-Output "Attempting to install dependency [$dep] with scoop"
# TODO: check if it's fine to not run it with --global
$install_cmd = "scoop install $scoop_package_matrix[$dep]"
}
else {
print_missing_dep_msg "$dep"
exit 1
}
try {
Invoke-Command $install_cmd -ErrorAction Stop
}
catch {
print_missing_dep_msg "$dep"
exit 1
}
}
function check_system_dep($dep) {
try {
Get-Command -Name $dep -ErrorAction Stop | Out-Null
}
catch {
install_system_package "$dep"
}
}
function check_system_deps() {
check_system_dep "git"
check_system_dep "nvim"
check_system_dep "make"
}
function install_nodejs_deps() {
$dep = "node"
try {
check_system_dep "$dep"
Invoke-Command -ScriptBlock { npm install --global neovim tree-sitter-cli } -ErrorAction Break
}
catch {
print_missing_dep_msg "$dep"
}
}
function install_python_deps() {
$dep = "pip"
try {
check_system_dep "$dep"
Invoke-Command -ScriptBlock { python -m pip install --user pynvim } -ErrorAction Break
}
catch {
print_missing_dep_msg "$dep"
}
}
function backup_old_config() {
$src = "$env:LUNARVIM_CONFIG_DIR"
if (Test-Path $src) {
New-Item "$src.old" -ItemType Directory -Force | Out-Null
Copy-Item -Force -Recurse "$src\*" "$src.old\." | Out-Null
}
msg "Backup operation complete"
}
function local_install() {
verify_lvim_dirs
$repoDir = git rev-parse --show-toplevel
$gitLocalCloneCmd = git clone --progress "$repoDir" "$env:LUNARVIM_BASE_DIR"
Invoke-Command -ErrorAction Stop -ScriptBlock { $gitLocalCloneCmd; setup_lvim }
}
function clone_lvim() {
try {
$gitCloneCmd = git clone --progress --depth 1 --branch "$LV_BRANCH" `
"https://github.com/$LV_REMOTE" `
"$env:LUNARVIM_BASE_DIR"
Invoke-Command -ErrorAction Stop -ScriptBlock { $gitCloneCmd }
}
catch {
msg "Failed to clone repository. Installation failed."
exit 1
}
}
function setup_shim() {
if ((Test-Path "$INSTALL_PREFIX\bin") -eq $false) {
New-Item "$INSTALL_PREFIX\bin" -ItemType Directory | Out-Null
}
Copy-Item -Force "$env:LUNARVIM_BASE_DIR\utils\bin\lvim.ps1" "$INSTALL_PREFIX\bin\lvim.ps1"
}
function uninstall_lvim() {
foreach ($dir in $__lvim_dirs) {
if (Test-Path "$dir") {
Remove-Item -Force -Recurse "$dir"
}
}
}
function verify_lvim_dirs() {
foreach ($dir in $__lvim_dirs) {
if ((Test-Path "$dir") -eq $false) {
New-Item "$dir" -ItemType Directory | Out-Null
}
}
backup_old_config
}
function setup_lvim() {
msg "Installing LunarVim shim"
setup_shim
msg "Installing sample configuration"
if (Test-Path "$env:LUNARVIM_CONFIG_DIR\config.lua") {
Move-Item "$env:LUNARVIM_CONFIG_DIR\config.lua" "$env:LUNARVIM_CONFIG_DIR\config.lua.old"
}
New-Item -ItemType File -Path "$env:LUNARVIM_CONFIG_DIR\config.lua" | Out-Null
$exampleConfig = "$env:LUNARVIM_BASE_DIR\utils\installer\config_win.example.lua"
Copy-Item -Force "$exampleConfig" "$env:LUNARVIM_CONFIG_DIR\config.lua"
# FIXME: this has never worked
# Invoke-Expression "$INSTALL_PREFIX\bin\lvim.ps1 --headless -c 'autocmd User PackerComplete quitall' -c 'PackerSync'"
Write-Host "Make sure to run `:PackerSync` at first launch" -ForegroundColor Green
create_alias
msg "Thank you for installing LunarVim!!"
Write-Output "You can start it by running: $INSTALL_PREFIX\bin\lvim.ps1"
Write-Output "Do not forget to use a font with glyphs (icons) support [https://github.com/ryanoasis/nerd-fonts]"
}
function validate_lunarvim_files() {
Set-Alias lvim "$INSTALL_PREFIX\bin\lvim.ps1"
try {
$verify_version_cmd='if v:errmsg != "" | cquit | else | quit | endif'
Invoke-Command -ScriptBlock { lvim --headless -c 'LvimUpdate' -c "$verify_version_cmd" } -ErrorAction SilentlyContinue
}
catch {
Write-Output "Unable to guarantee data integrity while updating. Please run `:LvimUpdate` manually instead."
exit 1
}
Write-Output "Your LunarVim installation is now up to date!"
}
function create_alias {
try {
$answer = Read-Host $(`
"Would you like to create an alias inside your Powershell profile?`n" + `
"(This enables you to start lvim with the command 'lvim') [y]es or [n]o (default: no)" )
}
catch {
msg "Non-interactive mode detected. Skipping alias creation"
return
}
if ("$answer" -ne "y" -or "$answer" -ne "Y") {
return
}
$lvim_bin="$INSTALL_PREFIX\bin\lvim.ps1"
$lvim_alias = Get-Alias lvim -ErrorAction SilentlyContinue
if ($lvim_alias.Definition -eq $lvim_bin) {
Write-Output "Alias is already set and will not be reset."
return
}
Add-Content -Path $PROFILE -Value $("`r`nSet-Alias lvim $lvim_bin")
Write-Host 'To use the new alias in this window reload your profile with: `. $PROFILE`' -ForegroundColor Green
}
function print_logo(){
Write-Output "
88\ 88\
88 | \__|
88 |88\ 88\ 888888$\ 888888\ 888888\ 88\ 88\ 88\ 888888\8888\
88 |88 | 88 |88 __88\ \____88\ 88 __88\\88\ 88 |88 |88 _88 _88\
88 |88 | 88 |88 | 88 | 888888$ |88 | \__|\88\88 / 88 |88 / 88 / 88 |
88 |88 | 88 |88 | 88 |88 __88 |88 | \88$ / 88 |88 | 88 | 88 |
88 |\888888 |88 | 88 |\888888$ |88 | \$ / 88 |88 | 88 | 88 |
\__| \______/ \__| \__| \_______|\__| \_/ \__|\__| \__| \__|
"
}
main "$args"

View File

@ -0,0 +1,449 @@
#!/usr/bin/env bash
set -eo pipefail
#Set branch to master unless specified by the user
declare LV_BRANCH="${LV_BRANCH:-"master"}"
declare -r LV_REMOTE="${LV_REMOTE:-lunarvim/lunarvim.git}"
declare -r INSTALL_PREFIX="${INSTALL_PREFIX:-"$HOME/.local"}"
declare -r XDG_DATA_HOME="${XDG_DATA_HOME:-"$HOME/.local/share"}"
declare -r XDG_CACHE_HOME="${XDG_CACHE_HOME:-"$HOME/.cache"}"
declare -r XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-"$HOME/.config"}"
declare -r LUNARVIM_RUNTIME_DIR="${LUNARVIM_RUNTIME_DIR:-"$XDG_DATA_HOME/lunarvim"}"
declare -r LUNARVIM_CONFIG_DIR="${LUNARVIM_CONFIG_DIR:-"$XDG_CONFIG_HOME/lvim"}"
declare -r LUNARVIM_CACHE_DIR="${LUNARVIM_CACHE_DIR:-"$XDG_CACHE_HOME/lvim"}"
declare -r LUNARVIM_BASE_DIR="${LUNARVIM_BASE_DIR:-"$LUNARVIM_RUNTIME_DIR/lvim"}"
declare BASEDIR
BASEDIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
BASEDIR="$(dirname -- "$(dirname -- "$BASEDIR")")"
readonly BASEDIR
declare ARGS_LOCAL=0
declare ARGS_OVERWRITE=0
declare ARGS_INSTALL_DEPENDENCIES=1
declare INTERACTIVE_MODE=1
declare -a __lvim_dirs=(
"$LUNARVIM_CONFIG_DIR"
"$LUNARVIM_RUNTIME_DIR"
"$LUNARVIM_CACHE_DIR"
)
declare -a __npm_deps=(
"neovim"
"tree-sitter-cli"
)
declare -a __pip_deps=(
"pynvim"
)
function usage() {
echo "Usage: install.sh [<options>]"
echo ""
echo "Options:"
echo " -h, --help Print this help message"
echo " -l, --local Install local copy of LunarVim"
echo " -y, --yes Disable confirmation prompts (answer yes to all questions)"
echo " --overwrite Overwrite previous LunarVim configuration (a backup is always performed first)"
echo " --[no]-install-dependencies Whether to automatically install external dependencies (will prompt by default)"
}
function parse_arguments() {
while [ "$#" -gt 0 ]; do
case "$1" in
-l | --local)
ARGS_LOCAL=1
;;
--overwrite)
ARGS_OVERWRITE=1
;;
-y | --yes)
INTERACTIVE_MODE=0
;;
--install-dependencies)
ARGS_INSTALL_DEPENDENCIES=1
;;
--no-install-dependencies)
ARGS_INSTALL_DEPENDENCIES=0
;;
-h | --help)
usage
exit 0
;;
esac
shift
done
}
function msg() {
local text="$1"
local div_width="80"
printf "%${div_width}s\n" ' ' | tr ' ' -
printf "%s\n" "$text"
}
function confirm() {
local question="$1"
while true; do
msg "$question"
read -p "[y]es or [n]o (default: no) : " -r answer
case "$answer" in
y | Y | yes | YES | Yes)
return 0
;;
n | N | no | NO | No | *[[:blank:]]* | "")
return 1
;;
*)
msg "Please answer [y]es or [n]o."
;;
esac
done
}
function main() {
parse_arguments "$@"
print_logo
msg "Detecting platform for managing any additional neovim dependencies"
detect_platform
check_system_deps
if [ "$ARGS_INSTALL_DEPENDENCIES" -eq 1 ]; then
if [ "$INTERACTIVE_MODE" -eq 1 ]; then
if confirm "Would you like to install LunarVim's NodeJS dependencies?"; then
install_nodejs_deps
fi
if confirm "Would you like to install LunarVim's Python dependencies?"; then
install_python_deps
fi
if confirm "Would you like to install LunarVim's Rust dependencies?"; then
install_rust_deps
fi
else
install_nodejs_deps
install_python_deps
install_rust_deps
fi
fi
backup_old_config
verify_lvim_dirs
if [ "$ARGS_LOCAL" -eq 1 ]; then
link_local_lvim
elif [ -d "$LUNARVIM_BASE_DIR" ]; then
validate_lunarvim_files
else
clone_lvim
fi
setup_lvim
msg "Thank you for installing LunarVim!!"
echo "You can start it by running: $INSTALL_PREFIX/bin/lvim"
echo "Do not forget to use a font with glyphs (icons) support [https://github.com/ryanoasis/nerd-fonts]"
}
function detect_platform() {
OS="$(uname -s)"
case "$OS" in
Linux)
if [ -f "/etc/arch-release" ] || [ -f "/etc/artix-release" ]; then
RECOMMEND_INSTALL="sudo pacman -S"
elif [ -f "/etc/fedora-release" ] || [ -f "/etc/redhat-release" ]; then
RECOMMEND_INSTALL="sudo dnf install -y"
elif [ -f "/etc/gentoo-release" ]; then
RECOMMEND_INSTALL="emerge -tv"
else # assume debian based
RECOMMEND_INSTALL="sudo apt install -y"
fi
;;
FreeBSD)
RECOMMEND_INSTALL="sudo pkg install -y"
;;
NetBSD)
RECOMMEND_INSTALL="sudo pkgin install"
;;
OpenBSD)
RECOMMEND_INSTALL="doas pkg_add"
;;
Darwin)
RECOMMEND_INSTALL="brew install"
;;
*)
echo "OS $OS is not currently supported."
exit 1
;;
esac
}
function print_missing_dep_msg() {
if [ "$#" -eq 1 ]; then
echo "[ERROR]: Unable to find dependency [$1]"
echo "Please install it first and re-run the installer. Try: $RECOMMEND_INSTALL $1"
else
local cmds
cmds=$(for i in "$@"; do echo "$RECOMMEND_INSTALL $i"; done)
printf "[ERROR]: Unable to find dependencies [%s]" "$@"
printf "Please install any one of the dependencies and re-run the installer. Try: \n%s\n" "$cmds"
fi
}
function check_neovim_min_version() {
local verify_version_cmd='if !has("nvim-0.7") | cquit | else | quit | endif'
# exit with an error if min_version not found
if ! nvim --headless -u NONE -c "$verify_version_cmd"; then
echo "[ERROR]: LunarVim requires at least Neovim v0.7 or higher"
exit 1
fi
}
function verify_core_plugins() {
msg "Verifying core plugins"
if ! bash "$LUNARVIM_BASE_DIR/utils/ci/verify_plugins.sh"; then
echo "[ERROR]: Unable to verify plugins, makde sure to manually run ':PackerSync' when starting lvim for the first time."
exit 1
fi
echo "Verification complete!"
}
function validate_lunarvim_files() {
local verify_version_cmd='if v:errmsg != "" | cquit | else | quit | endif'
if ! "$INSTALL_PREFIX/bin/lvim" --headless -c 'LvimUpdate' -c "$verify_version_cmd" &>/dev/null; then
msg "Removing old installation files"
rm -rf "$LUNARVIM_BASE_DIR"
clone_lvim
fi
}
function check_system_deps() {
if ! command -v git &>/dev/null; then
print_missing_dep_msg "git"
exit 1
fi
if ! command -v nvim &>/dev/null; then
print_missing_dep_msg "neovim"
exit 1
fi
check_neovim_min_version
}
function __install_nodejs_deps_pnpm() {
echo "Installing node modules with pnpm.."
pnpm install -g "${__npm_deps[@]}"
echo "All NodeJS dependencies are successfully installed"
}
function __install_nodejs_deps_npm() {
echo "Installing node modules with npm.."
for dep in "${__npm_deps[@]}"; do
if ! npm ls -g "$dep" &>/dev/null; then
printf "installing %s .." "$dep"
npm install -g "$dep"
fi
done
echo "All NodeJS dependencies are successfully installed"
}
function __install_nodejs_deps_yarn() {
echo "Installing node modules with yarn.."
yarn global add "${__npm_deps[@]}"
echo "All NodeJS dependencies are successfully installed"
}
function __validate_node_installation() {
local pkg_manager="$1"
local manager_home
if ! command -v "$pkg_manager" &>/dev/null; then
return 1
fi
if [ "$pkg_manager" == "npm" ]; then
manager_home="$(npm config get prefix 2>/dev/null)"
elif [ "$pkg_manager" == "pnpm" ]; then
manager_home="$(pnpm config get prefix 2>/dev/null)"
else
manager_home="$(yarn global bin 2>/dev/null)"
fi
if [ ! -d "$manager_home" ] || [ ! -w "$manager_home" ]; then
echo "[ERROR] Unable to install using [$pkg_manager] without administrative privileges."
return 1
fi
return 0
}
function install_nodejs_deps() {
local -a pkg_managers=("pnpm" "yarn" "npm")
for pkg_manager in "${pkg_managers[@]}"; do
if __validate_node_installation "$pkg_manager"; then
eval "__install_nodejs_deps_$pkg_manager"
return
fi
done
print_missing_dep_msg "${pkg_managers[@]}"
exit 1
}
function install_python_deps() {
echo "Verifying that pip is available.."
if ! python3 -m ensurepip &>/dev/null; then
if ! python3 -m pip --version &>/dev/null; then
print_missing_dep_msg "pip"
exit 1
fi
fi
echo "Installing with pip.."
for dep in "${__pip_deps[@]}"; do
python3 -m pip install --user "$dep"
done
echo "All Python dependencies are successfully installed"
}
function __attempt_to_install_with_cargo() {
if command -v cargo &>/dev/null; then
echo "Installing missing Rust dependency with cargo"
cargo install "$1"
else
echo "[WARN]: Unable to find cargo. Make sure to install it to avoid any problems"
exit 1
fi
}
# we try to install the missing one with cargo even though it's unlikely to be found
function install_rust_deps() {
local -a deps=("fd::fd-find" "rg::ripgrep")
for dep in "${deps[@]}"; do
if ! command -v "${dep%%::*}" &>/dev/null; then
__attempt_to_install_with_cargo "${dep##*::}"
fi
done
echo "All Rust dependencies are successfully installed"
}
function verify_lvim_dirs() {
if [ "$ARGS_OVERWRITE" -eq 1 ]; then
for dir in "${__lvim_dirs[@]}"; do
[ -d "$dir" ] && rm -rf "$dir"
done
fi
for dir in "${__lvim_dirs[@]}"; do
mkdir -p "$dir"
done
}
function backup_old_config() {
local src="$LUNARVIM_CONFIG_DIR"
if [ ! -d "$src" ]; then
return
fi
mkdir -p "$src.old"
touch "$src/ignore"
msg "Backing up old $src to $src.old"
if command -v rsync &>/dev/null; then
rsync --archive -hh --stats --partial --copy-links --cvs-exclude "$src"/ "$src.old"
else
OS="$(uname -s)"
case "$OS" in
Linux | *BSD)
cp -r "$src/"* "$src.old/."
;;
Darwin)
cp -R "$src/"* "$src.old/."
;;
*)
echo "OS $OS is not currently supported."
;;
esac
fi
msg "Backup operation complete"
}
function clone_lvim() {
msg "Cloning LunarVim configuration"
if ! git clone --branch "$LV_BRANCH" \
--depth 1 "https://github.com/${LV_REMOTE}" "$LUNARVIM_BASE_DIR"; then
echo "Failed to clone repository. Installation failed."
exit 1
fi
}
function link_local_lvim() {
echo "Linking local LunarVim repo"
# Detect whether it's a symlink or a folder
if [ -d "$LUNARVIM_BASE_DIR" ]; then
echo "Removing old installation files"
rm -rf "$LUNARVIM_BASE_DIR"
fi
echo " - $BASEDIR -> $LUNARVIM_BASE_DIR"
ln -s -f "$BASEDIR" "$LUNARVIM_BASE_DIR"
}
function setup_shim() {
make -C "$LUNARVIM_BASE_DIR" install-bin
}
function remove_old_cache_files() {
local packer_cache="$LUNARVIM_CONFIG_DIR/plugin/packer_compiled.lua"
if [ -e "$packer_cache" ]; then
msg "Removing old packer cache file"
rm -f "$packer_cache"
fi
if [ -e "$LUNARVIM_CACHE_DIR/luacache" ] || [ -e "$LUNARVIM_CACHE_DIR/lvim_cache" ]; then
msg "Removing old startup cache file"
rm -f "$LUNARVIM_CACHE_DIR/{luacache,lvim_cache}"
fi
}
function setup_lvim() {
remove_old_cache_files
msg "Installing LunarVim shim"
setup_shim
cp "$LUNARVIM_BASE_DIR/utils/installer/config.example.lua" "$LUNARVIM_CONFIG_DIR/config.lua"
echo "Preparing Packer setup"
"$INSTALL_PREFIX/bin/lvim" --headless \
-c 'autocmd User PackerComplete quitall' \
-c 'PackerSync'
echo "Packer setup complete"
verify_core_plugins
}
function print_logo() {
cat <<'EOF'
88\ 88\
88 | \__|
88 |88\ 88\ 888888$\ 888888\ 888888\ 88\ 88\ 88\ 888888\8888\
88 |88 | 88 |88 __88\ \____88\ 88 __88\\88\ 88 |88 |88 _88 _88\
88 |88 | 88 |88 | 88 | 888888$ |88 | \__|\88\88 / 88 |88 / 88 / 88 |
88 |88 | 88 |88 | 88 |88 __88 |88 | \88$ / 88 |88 | 88 | 88 |
88 |\888888 |88 | 88 |\888888$ |88 | \$ / 88 |88 | 88 | 88 |
\__| \______/ \__| \__| \_______|\__| \_/ \__|\__| \__| \__|
EOF
}
main "$@"

View File

@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -eo pipefail
INSTALL_PREFIX="${INSTALL_PREFIX:-"$HOME/.local"}"
XDG_DATA_HOME="${XDG_DATA_HOME:-"$HOME/.local/share"}"
XDG_CACHE_HOME="${XDG_CACHE_HOME:-"$HOME/.cache"}"
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-"$HOME/.config"}"
LUNARVIM_RUNTIME_DIR="${LUNARVIM_RUNTIME_DIR:-"$XDG_DATA_HOME/lunarvim"}"
LUNARVIM_CONFIG_DIR="${LUNARVIM_CONFIG_DIR:-"$XDG_CONFIG_HOME/lvim"}"
LUNARVIM_CACHE_DIR="${LUNARVIM_CACHE_DIR:-"$XDG_CACHE_HOME/lvim"}"
LUNARVIM_BASE_DIR="${LUNARVIM_BASE_DIR:-"$LUNARVIM_RUNTIME_DIR/lvim"}"
function setup_shim() {
local src="$LUNARVIM_BASE_DIR/utils/bin/lvim.template"
local dst="$INSTALL_PREFIX/bin/lvim"
[ ! -d "$INSTALL_PREFIX/bin" ] && mkdir -p "$INSTALL_PREFIX/bin"
# remove outdated installation so that `cp` doesn't complain
rm -f "$dst"
cp "$src" "$dst"
sed -e s"#RUNTIME_DIR_VAR#\"${LUNARVIM_RUNTIME_DIR}\"#"g \
-e s"#CONFIG_DIR_VAR#\"${LUNARVIM_CONFIG_DIR}\"#"g \
-e s"#CACHE_DIR_VAR#\"${LUNARVIM_CACHE_DIR}\"#"g "$src" \
| tee "$dst" >/dev/null
chmod u+x "$dst"
}
setup_shim "$@"
echo "You can start LunarVim by running: $INSTALL_PREFIX/bin/lvim"

Some files were not shown because too many files have changed in this diff Show More