title | description | author | categories | created | version |
---|---|---|---|---|---|
FAQ |
Frequently asked questions about Nyoom |
shaunsingh |
docs |
2022-12-09 |
0.1.0 |
This is the section for questions on how Nyoom works, is it for you, how does it compare to other configurations, and how can you get started.
If you don't mind tinkering with lisps, and don't want to start entirely from scratch, then of course! However, if you prefer something that is truly yours, don't mind a little boilerplate here and there, or don't like fennel, checkout some other configurations!
- Unlike quite a few premade configurations, Nyoom allows for a high degree of extensibility and customizability, while remaining performant.
- Nyoom puts a focus on integration. This means that enabled modules will enable new features and optimizations in other modules (e.g. enabling
tools.tree-sitter
will enable tree-sitter based folding withnvim-ufo
) - Nyoom enhances rather than replaces Neovim's features and ideals.
At its core Nyoom is just plain fennel with a few niceties. Everything within core/
is quite standard. It provides a set of opinionated defaults along with optimizations to speed up startup and it provides a standard library to simplify your code.
Nyoom takes heavy advantage of fennel's compile-time macro functionality, which builds the core of Nyoom's module system and package management system. Nyoom's module system allows for clever interactions between sets of plugins defined into modules, a concept familiar to users of doom emacs. However, emacs-lisp isn't fennel and thats where Nyoom's magic starts
A list of modules is defined in modules.fnl
using the nyoom!
macro. The purpose of the nyoom!
macro is to take the list of modules, formatted similar to doom's plist, and turn it into something neovim can read. It does at compile-time by
- loading all of the enabled modules into a
registry
including
(inline require) all of the enabled modules intopackages.fnl
. This allows Nyoom's package management system to module dependencies, and allows for more advanced macros that can pre-compute code determined across multiple modules.compiling
all of the enabled modules. As we loaded the list of modules and several macros in ourinclude
pass, we can use this information to conditionally compile code using macros (nyoom-module-p!
), compile warnings (nyoom-ensure-module!
) and more.
To aid with the module system, Nyoom also wraps packer.nvim
with a few macros with similar syntax to use-package
. This wrapper adds additional keys (such as :nyoom-module
) that aid in the definition and creation of modules.
All of these and a bit more comes together to create the nyoom cli
. Once again utilizing that compile time magic, nyoom sync
can precompute your enabled plugins, modules, and integrations, and compile that into a single file with lazy loaded definitions
Why go so far to ensure Nyoom starts up quickly? After all, some of you keep the same nvim
instance open for weeks at a time.
Startuptime gets a disproportional amount of attention because it’s the first thing Nyoom’s users notice
In most configurations, It’s left to the user to know or care about optimal lazy loads, autocommads, and to implement them, but that’s a lot to ask when the problem domain is so vast, esoteric, and a moving target (with a high cost-to-benefit). Who has the time to inspect, much less fix, all their packages? And maintain that effort across Emacs or package updates? It’s easier to just install all your plugins and leave it be, which is what people do.
However, when a user first opens up nyoom, the startuptime is the first thing they're greated with. Startuptime adds up quickly. With one or two plugins sure, it only adds a few milliseconds here or there, but add support for debugging, profiling, language servers, and several languages and neovim can easily take multiple seconds to get going.
Users shouldn't be scared of enabling modules. I shouldn't be scared of affecting users by adding more. By ensuring that the core modules and base of Nyoom are loaded and compiled optimally, everything is left in the hands of the user. It’s left to the user to know or care about lazy loading, auto commands, autoloading, and how to implement them in their own configurations, and by all means use the use-package!
macro to configure your plugins as well, even if its a bit slower than doing it yourself.
By making it easy to properly manage packages, I hope users will have more incentive to keep neatly loaded neovim configurations
Rather than startuptime, runtime performance is a bigger priority, though the two rarely stray far from each other. Each release of Nyoom is heavily profiled to ensure all modules and core code aren't bogging down your workflow
Fennel is a programming language that brings together the speed, simplicity, and reach of Lua with the flexibility of a lisp syntax and macro system. Macros are how lisps accomplish metaprogramming. You’ll see a lot of people treat lisp macros with a kind of mystical reverence. While several other languages have macro systems, the power of macros in lisps stem from allowance of lisps to you to write programs using the same notation you use for data structures. Remember: code is data, and we just need to manipulate data.
While people largely exaggerate the usefulness of macros, there are a few places where macros shine, and configurations are one of them. Utilizing macros, we can essentially create our own syntax at compile-time. For example, lets take a look at the set!
macro I've used. set!
is used for vim.opt
options. For example, (set! mouse :a)
expands to vim.opt["mouse"]="a"
. If a string or number isn't passed to set!
, it will assume true. e.g. (set! list)
will expand to vim.opt["list"]=true
. Similarly if the option starts with no, it will assume false e.g. (set! noru)
will expand to vim.opt["ru"]=false
. Of course, this is a very simple example and macros can get very, very complex but you get the idea.
Fennel also fixes quite a few of the quirks of lua:
- the paren-first syntax is more regular
- being a lisp, lua's issues of statements and issues of operator precedence are solved
- fennel makes it super difficult to use lua globals on accident.
- seperates syntax sequential and key/value tables, while lua uses curly braces for both. Plus a lot of nice syntax for dealing with variables and data in general
With the macros provided, you can configure neovim just as easily, or dare I say easier than you can with Lua or vimscript, while retaining the performance benefits of LuaJIT.
For most people, chances are you haven't even heard of fennel before. So where should you start?
- Read through the Documentation
- Install fennel yourself! (Skip the part where it goes over adding fennel support to your editor, that's what this project is for :p). A copy of fennel is provided within neovim through
hotpot.nvim
- Learn lua first. I recommend reading through the Neovim lua guide as well.
- Learn fennel
- Go over the Style guide.
- Learn macros.
If you have trouble configuring neovim to your needs, check out Antifennel to see how lua code compiles back to fennel! However, the generated code isn't always the cleanest, so its recommend you use it as a last resort. If you need any help, feel free to join the Nyoom discord server!
Feel free to open the Scratch buffer (:Scratch
) to get a nice working eviornment to start with
While fiddling with the config, you can check if the things are not broken yet:
- evaluate form you just written (
<localleader>er
, by default<space>mer
) - evaluate buffer (
<localleader>eb
, by default<space>meb
) - live-compile (reflect) your changes with
<leader>hr
- In reflect mode, live-evaluate your code with
<leader>hx
Take a look at :h conjure
for more
For fun, no major reason really. Also somewhat goes well with the mantras Nyoom lives by.
This is the section for learning the basics of how to get the most out of Nyoom.
As you've probably noticed, all the main Packer commands such as :PackerSync
don't work in Nyoom. Instead, its recommend to use the nyoom
cli command, a small shell script that lives in bin/
.
Nyoom ships with a lockfile containing pinned commits for all of the plugins it uses. You can run nyoom sync
to syncronize your plugins with the provided lockfile.lua
, and to install/remove plugins depending on what modules you have enabled.
If you'd like to live life on he edge, you can run nyoom lock
to update the lockfile, then run nyoom sync
to update your plugins to their latest respective commits.
nyoom sync
will also spit out the commit of Nyoom you're using. As Nyoom uses git under the hood, any and all git commands will works just as well. You can use nyoom upgrade
to git pull
to the latest version of Nyoom.
Enabling a language module (e.g. lang.rust
) will do the following:
- Install its tree-sitter parser with
tools.tree-sitter
- Install its language server with
tools.lsp
- Set it up for debugging with
tools.debugger
if available - Register its tooling under mason to auto-install with
tools.mason
- Set up a minor GUI with
ui.hydra
if available - Set up recomended formatters and linters if available
- Install any language-specific plugins (e.g
rust-tools
andcrates.nvim
).
If you find support for a language lacking, or want to add a plugin/integration to a module, feel free to pull-request or open an issue about it!
You can use the nyoom upgrade
command if you'd like a fancy prompt with a nice diff. As Nyoom uses git under the hood, you can also simply git pull
.
Refer to the getting_started
guide for instructions on how to add packages.
Refer to the getting_started
guide for instructions on how to add configuration. You can also take a look at examples.md
to check out examples of configurations others have done
Refer to contributing.md
for information on how to contribute