Giter Site home page Giter Site logo

nfnl's Introduction

nfnl

Enhance your Neovim experience through Fennel with zero overhead. Write Fennel, run Lua, nfnl will not load unless you're actively modifying your Neovim configuration or plugin source code (nfnl-plugin-example).

  • Only loads when working in directories containing a .nfnl.fnl configuration file.
  • Automatically compiles *.fnl files to *.lua when you save your changes.
  • Can be used for your Neovim configuration or plugins with no special configuration, it just works for both.
  • Includes a Clojure inspired standard library (based on Aniseed).
  • Compiles your Fennel code and then steps out of the way leaving you with plain Lua that doesn't require nfnl to load in the future.
  • Displays compilation errors as you save your Fennel code to keep the feedback loop as tight as possible.

Usage

First, you must create the configuration file at the root of your project or configuration, this can be blank if you wish to rely on the defaults for now.

echo "{}" > .nfnl.fnl

The first time you open a Fennel file under this directory you'll be prompted to trust this configuration file since it's Fennel code that's executed on your behalf. You can put any Fennel code you want in this file, just be sure to return a table of configuration at the end.

(print "Hello, World! From my nfnl configuration!")

{:fennel-path "..."}

By default, writing to any Fennel file with Neovim under the directory containing .nfnl.fnl will automatically compile it to Lua. If there are compilations errors they'll be displayed using vim.notify and the Lua will not be updated.

nfnl will refuse to overwrite any existing Lua at the destination if nfnl was not the one to compile it, this protects you from accidentally overwriting existing Lua with compiled output. To bypass the warning you must delete or move the Lua file residing at the destination yourself.

Now you may use the compiled Lua just like you would any other Lua files with Neovim. There's nothing special about it, please refer to the abundant documentation on the topic of Neovim configuration and plugins in Lua.

You must commit the Lua into your configuration or plugin so that it can be loaded by native Neovim Lua systems, with absolutely no knowledge of the Fennel it originated from.

Configuration

nfnl is configured on a per directory basis using .nfnl.fnl files which also signify that the plugin should operate on the files within this directory. Without the file the plugin is inert, meaning even if you don't lazy load it you won't see any performance impact at startup time.

Any configuration you don't provide (an empty file or just {} is absolutely fine!) will default to these values that should work fine for most people.

{;; Enables verbose notifications from nfnl, including notifications about
 ;; when it starts up and when it compiles successfully. Useful for debugging 
 ;; the plugin itself and checking that it's running when you expect it to.
 :verbose false

 ;; Passed to fennel.compileString when your code is compiled.
 ;; See https://fennel-lang.org/api for more information.
 :compiler-options {;; Disables ansi escape sequences in compiler output.
                    :error-pinpoint false}

 ;; Warning! In reality these paths are absolute and set to the root directory
 ;; of your project (where your .nfnl.fnl file is). This means even if you
 ;; open a .fnl file from outside your project's cwd the compiler will still
 ;; find your macro files. If you use relative paths like I'm demonstrating here
 ;; then macros will only work if your cwd is in the project you're working on.

 ;; They also use OS specific path separators, what you see below is just an example really.
 ;; I'm not including nfnl's directory from your runtimepath, but it would be there by default.
 ;; See :rtp-patterns below for more information on including other plugins in your path.

 ;; String to set the compiler's fennel.path to before compilation.
 :fennel-path "./?.fnl;./?/init.fnl;./fnl/?.fnl;./fnl/?/init.fnl"

 ;; String to set the compiler's fennel.macro-path to before compilation.
 :fennel-macro-path "./?.fnl;./?/init-macros.fnl;./?/init.fnl;./fnl/?.fnl;./fnl/?/init-macros.fnl;./fnl/?/init.fnl"

 ;; A list of glob patterns (autocmd pattern syntax) of files that
 ;; should be compiled. This is used as configuration for the BufWritePost
 ;; autocmd, so it'll only apply to buffers you're interested in.
 ;; Will use backslashes on Windows.
 ;; Defaults to compiling all .fnl files, you may want to limit it to your fnl/ directory.
 :source-file-patterns ["*.fnl" "**/*.fnl"]

 ;; A function that is given the absolute path of a Fennel file and should return
 ;; the equivalent Lua path, by default this will translate `fnl/foo/bar.fnl` to `lua/foo/bar.lua`.
 ;; See the "Writing Lua elsewhere" tip below for an example function that writes to a sub directory.
 :fnl-path->lua-path (fn [fnl-path] ...)}

As an example, if you only want to compile .fnl files under the fnl/ directory of your Neovim configuration (so nothing in the root directory) you could use this .nfnl.fnl file instead.

{:source-file-patterns ["fnl/**/*.fnl"]}

And since this is a Fennel file that's executed within Neovim you can actually load nfnl's modules to access things like the default config values.

(local core (require :nfnl.core))
(local config (require :nfnl.config))
(local default (config.default))

{:source-file-patterns (core.concat default.source-file-patterns ["custom-dir/*.fnl"])}

config.default accepts a table of arguments (docs) to change how it builds the default configuration. You can call (config.default {...}) on the last line of your .nfnl.fnl file in order to return a modified default configuration table. You also then have the option to call config.default, modify that table with extra values and then return that.

By providing a different rtp-patterns value (defaults to ["/nfnl$"]) we can include other plugins you have installed in your search paths when requiring Lua modules or macros.

;; Configuration that includes nfnl _and_ your-cool-plugin in the search paths.
(local config (require :nfnl.config))
(config.default {:rtp-patterns ["/nfnl$" "/your-cool-plugin$"]})

;; Configuration that includes ALL of your installed plugins in your search paths.
;; This might slow down compilation on some machines, so it's not the default.
(local config (require :nfnl.config))
(config.default {:rtp-patterns [".*"]})

;; Searching all of your plugins _and_ merging in some other custom configuration.
(local core (require :nfnl.core))
(local config (require :nfnl.config))
(core.merge
  (config.default {:rtp-patterns [".*"]})
  {:source-file-patterns ["fnl/**/*.fnl"]})

Installation

  • Lazy: { "Olical/nfnl", ft = "fennel" }
  • Plug: Plug 'Olical/nfnl'
  • Packer: use "Olical/nfnl"

Lazy will lazily load the plugin when you enter a Fennel file for the first time. There is no need to call require("nfnl").setup() right now, it's currently a noop but it may be used eventually. Some plugin managers support this function and will call it automatically.

  • Requires Neovim > v0.9.0.
  • Add the dependency to your plugin manager.
  • Add lazy loading rules on the Fennel filetype if you want.

Standard library

nfnl ships with a standard library used mostly for it's internal implementation, but it can also be used by your own Neovim configuration or plugins. This is based on Aniseed's standard library but without the module system that prevented you from using it in standard, non-Neovim, Fennel projects.

Full API documentation powered by fenneldoc can be found in the api directory.

The documentation is regenerated by executing ./script/render-api-documentation. One limitation of using this tool is that all top level values in a module should really be functions, if we do work inside (local) for example we'll end up incurring side effects at documentation rendering time that we may not want.

Macros

Fennel allows you to write inline macros with the (macro ...) form but they're restricted to only being used in that one file. If you wish to have a macro module shared by the rest of your codebase you need to mark that file as a macro module by placing ;; [nfnl-macro] somewhere within the source code. The exact amount of ; and whitespace doesn't matter, you just need a comment with [nfnl-macro] inside of it.

This marker does two things:

  • Instructs the compiler not to attempt to compile this file since it would fail. You can't compile macro modules to Lua, they use features that can only be referred to at compile time and simply do not translate to Lua.
  • Ensures that whenever the file is written to all other non-macro modules get recompiled instead. Ensuring any inter-dependencies between your Fennel and your macro modules stays in sync and you never end up having to find old Lua that was compiled with old versions of your macros.

For example, here's a simplified macro file from nfnl itself at fnl/nfnl/macros.fnl.

;; [nfnl-macro]

;; .nfnl.fnl config so you don't need to prefix globals like _G.vim.*
;; {:compiler-options {:compilerEnv _G}}

(fn time [...]
  `(let [start# (vim.loop.hrtime)
         result# (do ,...)
         end# (vim.loop.hrtime)]
     (print (.. "Elapsed time: " (/ (- end# start#) 1000000) " msecs"))
     result#))

{: time}

When writing to this file, no matching .lua will be generated but all other source files in the project will be re-compiled against the new version of the macro module.

This system does not currently use static analysis to work out which files depend on each other, instead we opt for the safe approach of recompiling everything. This should still be fast enough for everyone's needs and avoids the horrible subtle bugs that would come with trying to be clever with it.

Why can't I refer to the vim global in my macros?

By default, the Fennel compiler employs a compiler sandbox in your macro modules. This means you can't refer to any free global variables such a vim. You have to configure the Fennel compiler API with the {:compiler-options {...}} section of your .nfnl.fnl file.

You can either prefix each of these globals with _G like _G.vim.g.some_var or you can turn off the relevant sandboxing rules. One approach is to set the compiler environment to _G instead of Fennel's sanitised environment. You can do that with the following .nfnl.fnl file.

{:compiler-options {:compilerEnv _G}}

OS support

Currently only developed for and tested on Arch Linux, but this works fine on MacOS. You can see another example of creating a plugin and done on MacOS at this blog post. I tried my best to support Windows without actually testing it. So I've ensured it uses the right path separators in all the places I can find.

If you try this out and it works on MacOS or Windows, please let me know so I can add it here. If you run into issues, please report them with as much detail as possible.

Tips

Ignoring compiled Lua

Create a .ignore file so your .lua files don't show up in Telescope when paired with ripgrep among many other tools that respect this file.

lua/**/*.lua

You can also add these known directories and files to things like your Neo-tree configuration in order to completely hide them.

GitHub language statistics

Create a .gitattributes file to teach GitHub which of your files are generated or vendored. This ensures your "languages" section on your repository page reflects reality.

lua/**/*.lua linguist-generated
lua/nfnl/fennel.lua linguist-vendored
script/fennel.lua linguist-vendored

LSP

I highly recommend looking into getting a good LSP setup for fennel-language-server. I use AstroNvim since it bundles LSP configurations and Mason, a way to install dependencies, in one pre-configured system. My configuration is here in my dotfiles.

With the Fennel LSP running I get a little autocompletion alongside really useful unused or undeclared symbol linting. It'll also pick up things like unbalanced parenthesis before I try to compile the file.

The same can be done for Lua so you can also check the linting and static analysis of the compiled output in order to help debug some runtime issues.

Directory local Neovim configuration in Fennel

I wrote nvim-local-fennel to solve this problem years ago but I now recommend combining nfnl with the built in exrc option. Simply :set exrc (see :help exrc for more information), create a .nfnl.fnl file and then edit .nvim.fnl.

This will write Lua to .nvim.lua which will be executed whenever your Neovim enters this directory tree. Even if you uninstall nfnl the .lua file will continue to work. Colleagues who also use Neovim but don't have nfnl installed can also use the .nvim.lua file provided they have exrc enabled (even if they can't edit the Fennel to compile new versions of the Lua).

This solution achieves the same goal as nvim-local-fennel with far less code and built in options all Neovim users can lean on.

Embedding nfnl inside your plugin

If you want to ship a plugin (nfnl-plugin-example) that depends on nfnl modules you'll need to embed it inside your project. You can either cp -r lua/nfnl into your-project/lua/nfnl if you don't mind your plugin's copy of nfnl colliding with other plugins or you can use script/embed-library to copy the files into a lower level directory and modify them to isolate them for your plugin specifically.

cp -r nfnl/lua/nfnl my-plugin/lua/nfnl

Now your plugin can always use (require :nfnl.core) and know it'll be around, but you might run into issues where another plugin author has done the same and is using an older version of nfnl that lacks some feature you require. Lua has a global module namespace, so collisions are quite easy to accidentally cause. You may use my embedding script (or your own) to avoid this though:

# There are more paths and options available, see the script source for more information.
# This will write to $PROJECT/lua/$PROJECT/nfnl.
SRC_DIR=nfnl/lua/nfnl PROJECT=my-plugin ./nfnl/script/embed-library

This will copy nfnl's Lua code into your project's directory under a namespaced directory unique to your project. It will then perform a find and replace on the Lua code to scope the nfnl source to your plugin, avoiding conflicts with any other copy of nfnl.

This script depends upon fd and sd, so make sure you install those first! Alternatively you could modify or write your own script that works for your OS with your available tools.

Writing Lua elsewhere

If you're not happy with the defaults of Lua being written beside your Fennel and still disagree with my justifications for it then you may want to override the :fnl-path->lua-path function to perform in a way you like. Since you get to define a function, how this behaves is entirely up to you. Here's how you could write to a sub-directory rather than just lua, just include this in your .nfnl.fnl configuration file for your project.

(local config (require :nfnl.config))
(local default (config.default))

{:fnl-path->lua-path (fn [fnl-path]
                       (let [rel-fnl-path (vim.fn.fnamemodify fnl-path ":.")]
                         (default.fnl-path->lua-path (.. "some-other-dir/" rel-fnl-path))))}

Commands

User commands are defined inside your Fennel buffers when nfnl configuration is detected, they are just thin wrappers around the function found in nfnl.api which you can read about under the next header.

  • :NfnlFile [path]

    • path defaults to %

    Run the matching Lua file for this Fennel file from disk. Does not recompile the Lua, you must use nfnl to compile your Fennel to Lua first. Calls nfnl.api/dofile under the hood.

  • :NfnlCompileAllFiles [path]

    • path defaults to .

    Executes (nfnl.api/compile-all-files) which will, you guessed it, compile all of your files.

API

Although you can require any internal nfnl Lua module and call it's functions (full index of internal modules and functions) there is a specific module, nfnl.api (documentation), that is designed to be hooked up to your own functions, mappings and autocmds.

The functions within are designed to "do the right thing" with little to no configuration. You shouldn't need them in normal use, but they may come in useful when you need to fit nfnl into an interesting workflow or system.

As an example, here's how and why you'd use the compile-all-files function from another Fennel file to, you guessed it, compile all of your files.

(local nfnl (require :nfnl.api))

;; Takes an optional directory as an argument, defaults to (vim.fn.getcwd).
(nfnl.compile-all-files)

In the case where you're absolutely adamant that you need to .gitignore your compiled Lua output, this can be used after you git pull to ensure everything is compiled. However, I strongly advise committing your Lua for performance and stability.

This project was designed around the principal of compiling early and then never needing to compile again unless you make changes. I thought long and hard about the tradeoffs so you don't have to. These tools are here for when I'm wrong.

Development

If you have nfnl installed in Neovim you should be able to just modify Fennel files and have them get recompiled automatically for you. So nfnl is compiled with nfnl. This does however mean you can perform an Oopsie and break nfnl, rendering it useless to recompile itself with fixed code.

If you run into issues like this, you can execute script/bootstrap-dev to run a file watching Fennel compiler and script/bootstrap to compile everything with a one off command. Both of these lean on script/fennel.bb which is a smart Fennel compiler wrapper written in Babashka. This wrapper relies on the bundled Fennel compiler at script/fennel.lua, so it will ignore any Fennel version installed at the system level on the CLI.

So you'll need the following to use the full development suite:

  • A Lua runtime of some kind to execute script/fennel.lua.
  • Babashka to execute script/fennel.bb.
  • Entr if you want to use file watching with script/bootstrap-dev.

The bootstrap tools should only really ever be required during the initial development of this plugin or if something has gone catastrophically wrong and nfnl can no longer recompile itself. Normally having nfnl installed and editing the .fnl files should be enough.

Remember to rebuild the API documentation and run the tests when making changes. This workflow will be automated and streamlined eventually.

Testing

Tests are written under fnl/spec/nfnl/**/*_spec.fnl. They're compiled into the lua/ directory by nfnl itself and executed by Plenary, you must have this plugin installed in order to run the test suite within Neovim.

The project local .nfnl.fnl defines the <localleader>pt mapping which allows you to execute the test suite from within Neovim using Plenary.

To run the tests outside of your configuration you can run ./script/setup-test-deps (installs dependencies into this local directory) and then ./script/test to execute the tests in a headless local Neovim configuration.

Unlicensed

Find the full Unlicense in the UNLICENSE file, but here's a snippet.

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.

lua/nfnl/fennel.lua and script/fennel.lua are excluded from this licensing, they're downloaded from the Fennel website and retains any license used by the original author. We vendor it within this tool to simplify the user experience.

script/fenneldoc.lua is also excluded since it's compiled from the fenneldoc repository.

nfnl's People

Contributors

datwaft avatar kamholtz avatar olical avatar russtoku avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nfnl's Issues

Add a way to write compiled Lua to a completely different directory

This will involve a new option in .nfnl.fnl which will probably be a complete override of the function that replaces .fnl and /fnl/ with .lua and /lua/. It'll allow the user to combine some other functions that do exactly what they want.

Or it'll just be a "prefix" path string for the output, not sure yet.

Direct Eval of Fennel Expressions

Heya! A couple months ago I converted my neovim config off of aniseed and to Nfnl and have for the most part been loving it. The approach seems to be a much nicer set of tradeoffs and makes debugging issues a little easier.

One part of aniseed I've been missing though is some way to evaluate or resource a given fennel file. I find myself somewhat frequently editing part of my config and wanting to quickly run some part of it either to update the configuration live and move on or test some of the changes.

I'm curious about what the recommend way to do that would be. I know that I could just open the lua file and evaluate that directly but that requires figuring out where the compiled lines landed which takes time and thinking. Maybe there could be a setting to store the source maps for the compilation and have some command which looks up the equivalent lua file or range in the compiled lua file and evaluates that transparently?

Maybe I'm thinking to hard and there is a simpler approach I'm overlooking. Any help would be appreciated!

Thanks for your continued work on making neovim a nicer place to write software. I've used your stuff for years now and really appreciate the attention you clearly put into it <3

Compile-on-save Does not Work on Nightly/0.10

Hello! I was trying this plugin out on nightly (inlay hints!) and automatic compiling is not working.

Minimal Config

local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'

if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    'git',
    'clone',
    '--filter=blob:none',
    '--single-branch',
    'https://github.com/folke/lazy.nvim.git',
    lazypath,
  })
end
vim.opt.runtimepath:prepend(lazypath)

require('lazy').setup({
  spec = {
    'Olical/nfnl',
    ft = 'fennel',
  },
  defaults = {
    lazy = true,
  },
})

I also tried using pack/*/start and pack/*/opt directories, and the results are the same.

I managed to track it down to lazy loading. If lazy loading as above (or with pack/*/opt) then the plugin works after the second fennel file is opened.

Best I can tell, two auto commands are created:

  • One for filetype fennel
  • The second for BufWritePost

On nightly, the first autocmd is always loaded. But the second is only loaded for every subsequent fennel file.

If I don't lazy load:

require('lazy').setup({
  spec = {
    'Olical/nfnl',
  },
})

Then everything works as advertised on nightly and 0.9.

I'm happy to help with tracking it down further, but not really sure where to start.

"Auto compile on save" not working after commit 596c1a2 on Windows.

compile.into-file called with these arguments:

root-dir: D:\dev_env\vimconf\nvim
ev.file: rc\dap.fnl
(fs.full-path ev.file): D:\dev_env\vimconf\nvim\fnl\rc\dap.fnl

My .nfnl.fnl:

{:source-file-patterns ["fnl/**/*.fnl" "fnl/*.fnl" "*.fnl"]
 :compiler-options {:compilerEnv _G}}

Is this commit means users should write source-file-patterns in Lua's regex now?

(core.some #(string.find path $) (cfg [:source-file-patterns]))

Compile error when trying to `import-macros`

Problem

When I write a macro file and try to import it I get an error Compile error: macros module not found.

Reproduction

nfnl version: 7ef3da2

A similar setup as #12:

mkdir /tmp/test
cd /tmp/test

touch {macro,.nfnl,file}.fnl
echo ";; [nfnl-macro]\n{:test (fn test [])}" > macro.fnl
echo "(import-macros {: test} :macros)\n(test)" > file.fnl

If I try and compile file.fnl I get:

Compile command
nvim file.fnl --headless -c "lua vim.notify = function(msg) local f = io.open('/dev/stdout', 'a'); f:write(msg .. '\n'); f:close() end" -c 'write' -c 'quit'
/private/tmp/test/file.fnl:1:0 Compile error: unknown:376:? Compile error: macros module not found.


�[7m(import-macros {: test} :macros)�[0m

"Auto comile on save" won't work if I switch window.

For example, I edit autocmd.fnl first, then I split a new window edit colors.fnl.

image

autocmd.fnl is buffer No.10, colors.fnl is buffer No.16.

Then let's check :autocmd BufWritePost:
image

So if I jump back to left window(autocmd.fnl), and :w, it won't auto compile.

Now if I do a :e in left window(autocmd.fnl), let's check :autocmd BufWritePost:
image

Now I jump to right window, colors.fnl won't auto compile.

Saving .fnl doesn't automatically compile it to lua

This works! So much easier to use than Aniseed but I discovered that saving a .fnl file doesn't compile it to .lua.

I have this set-up:

my-plugin (master)$ tree -a -I .git
.
├── .nfnl.fnl
├── fnl
│   └── my-plugin
│       └── main.fnl
├── lua
│   └── my-plugin
│       └── main.lua
└── plugin
    └── my-plugin.vim

With this in .nfnl.fnl:

{:source-file-patterns ["fnl/**/*.fnl"]}

After saving main.fnl, I noticed that it wasn't compiled.

my-plugin (master)$ ls -l */my-plugin/*
-rw-r--r--  1 russ  staff  282 Jul 11 18:26 fnl/my-plugin/main.fnl
-rw-r--r--  1 russ  staff  437 Jul 11 18:04 lua/my-plugin/main.lua

Did I miss something?

cannot compile macros that contain vim namespace

Some of my macros contain various vim namespace functions used to simplify the macro signature:

; this is *not* a macro, it used in macros
(fn scope [opt]
  "Get the scope of an option"
  (let [opt# (tostring opt)]
      (. (vim.api.nvim_get_option_info2 opt# {}) :scope)))

these do not compile with nfnl, saying that vim is an unknown identifier.

.nfnl.fnl file

{:source-file-patterns ["test/fnl/**/*.fnl"
                        "fnl/**/*.fnl"]}

the macros are imported with import-macros for the file i am attempting to compile

Doesn't compile when editing from another dir

cd test
nvim fnl/t.fnl # no fnl/t.lua
cd fnl/ && nvim t.fnl # -> t.lua

test/.nfnl.fnl:

{
  :source-file-patterns ["*.fnl" "**/*.fnl"]
}

This is particularly bothersome given that most people are navigating to files using fzf or tree view which don't change the cwd.

Am I missing something simple?

`import-macro` uses nvim cwd and not project cwd.

simple test:

mkdir test
touch test/{macro,.nfnl,file}.fnl

test/macro.fnl

;; [nfnl-macro]
{:test (fn test [])}

test/file.fnl

(import-macros {: test} :macros)
(test)
  • from home dir, i get a compile error. cd ~; nvim test/file.fnl -c ':w'
  • from project dir, i can compile: cd test; nvim file.fnl -c ':w'

I would have perhaps expected something like:

  1. attempt to compile the file test/file.fnl
  2. walk up the dir to look for .nfnl.fnl
  3. use that dir (that .nfnl.fnl is in) to act as the dir to resolve macro imports for.

Usecase:

I want to be able to work on my projects, get the feel for a new config, edit the file from my current working directory (ie: inside a work project), and then save and compile my config before going back to what i was working on

this might also affect require calls but i'm not sure.

.fnl files not automatically compiling on save

Hello 👋! I'm having issues with files not being automatically compiled on save inside of my neovim directory.

# Neovim appimage through WSL
NVIM v0.9.1
Build type: Release
LuaJIT 2.1.0-beta3

Relevant files:

;; ~/.config/nvim/.nfnl.fnl
{:source-file-patterns ["fnl/**/*.fnl"]}
;; ./fnl/test.fnl
(vim.notify :hello)
{ :hello 123 }
-- ./lua/plugins/nfnl.lua
return {
     "Olical/nfnl",
     ft = "fennel",
}

Saving does not generate the file lua/test.lua, however require [[nfnl]]['compile-all-files ]() does work as expected. Lazy shows nfnl as loaded when opening a fennel file.

:au * fennel
# shows `nfnl-setup  FileType`

~Also unrelated: is there a way to specify a target directory for the generated files?

Non-deterministic output of lua?

Hi hi, great project - moved over from aniseed and it's been great so far!

I did notice one thing with checking in the generated files, though, is that occasionally the fields in lua will be reordered, leading to diffs in the generated code where there probably shouldn't be.

For example, the fennel code here:

https://github.com/stefanvanburen/dotfiles/blob/a8cabd4ca54e2052b71b88acb09f00f5f05f27e8/.config/nvim/init.fnl#L517-L538

Seems to occasionally be regenerated with a different field order, resulting in a diff:

-lspconfig.gopls.setup({cmd = {"gopls", "-remote=auto"}, settings = {gopls = {staticcheck = true, analyses = {unusedparams = true, unusedwrite = true, nilness = true}, hints = {parameterNames = true, functionTypeParameters = false, rangeVariableTypes = false, compositeLiteralFields = false, compositeLiteralTypes = false, assignVariableTypes = false, constantValues = false}}}})
+lspconfig.gopls.setup({cmd = {"gopls", "-remote=auto"}, settings = {gopls = {staticcheck = true, analyses = {unusedparams = true, unusedwrite = true, nilness = true}, hints = {parameterNames = true, assignVariableTypes = false, constantValues = false, functionTypeParameters = false, rangeVariableTypes = false, compositeLiteralFields = false, compositeLiteralTypes = false}}}})

(Particularly that last table, where it seems like the true field always comes first, but the false fields are ... in random order, as far as I can tell?)

Not sure if this is something that can be fixed or worked around, happy to help debug further!

Any way to disable compile on save?

It seems that compile on save conflicts with my format on save so I wish to trigger compiling manually. How do I set up the configuration to achieve that?

Cannot find macros from local repo

I'm starting to rewrite my config with nfnl, and I have a repo of macros (here) that I want so use from my local git repo of it. I have added the package to my runtime, and also installed with lazy.nvim afterwards, but nfnl just can't find them:

;init.fnl
(comment "Create necessary paths")
(local lazy-path (.. (vim.fn.stdpath :data) :/lazy/lazy.nvim))
(local package-path (.. (vim.fn.stdpath :data) :/lazy))
(local config-name :nvim-new)
(local nfnl-path (.. vim.env.HOME :/.config/ config-name :/.nfnl.fnl))
(local macros-repo (.. vim.env.HOME "/Repos/NEOVIM/nvim-anisole-macros"))

(comment "Install lazy for later. This is the recommended install method, not fennel specific")
(fn lazy-install []
  (when (not (vim.loop.fs_stat lazy-path))
    (vim.fn.system [:git
                    :clone
                    "--filter=blob:none"
                    :--single-branch
                    "https://github.com/folke/lazy.nvim.git"
                    lazy-path])))

(comment "Allow installation of bootstrapping plugins
      Macros and nfnl for compilation are installed this way")
(fn ensure [repo package dir]
 (if (not dir)
     (do
       (vim.fn.system [:git
                       :clone
                       "--filter=blob:none"
                       :--single-branch
                       (.. "https://github.com/" repo :.git)
                       (.. package-path "/" package)])
       (vim.opt.runtimepath:prepend (.. package-path "/" package)))
     (let [install-path (string.format "%s/%s" package-path
                         package)]
       (vim.fn.system (string.format "rm -r %s" install-path))
       (vim.fn.system (string.format "ln -s %s %s" repo
                       package-path))
       (vim.opt.runtimepath:prepend install-path))))

(comment "nfnl requires a config file to work, simply add that")
(fn nfnl-config []
  (when (not (vim.loop.fs_stat nfnl-path))
    (vim.fn.system (.. "touch " nfnl-path))
    (vim.fn.system (.. "bash -c 'echo \"{}\" >> " nfnl-path "'"))))

(comment "Run bootstrapping process")
(lazy-install)
(ensure macros-repo :nvim-anisole-macros true)
(ensure :Olical/nfnl :nfnl)
(nfnl-config)
(vim.opt.runtimepath:prepend lazy-path)
((. (require "lazy") :setup) :plugins)
Error detected while processing BufWritePost Autocommands for "<buffer=1>":                                                                               
/home/kat/.config/nvim-new/fnl/globals/options.fnl:1:0 Compile error: unknown:376:? Compile error: nvim-anisole.macros.options module not found.          
                                                                                                                                                          
                                                                                                                                                          
^[[7m(import-macros option :nvim-anisole.macros.options)^[[0m

File I am compiling:

(import-macros option :nvim-anisole.macros.options)
(option.set {mouse :nvi
             number true
             relativenumber true
             modeline true
             undofile true
             virtualedit "block"
             hidden false
             updatetime 100
             cmdheight 2
             title true})

.nfnl.fnl

{:fennel-macro-path "./?.fnl;./?/init-macros.fnl;./?/init.fnl;./fnl/?.fnl;./fnl/?/init-macros.fnl;./fnl/?/init.fnl;./fnl/?/macros/?.fnl"}

Prevents to open Fugitive diff

When I try to open a fugitive diff of a fennel file I get an error
.../.nfnl.fnl is not trusted, refusing to compile.

Steps to reproduce

  • make a change in a fennel file
  • open fugitive :Git
  • trigger vertical diff of the changed fenne file (dv mapping)

Expected - 2 buffers side by side comparing the indexed version of the file with the unstaged version
Actual - error .../.nfnl.fnl is not trusted, refusing to compile. and only one buffer opens with the local version

More details

The indexed version of the file has a path fugitive://{a}/.git//0/{b}/init.fnl
where {a} is the absolute path to the git folder on my machine and {b} path inside my git repo.
Looks like the corresponding fugitive://{a}/.git//0/{b}/.nfnl.fnl is not trusted.

  • any call to secure.read fugitive file returns nil (vim.secure.read "fugitive:///.../.nfnl.fnl")
  • trying to trust the file programmatically returns an error
(vim.secure.trust {:action :deny :path "fugitive:///.../.nfnl.fnl"})
"invalid path: "fugitive:///.../.nfnl.fnl"

Suggestions

Would it be possible to have a way to ignore some configuration files without a prompt?
A regular expression would be great, or a predicate function.

Alternatively, the message about untrusted .nfnl.fnl could be a warning, not an error.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.