Code Monkey home page Code Monkey logo

hotpot.nvim's Introduction

Hotpot Logo

๐Ÿฒ Hotpot

You take this home, throw it in a pot, add some broth, some neovim... baby, you got a stew going!

~ Fennel Programmers (probably)

Hotpot is a Fennel compiler plugin for Neovim. Just (require :my-fennel) and Hotpot does the rest, recompiling your fennel code as needed.

;; ~/.config/nvim/fnl/is_neat.fnl
;; put your fennel code in fnl/
(fn [what] (print what "is neat!"))
-- and require it like normal in your lua file
local neat = require('is_neat') -- compiled & cached on demand
neat("fennel") -- => "fennel is neat!"

TOC

Requirements

  • Neovim 0.9.1+
  • Fanatical devotion to parentheses.

Getting Started

Install

All you need to do is install Hotpot and call require("hotpot") in your init.lua Neovim configuration file.

First lets setup our init.lua file. In this example we use the lazy.nvim plugin manager, but other plugin manager will follow the same pattern -- likely without the runtimepath alterations.

-- ~/.config/nvim/init.lua

-- As per lazy's install instructions
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",
    "https://github.com/folke/lazy.nvim.git",
    "--branch=stable", -- latest stable release
    lazypath,
  })
end

-- Bootstap hotpot into lazy plugin dir if it does not exist yet.
local hotpotpath = vim.fn.stdpath("data") .. "/lazy/hotpot.nvim"
if not vim.loop.fs_stat(hotpotpath) then
  vim.notify("Bootstrapping hotpot.nvim...", vim.log.levels.INFO)
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "--single-branch",
    "--branch=v0.12.0",
    "https://github.com/rktjmp/hotpot.nvim.git",
    hotpotpath,
  })
end

-- As per lazy's install instructions, but insert hotpots path at the front
vim.opt.runtimepath:prepend({hotpotpath, lazypath})

require("hotpot") -- optionally you may call require("hotpot").setup(...) here

-- include hotpot as a plugin so lazy will update it
local plugins = {"rktjmp/hotpot.nvim"}
require("lazy").setup(plugins)

-- include the rest of your config
require("say-hello")

The say-hello module would be put in ~/.config/nvim/fnl/say-hello.fnl:

;; ~/.config/nvim/fnl/say-hello.fnl
(print :hello!)

Usage

Place all your fennel files under a fnl dir, as you would place lua files under lua. This practice extends to other folders outside of your config directory, such as plugins you may write or install.

With your file in the correct location, you only need to require it like you would any normal lua module.

;; ~/.config/nvim/fnl/is_neat.fnl
;; some kind of fennel code
(fn [what]
  (print what "is neat!"))
-- and in ~/.config/nvim/init.lua
local neat = require('is_neat')
neat("fennel") -- => "fennel is neat!"

Hotpot will keep an internal cache of lua code, so you won't see files cluttering the lua/ directory.

You can may want to read the cookbook or see more options in setup.

Setup

The setup() function may optionally be called. setup() provides access to Fennels configuration options as described on fennel-lang.org as well as some configuration of hotpot itself.

You do not have to call setup unless you are altering a default option.

require("hotpot").setup({
  -- provide_require_fennel defaults to disabled to be polite with other
  -- plugins but enabling it is recommended.
  provide_require_fennel = false,
  enable_hotpot_diagnostics = true,
  compiler = {
    -- options passed to fennel.compile for modules, defaults to {}
    modules = {
      -- not default but recommended, align lua lines with fnl source
      -- for more debuggable errors, but less readable lua.
      -- correlate = true
    },
    -- options passed to fennel.compile for macros, defaults as shown
    macros = {
      env = "_COMPILER" -- MUST be set along with any other options
    },
    -- A function that accepts a string of fennel source and a table of
    -- of some information. Can be used to alter fennel code before it is
    -- compiled.
    preprocessor = nil
  }
})
  • provide_require_fennel inserts a package.preload function that will load Hotpot's copy of fennel when you call (require :fennel). This can be useful for ergonomics or for compatibility with libraries that expect Fennel to be in package.path without having to pay the cost of loading the Fennel compiler when its not used.

  • enable_hotpot_diagnostics enable or disable automatic attachment of diagnostics to fennel buffers. See diagnostics.

  • compiler.modules is passed to the Fennel compiler when compiling regular module files.

  • compiler.macros is passed to the Fennel compiler when compiling macro files. Be sure to include env = "_COMPILER" unless you have a good reason not to.

  • compiler.preprocessor is a function that accepts the fennel source code as a string, and a table, {: path : modname : macro}.

Fennel compiler plugins are supported in two forms, as a table (ie. as described by Fennels documentation) and as a string which should be a module name. If your plugin needs access to the "compiler environment" (ie. it uses special forms such as (sym) or (macroexpand) not available to "normal" Fennel code), you should specify the module name and hotpot will load it when required in the compiler environment.

Note:

  • The filename compilation option is always set to the appropriate value and can not be altered via the setup interface.

  • The modules and macros tables replace the defaults when given, they are not merged. Include all options you wish to pass to the compiler!

  • The compiler options are not currently passed to any api.compile functions and are only applied to Hotpots internal/automatic compilation. If you have use for passing options to api.compile please open an issue.

For a complete list of compiler options, see Fennels documentation, specifically the API usage section.

dot-hotpot

Hotpot can optionally be configured to build lua/ directories on-save with per-project settings by using a .hotpot.lua file.

See :h hotpot-cookbook-using-dot-hotpot in the COOKBOOK.

Diagnostics

Hotpot ships with built in diagnostics feature to show fennel compilation errors via Neovim diagnostics.

It automatically attaches to buffers with the filetype fennel and updates when ever you leave insert mode or otherwise change the buffer.

"Macro modules" require a special fennel environment. To detect "macro modules", Hotpot checks if the buffer filename ends in macro.fnl or macros.fnl which is common practice. It's not currently possible to enable the macro environment in other contexts (please open an issue).

The API

Hotpot provides a number of functions for evaluating and compiling Fennel code, including helpers to easily operate on strings, selections and buffers for example.

See :h hotpot.api.

Commands

Hotpot provides 3 commands which behave similarly but not exactly like Neovims Lua commands (see :h lua-commands).

It also allows the :source command to work with .fnl files.

:[range]Fnl {expression}

: Evaluates {expression} or range

If given form is preceded by =, the result is passed through fennel.view and printed. Multiple return values are separated with , .

You may also use = when providing a range.

If a range and a form is provided, the range is ignored.

:Fnl (vim.keymap.set ...) ;; evaluates code, no output
:Fnl (values 99 (+ 1 1)) ;; evaluates code, no output
:Fnl =(values 99 (+ 1 1)) ;; evaluates code, outputs "99, 2"
:Fnl=(+ 1 1) ;; You may omit the space

:'<,'>Fnl ;; evaluates selection in current buffer
:1,10Fnl = ;; evaluate lines 1 to 10 in current buffer, prints output
:'<,'>Fnl= ;; again, the space may be omitted

:'<,'>Fnl (print :hello) ;; prints "hello" (range is ignored)

:[range]Fnldo {expression}

: Evaluates {expression} for each line in [range]

The result of the expression replaces each line in turn. Two variables are available inside {expression}, line and linenr.

:'<,'>Fnldo (string.format "%d: %s" linenr (line:reverse))
=> Prepends line number and reverses the contents of line

:Fnlfile {file}

: Evaluates {file}, see also :h :source.

:Fnlfile %

:Fnlfile my-file.fnl

:source {file}

: See :h :source

Keymaps

Hotpot expects the user to specify most maps themselves via the API functions (see :h hotpot.api). It does provide one <Plug> mapping for operator-pending eval.

<Plug>(hotpot-operator-eval)

Enters operator-pending mode and evaluates the Fennel code specified by the proceeding motion.

map <Plug> ghe <Plug>(hotpot-operator-eval)

gheip -> evauate fennel code in paragraph

Module preference

Given the directory structure,

mod/fnl/code.fnl
mod/lua/code.lua

and a call (require :code), Hotpot will opt to load the lua file instead of compiling the fennel source and overwriting mod/lua/code.lua.

This behaviour exists in case a plugin ships with both code in both the lua and fnl directories, but the plugin author has post-processed the compiled lua code, or is using an incompatible fennel version, etc.

In most cases, such as your config, Hotpot won't create mod/lua/code.lua and you won't run into any issues but it may encounter friction when writing a plugin in fennel.

Quirks

  • Hotpot will only compile fennel files that are found in Neovims RTP. It will evaluate files that are found in luas package.path. This is for safety purposes because it can be unclear where and when its safe to compile or overwrite .lua files. In most usage this won't occur -- files will be found in the RTP first but it can occur when executing in scratch buffers with the api or via commands.

Licenses

Hotpot embeds fennel.lua, see lua/hotpot/fennel.lua for licensing information.

hotpot.nvim's People

Contributors

6cdh avatar alexaandru avatar datwaft avatar mikemee avatar mrcjkb avatar rktjmp avatar s-cerevisiae avatar shadmansaleh 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

hotpot.nvim's Issues

Take advantage of lua binary loader when PR is merged

There is a Neovim PR that saves a loaded lua module via string.dump, meaning later loads can skip the interpreter.

Ideally we would be able to take advantage of this without extra effort, or at least clone the code for hotpot.

Depending on the final implementation in Neovim, we either:

  • piggy back internal implementation if it is exposed
    • Find or write hotpot cache file (the lua) when needed
    • Call out to neovim.lua_loader(path) to load path into cache / load from cache
    • This depends on how nvim's code works, not preferred option unless they intentionally expose the API
  • Output hotpot cache files into RTP and then return "not found" for requests which kicks back down the chain to nvims loader
    • instead of writing to hotpotcache/home/user/..../project/my/module.lua we write to hotpotcache/my/module.lua and add hotpotcache/ to the RTP.
    • requires hotpot to be the first loader/ahead of nvims (probably ok to enforce)
    • Opens the ./?.lua part of lua's package.path for collisions. This mostly wont impact users AFAIK since plugins can't use that anyway, but it would effect :Fnl commands that call require.
      • could check for relative require finds and act differently for those
      • Probably actually an option to hotpot: cache_style: shallow|deep which defaults to shallow for most people.
  • Clone the implementation internally
    • +most control, +code isn't very big
    • -extra maint, -pref to not double up

See:

Neovim PR (title slightly under described) neovim/neovim#15436
Extracted mpack loading https://github.com/lewis6991/impatient.nvim

Cannot import .so file in a macro file

Hello! I am here, again, with another bug.

This time the bug is related to trying to require a luarock module from a fennel macro file. I am trying to use this luarock inside my macro file to process strings using PCRE2 regexes.

As you can see in the next screenshot, the luarock can be required from init.lua and init.fnl, but it cannot be required from macrofile.fnl.

evidence

How to reproduce

Learning from past issues, I created this repository that contains how to reproduce the bug using docker.

My suspicions

I am using this:

local package_path_str = table.concat({
    "/opt/here/share/lua/5.1/?.lua", "/opt/here/share/lua/5.1/?/init.lua",
    "/opt/here/lib/luarocks/rocks-5.1/?.lua",
    "/opt/here/lib/luarocks/rocks-5.1/?/init.lua"
}, ";")

if not string.find(package.path, package_path_str, 1, true) then
    package.path = package.path .. ';' .. package_path_str
end

local install_cpath_pattern = "/opt/here/lib/lua/5.1/?.so"

if not string.find(package.cpath, install_cpath_pattern, 1, true) then
    package.cpath = package.cpath .. ';' .. install_cpath_pattern
end

To make neovim able to source luarocks as Lua modules. This is the way that packer recommends and uses.

Maybe the bug is related to the package.path variable.

Hotpot Reflect

  • Some plugins are destructive on the buffer and destroy the marks. We attempt to restore them but there may be more work we can do.
  • API terming is a bit off re: session maybe.
  • Expose API for sending ranges directly
    • Currently must have visual selection in current buffer, should accept buf positions where positions may or may not be "editor relative" [1,1] -> [n n] (how get-hl returns them) or [0,0] ... (how most of nvim's api works).

Reloading config with `:Fnlfile` or `:source` always look for macro file on current pwd

Hello! First of all I want to thank you for this marvelous plugin, being able to write my config in fennel has been tons of fun.
Unfortunately, I am having a couple troubles trying to figure out how to recompile fennel files on the fly.

So, a simplification of my current .config/nvim/ is the following folder structure:

โ”œโ”€โ”€ fnl/
โ”‚ย ย  โ”œโ”€โ”€ macros.fnl
โ”‚ย ย  โ”œโ”€โ”€ startup.fnl
โ”œโ”€โ”€ init.lua

where init.lua requires hotpot and startup, and startup.fnl uses the macros defined in macros.lua.
All is well and good for loading the files on startup.
The problem arises when I make some modification on startup.fnl during a session and want to reload it on the fly.
While hotpot scans the .config/nvim/fnl/ folder for loading modules with require, it seems to only scan the current pwd for the :Fnlfile or :source commands.
This behaviour is great for loading standalone fennel files but forces me to change my pwd everytime I want to reload the config.
I've looked through hotpot's docs but couldn't find how to change the macro searching behaviour when using :source instead of require . Is there any way to do that?

`require` fails when requiring a macro-utils file from other macro files with `compilerEnv` as `_G`

The issue is that when the compiler macro option compilerEnv is set to _G,
and you want to require a module that uses macro-exclusive functions from the
macro file, neovim displays the following error:

.../packer/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:113: Compile error in /root/.config/nvim/fnl/core/macro-utils.fnl:9
  symbols may only be used at compile time
        (= `fn (. x 1))
            ^^
            * Try moving this to inside a macro if you need to manipulate symbols/lists.

This could be the case if you want to share code between multiple macro files,
and therefore you create an utils module.

If you don't use that compiler macro option or you don't use an utils module
but have the code in the same macro file, everything works perfectly.

How to reproduce the issue

Note: you must have Docker installed on your computer.

Clone the following repository: datwaft/hotpot-issue_48

Execute the following terminal command:

docker build -t hotpot-issue . && docker run -it hotpot-issue

After that execute neovim:

nvim

Expected result

These lines should print "Hello"
================================
Hello
Hello
These lines should print "Bye"
==============================
Bye
Bye
Bye

Current result

The following error is displayed.

.../packer/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:113: Compile error in /root/.config/nvim/fnl/core/macro-utils.fnl:9
  symbols may only be used at compile time
        (= `fn (. x 1))
            ^^
            * Try moving this to inside a macro if you need to manipulate symbols/lists.

0.3.0 Breaking Changes

  • Neovim 0.7 required
  • Improved x-selection API selection accuracy.
    • Now uses nvim_get_mode, sometimes bindings set by whichkey.nvim
      incorrectly report the current mode, so this is potentially breaking if you
      use a non-standard way to set keys. Keymaps set via vim.keymap.set behave
      correctly.
  • hotpot.api.eval functions now return true result or false error for
    symmetry with hotpot.api.compile.
  • Moved fnl, fnlfile, fnldo, eval-operator and eval-operator-bang
    to hotpot.api.command.
  • Added in-editor diagnostics via hotpot.api.diagnostics
    • Enabled automatically in Fennel files. See :h hotpot.api.diagnostics for
      details and how to disable.
  • Added ahead of time compilation via hotpot.api.make.
  • Added in-editor repl-like via hotpot.api.reflect
    • Mark regions of your code and show the results of the compilation or
      evaluation as you edit. See :h hotpot.api.reflect for details.

See CHANGELOG.md

delete cache

How can I delete compilation cache? Its currently messing up and anytime I update my config I keep on getting this error (I deleted lua/plugins as now its written in fennel)

image

Cannot import .lua file from a macro file

Hello! Sorry for so many issues.

This time I was trying to use another regex library, as a continuation of #33. This library is LuLPeg and it is a pure Lua port of LPeg; which means that it doesn't need any .so files.

When I try to require this file from a macro file it seems to try to compile the file as if it was a .fnl file.

Here is the error message:

Error detected while processing /root/.config/nvim/init.lua:
.../packer/start/hotpot.nvim/fnl/hotpot/searcher/module.fnl:104: Compile error in /root/.config/nvim/fnl/core/init.fnl:3
  Parse error in /root/.config/nvim/lua/lulpeg.lua:1
  invalid whitespace after quoting prefix
-- LuLPeg, a pure Lua port of LPeg, Roberto Ierusalimschy's
----------^
stack traceback:
^I[C]: in function 'parse_error'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:3589: in function 'parse_prefix'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:3663: in function '(for generator)'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2996: in function 'compile-string'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:4014: in function 'loader'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2004: in function '_2_'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2007: in function 'require'
^I/root/.config/nvim/fnl/core/macro/macrofile.fnl:1: in function 'loader'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2041: in function 'require-macros'
^Isrc/fennel/macros.fnl:257: in function <src/fennel/macros.fnl:251>
^I[C]: in function 'xpcall'
^I...
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:3000: in function 'compile-string'
^I...te/pack/packer/start/hotpot.nvim/fnl/hotpot/compiler.fnl:23: in function <...te/pack/packer/start/hotpot.nvim/fnl/hotpot/compiler.fnl:22>
^I[C]: in function 'compile_string'
^I...te/pack/packer/start/hotpot.nvim/fnl/hotpot/compiler.fnl:40: in function <...te/pack/packer/start/hotpot.nvim/fnl/hotpot/compiler.fnl:29>
^I[C]: in function 'compile_fnl'
^I.../packer/start/hotpot.nvim/fnl/hotpot/searcher/module.fnl:101: in function <.../packer/start/hotpot.nvim/fnl/hotpot/searcher/module.fnl:89>
^I[C]: in function 'pcall'
^I.../packer/start/hotpot.nvim/fnl/hotpot/searcher/module.fnl:135: in function <.../packer/start/hotpot.nvim/fnl/hotpot/searcher/module.fnl:124>
^I[C]: in function 'require'
^I/root/.config/nvim/init.lua:15: in main chunk
(import-macros {} :core.macro.macrofile)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The module can be required without any problem in a normal .fnl file.

How to reproduce

Here is the repository to reproduce the issue: https://github.com/datwaft/hotpot-issue_34

Fennel files under ~/.config/nvim/plugin/* are not loaded automatically

Given the following files:

$ grep . plugin/*
plugin/bar.vim:echo 'bar.vim'
plugin/baz.lua:print "baz.lua"
plugin/foo.fnl:(print :foo.fnl)

loading vim, will automatically load, the vim, the lua but not the fnl file:

$ nvim --headless +q
bar.vim
baz.lua

It would be very nice if fennel files would also be loaded, similar to lua files. That would give us more flexibility into how we organize our config files.

To a more general note, it would be great if fennel would be supported everywhere where lua is (like colors, after, etc.). The neovim/neovim#12670 issue extended where lua can be used (including plugin folders).

Compilation result differs from `macrodebug` result

Hotpot Issue about Macro Expansion

This issue is about a difference between the result of a macro expansion in
macrodebug and the compilation result by using Hotpot.

How to reproduce the issue

Clone the following repository: https://github.com/datwaft/hotpot-macro_expansion_issue

Execute the following Docker command:

docker build -t issue . && docker run -it issue

Inside the Docker container execute nvim to open Neovim, the result of
macrodebug will be printed and can be accessed using :messages.

When you open /root/.cache/nvim/hotpot/root/.config/nvim/fnl/conf/init.lua
the compilation result doesn't contain the underline as would be expected.

Expected result

The macro...

(highlight! MatchParen [:underline] {:bg "#262626"})

...should be expanded to:

(vim.api.nvim_set_hl 0 "MatchParen" {:bg "#262626" :underline true})

Current result

The macro...

(highlight! MatchParen [:underline] {:bg "#262626"})

...is being expanded to:

(vim.api.nvim_set_hl 0 "MatchParen" {:bg "#262626"})

Macro file is required multiple times during compilation

Hello!

This issue was kind of a pain to debug.

One of the functionalities that I make use of in my macros to configure Neovim is that a global inside a macro file is defined when the macro file is required and then can be used by any macro during the compilation.

An example of a use of this is a global counter:

(set _G.__core_counter 0)

This counter can be used in the macros inside the file to generate an unique symbol each time without needing to use (os.date %s) or the like.

This functionality is present in the normal Fennel behaviour as can be seen in the reproduction repo.

In hotpot the macro file is evaluated each time it is required, which by itself goes against the normal behaviour of Fennel, but it seems that the counter is reset in each evaluation of the macro file, as if it wasn't set.

How to reproduce the issue

I created datwaft/hotpot-issue_38 to reproduce the issue using Docker.

Expected results

This can be seen by executing the following commands inside the Docker container:

foo@bar:~$ cd test && fennel init.fnl
The macros.fnl file was required.
The file1.fnl file was required.
file1   1
file1   2
file1   3
The file2.fnl file was required.
file2   4
file2   5
file2   6
The file3.fnl file was required.
file3   7
file3   8
file3   9

As you can see the macros.fnl file is only required once and the counter is maintained between files.

Current results

The macros.fnl file was required.
The file1.fnl file was required.
file1 1
file1 2
file1 3
The macros.fnl file was required.
The file2.fnl file was required.
file2 1
file2 2
file2 3
The macros.fnl file was required.
The file3.fnl file was required.
file3 1
file3 2
file3 3

As you can see the macros.fnl file is required once per file and the counter is not maintained.

ftplugins dir support

  • Add autocmd code, possibly behind a flag.
  • (try to) Benchmark impact.
  • default on or off (on is more seamless)
;; in your config
(let [{: nvim_create_autocmd : nvim_create_augroup} vim.api
      au-group (nvim_create_augroup :hotpot-ft {})
      cb #(pcall require (.. :ftplugin. (vim.fn.expand "<amatch>")))]
  (nvim_create_autocmd :FileType {:callback cb :group au-group}))
;; ~/.config/nvim/ftplugin/wow.fnl
(print :wow!)
"in vim
:set ft=wow
" wow!

Originally posted by @rktjmp in #41 (comment)

Very slow startup time on Windows

I was trying to port my Neovim config from my phone (with Termux) and Linux server to my Windows laptop, then I found it taking a lot of time to start on Windows: ~190ms on my phone, but ~2.7s on the Windows laptop, which is intolerable.

After some testing I confirmed that it's hotpot being slow.
nvim --startuptime showed that it takes 2456ms to load my init.lua. I manually compiled all my .fnls to Lua, removed require 'hotpot' from init.lua, and the time reduced to 84ms.

I tried to make a minimal reproducible config, and here's what I got:

init.lua:

local function ensure_installed(plugin)
  local author, name = unpack(vim.split(plugin, '/'))
  local plugin_path = vim.fn.stdpath('data')..'/site/pack/packer/start/'..name
  if vim.fn.empty(vim.fn.glob(plugin_path)) ~= 0 then
    print("Installing", plugin, "to", plugin_path)
    vim.fn.system({'git', 'clone', 'https://github.com/'..plugin, plugin_path})
  end
end
ensure_installed('rktjmp/hotpot.nvim')
require 'hotpot'
require 'start'

fnl/start.fnl

(print "do something")

This config can be used on any machine with a fresh install of Neovim.
In a Linux container it loads init.lua in 1ms and hotpot.nvim in 0.1ms after the second startup,
while on (another) Windows laptop loading init.lua always takes ~200ms. (hotpot takes about 0.2ms).
It also seems that the fennel module is always loaded on Windows.

I have 2 Windows devices and am willing to provide any additional information, try any solutions or do any tests as requested.

Support `:checkhealth` module creation

Hello!

I am currently trying to create a :checkhealth module for my Neovim configuration.

I tried creating a file called fnl/conf/health.fnl but Neovim is not detecting it for :checkhealth.

Later on I tried with lua/conf/health.lua and it worked, but I would like to create this module using Fennel.

Here is the code I am using, if it helps:

fnl/conf/health.fnl
(local config (require :lspconfig))
(local {:report_start report-start!
        :report_info report-info!
        :report_ok report-ok!
        :report_warn report-warn!
        :report_error report-error!} (require :health))
(local {: format} string)

(lambda executable? [command]
  (= 1 (vim.fn.executable command)))

(lambda report! [name]
  (assert (= :string (type name)) "expected string for name")
  (let [command (?. config name :cmd 1)]
    (if (executable? command)
      (report-ok! (format "%s: the command '%s' is executable." name command))
      (report-error! (format "%s: the command '%s' is not executable." name command)))))

(lambda check! []
  (report-start! "lspconfig servers' executables")
  (let [configured-servers (config.available_servers)]
    (if (= 0 (length configured-servers))
      (report-info! "no lsp servers have been configured.")
      (each [_ server (ipairs configured-servers)] (report! server)))))

{:check check!}
lua/conf/health.lua
local config = require("lspconfig")
local health = require("health")

local messages = {
	["executable"] = [[%s: the command '%s' is executable.]],
	["not-executable"] = [[%s: the command '%s' is not executable.]],
	["none"] = [[no lsp servers have been configured.]],
}

local function report(name)
	local command = config[name].cmd[1]
	if vim.fn.executable(command) == 1 then
		health.report_ok(string.format(messages["executable"], name, command))
	else
		health.report_error(string.format(messages["not-executable"], name, command))
	end
end

local function check()
	health.report_start("lspconfig servers' executables")
	local configured_servers = config.available_servers()
	if #configured_servers == 0 then
		health.report_info(messages["none"])
	else
		for _, server in ipairs(configured_servers) do
			report(server)
		end
	end
end

return {
	check = check,
}

Here is something from :help health-lua-dev that can help:

Healthchecks are functions that check the user environment, configuration,
etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/.

To add a new healthcheck for your own plugin, simply define a Lua module in
your plugin that returns a table with a "check()" function. |:checkhealth|
will automatically find and invoke this function.

If your plugin is named "foo", then its healthcheck module should be a file in
one of these locations on 'runtimepath' or 'packpath':
        - lua/foo/health/init.lua
        - lua/foo/health.lua

If your plugin provides a submodule named "bar" for which you want a separate
healthcheck, define the healthcheck at one of these locations on 'runtimepath'
or 'packpath':
        - lua/foo/bar/health/init.lua
        - lua/foo/bar/health.lua

All submodules should return a Lua table containing the method `check()`.

Add "intercept require :hotpot" option

Re: #27 where the cljlib must be patched so it's require :fennel calls can work without including fennel somewhere else.

It would be nice if Hotpot could optionally be instructed to intercept require calls for fennel and provide it's already included version.

require("hotpot").setup({
  intercept_require_fennel = true
})

Tests

Sorting out fennel, lua to fennel, how everything fits together and how to run a fennel test suite was a bit much when I just started mucking around with the idea in my dot files.

os.date in macros in 0.10.0

allowed globals changed, or warnings (that were maybe swallowed, somehow?) became errors.

Setting allowedGlobals: false disables global checks, which has precedence in fennel.fnl, so maybe not as gross as it looks?

Not super keen on it, maybe just follow convention and defer to fennels allowed list.

Building fennel plugin with hotpot

I saw your paperplanes.nvim plugin and thought that it would be nice to try build my own fennel plugin. I tried to find a way to compile fnl directory into lua. I found #18 issue, but seems like it's closed without providing info whether it is implemented or not. After trying to copy build.fnl and hotpotfile.fnl i get an error about trying to index "f_out" variable which is not even being called inside those .fnl files. I hope you could explain any way to compile fennel plugins using hotpot.nvim

requireAsInclude

Hi, sorry to bother you but is there a way to pass flags to the fennel compiler through hotpot? I would ideally like to pass the --require-as-include flag to fennel

Add ways to execute fennel code from neovim

@rktjmp I'm not sure if this falls under this plugin . But since it encourages using fennel even in small amounts I think it should help a bit with writting fennel too :)

It's too hard to write fennel without someway of exexuting and verifying that the code works . hotpot only loades the code once on require . Even re requiring the file after clearing package cache is clumsy .

After a good fight with fennel ๐Ÿ˜‚
I've put this in my configs

(fn get_range_lines [line1 line2]
  "
    Get buffer lines from range line1 - line2
    line1 & line2 can either be line number or position line [row, col]
  "
  (var retval [])
  (if (= (type line1) "number")
      (set retval (vim.api.nvim_buf_get_lines 0 (- line1 1) line2 false))
    (= (type line1) "table")
      (let [[line1_row line1_col] line1
            [line2_row line2_col] line2
            buf (vim.api.nvim_buf_get_lines 0 (- line1_row 1) line2_row false)]
          (when (> (length buf) 0)
            (tset buf 1 (string.sub (. buf 1) line1_col + 1))
            (tset buf (length buf) (string.sub (. buf (length buf)) 1 (+ line2_col 1)))
            (set retval buf))))
  retval)

(fn exec_fennel_str [...]
   "Executes input strings as fennel code"
  (let [buf (table.concat [...] " ")
        compiled-str ((. (require "fennel") "compileString") buf)]
    ((loadstring compiled-str))))

(fn exec_fennel_range [line1 line2]
  "Execute range from line1 - line2"
  (let [lines (table.concat (get_range_lines line1 line2) "\n")]
     (exec_fennel_str lines)))

(fn exec_fennel_file [fname]
  "Execute file fname"
  (local fname (vim.fn.expand fname))
  (local file (io.open fname))
  (if file
    (let [buf (file:read "*a")]
      (file:close)
      (exec_fennel_str buf))
    (print "File not found")))

(fn exec_fennel [line1 line2 fname]
  "Executes range line1 - line2 when fname isn't provided.
   When fname is provided executes the file.
   Used by :FennelFile command
  "
  (if (= fname "")
    (exec_fennel_range line1 line2)
    (exec_fennel_file fname)))

(fn fennel_operator_eval []
  "Executes range from mark '[ to mark '] set by 'opfunc'"
  (let [line1 (vim.api.nvim_buf_get_mark 0 "[")
        line2 (vim.api.nvim_buf_get_mark 0 "]")]
     (exec_fennel_range line1 line2))
  (if (. (require "exec_fennel") "opfunc_backup")
    (tset vim.o "operatorfunc" (. (require "exec_fennel") "opfunc_backup"))
    (tset (require "exec_fennel") "opfunc_backup"  "")
  ))

(fn exec_fennel_operator []
  "Sets fennel_operator_eval as 'opfunc' and trigures oppending mode"
  (tset (require "exec_fennel") "opfunc_backup" "")
  (tset vim.o "operatorfunc" "v:lua.require'exec_fennel'.fennel_operator_eval")
  (vim.api.nvim_feedkeys "g@" "n" false))

(fn define_commands []
  "Defines vimL api"
  (vim.cmd "
   command! -range=% -nargs=? -complete=file FennelFile :lua require'exec_fennel'.exec_fennel(<line1>, <line2>, <q-args>)
   command! -nargs=+ Fennel :lua require'exec_fennel'.exec_fennel_str(<q-args>)
   au! my_commands SourceCmd *.fnl :FennelFile <afile>
   nnoremap <Plug>(exec-fennel-operator) :lua require'exec_fennel'.exec_fennel_operator()<cr>
   "))

{ : get_range_lines
  : exec_fennel_range
  : exec_fennel_str
  : exec_fennel
  : define_commands
  : exec_fennel_operator
  "opfunc_backup" ""
  : fennel_operator_eval }

It provides

  1. :Fennel that directly executes fennel from argument. like :lua
  2. :FennelFile that executes a fennel file. like :source . Just like source it excepts range so you can execute specific regions of curremt buffer with that . If :FinnelFile is executed without argument and range it just executes current buffer . Again just mimics :source interface.
  3. A normal mode map for an operator \<Plug>(exec-fennel-operator) . This can execute fennel code from current buffer that is selected by operator . Like I have it mapped to \<leader>fe and I can go to a paran and do <leader>fe% or \<leader>fea( to execute the block
  4. Also sets a auto command so you can :source fennel files .

If you like you can put some of these interface in this plugins as helper.

cache path for file not following links

Installing a local plugin via packer creates a symlink, calling cache-path-for-fnl-file on a file in that plugin does not resolve because the path on disk is ~/projects/abc/xyz but the path in cache (loaded via RTP) is ~/.local/.../site/packer/abc/xyz.

Using should be using fs_realpath but maybe it got missed or ?

Potential breaking changes in Fennel version 1.0.0

Fennel 1.0.0 includes some changes that may effect your configurations, specifically around its macro sandboxing.

You may pin your clone to 3d83a46 if you experience any problems until you're ready to migrate.

See Fennels changelog for a complete list.

https://github.com/bakpakin/Fennel/blob/main/changelog.md

  • Enforce compiler sandbox by default instead of warning
  • Disallow & in identifiers
  • Implicit else branches in if are treated as nil, not zero values

See also #22 (comment) (and historically #16 #19)

Future Tooling

  • Expose hotpot.compile_file(in, out)
    Allows for saving arbitrary fnl files. in could be path or module name. Path may be tricky depending on needing package.path etc to be setup, so it would not be truly arbitrary.
    hotpot.api.compile

  • #18
    Can just be a lua/fnl file that we luado (maybe with fwatch.nvim if you cared for a watcher), maybe with some injected state.

  • Show cached lua

Can take current buffer (if backed by file), module name or file path? At least 1 & 2.

  • Clear cached lua

Probably two three forms.

  • clear_cache_file(fnl-path) converts fnl file to lua cache path and removes it
  • clear-cache-module(modname) converts modname to fnl path and clears it
  • clear-cache() nukes whole cache

Opt for explicit nuke over something like clear_cache_file() because clear_cache_file() == clear_cache_file(nil) == clear_cache_file(missing-var).

Probably OK to set this via a setup method. It must be set before requiring any other fnl files.

Maybe add-compiler-plugin so you can add one plugin then compile the next using that plugin, etc.

  • Better inline run-fennel tools

:Fennel code :FennelFile file :source file
See #8.

  • Fnldo

Mirror :luado

  • show log

Automatically opens ~/.cache/nvim/hotpot.log

hotpot/fs.lua:15 bad argument #2 to 'xpcall' (function expected, got nil)

Unsure makes this pop up, something to do with... adding a new file, writing out the compiled code post-compile breaks.

Loading a new separate nvim session will make the original session start working. Possibly to do with the first-load of hotpot after self compiling.

Started getting full error message which points to the second argument here:

return close_handlers_0_(xpcall(_0_, (package.loaded.fennel or debug).traceback))

Guessing that package.loaded.fennel resolves but is missing traceback somehow. The close_handlers.. call is automatically generated by Fennel, so you would hope it's OK.

`hotpot.lua:33: module 'hotpot.hotterpot' not found`

Running into this issue after a full system upgrade (NixOS and home-manager). Issue doesn't seem to be related to neovim's version, as I didn't have this issue with both neovim 0.6 stable and 0.7 nightly before upgrading all packages in my environment.

Here's the messages I get immediately after starting neovim:

Error detected while processing /home/harrison/.config/nvim/init.vim:
line    5:
E5108: Error executing lua .../home-manager/start/vimplugin-hotpot.nvim/lua/hotpot.lua:33: module 'hotpot.hotterpot' not found:
	no field package.preload['hotpot.hotterpot']
	no file '/home/harrison/.cache/nvim/hotpot//nix/store/6gncbnhp95g4vr1504jsp6ffnr1ldizc-vimplugin-hotpot.nvim/fnl/hotpot/hotterpot.lua'
	no file '/nix/store/jxz9x9xp1ss6w06022c2dljjnhqqmck1-luajit-2.1.0-2021-10-27-env/share/lua/5.1/hotpot/hotterpot.lua'
	no file '/nix/store/jxz9x9xp1ss6w06022c2dljjnhqqmck1-luajit-2.1.0-2021-10-27-env/share/lua/5.1/hotpot/hotterpot/init.lua'
	no file '/nix/store/jxz9x9xp1ss6w06022c2dljjnhqqmck1-luajit-2.1.0-2021-10-27-env/lib/lua/5.1/hotpot/hotterpot.so'
	no file '/nix/store/jxz9x9xp1ss6w06022c2dljjnhqqmck1-luajit-2.1.0-2021-10-27-env/lib/lua/5.1/hotpot.so'
stack traceback:
	[C]: in function 'require'
	.../home-manager/start/vimplugin-hotpot.nvim/lua/hotpot.lua:33: in function <.../home-manager/start/vimplugin-hotpot.nvim/lua/hotpot.lua:29>
	[C]: in function 'require'
	[string ":lua"]:1: in main chunk

# all of my fennel modules also not found ...

Error detected while processing /nix/store/6gncbnhp95g4vr1504jsp6ffnr1ldizc-vimplugin-hotpot.nvim/plugin/hotpot.vim:
line    2:
E5108: Error executing lua [string ":lua"]:1: loop or previous error loading module 'hotpot'
stack traceback:
	[C]: in function 'require'
	[string ":lua"]:1: in main chunk

Here's my neovim config for home-manager as well. Its parent directory is the rest of my home-manager config.

Any ideas? Let me know if I can help at all :) Thanks!

doc/hotpot.txt

Writing vimdoc sucks so ... I will write docs if this gets 10 stars on github. other people use ๐Ÿฒ Hotpot.

Build System

Experimental WIP https://github.com/rktjmp/hotpot-build.nvim

System with two parts

  • Build system, internal to hotpot (or hotpot-build.nvim, etc)
  • User spec file (hotpotfile.fnl? hotpot-build.fnl, cook.fnl)

Build system exposes:

  • compile-file(in, out)
    • in must be fnl file, out is lua file
    • makes dirs in path if not existing
  • compile-dir(in, out, ignore-matches?)
    • recurses in for fnl files, compile-file's
    • optional ignore-matches pattern (or list of patterns? or raw paths? or function that returns true/false?) which wont be compiled.
      • have to do this for "macro modules" that don't compile to anything on their own (never ever?)
  • rm-dir(dir)
    • removes directory
  • rm-file(file)
    • removes file
  • copy-file(from, to)
    • copy a to b (for bundled deps, etc)

Spec file

Fennel module that should return a table containing at least these functions:

  • build must provide
    • when run, uses compile-* and produces lua somewhere.
  • clean (optional?)
    • when run, cleans any artifacts of build
  • watch (optional)
    • returns list of folders or files to watch for changes and a matching function (name?) to call
    • if module exposes my-fn, watch can list :my-fn as a callable.

It could be reasonable to provide an embedded "default spec", which has

(fn build []
  (compile-dir :fnl :lua))

(fn clean []
  (rm-dir :lua))

(fn watch []
  {:fnl :build})

{: build
 : clean
 : watch}

Run via :HotpotBuild which looks for hotpotfile.fnl in working dir and loads that (always via fnlfile).

Cannot use cljlib with hotpot

When I try to use cljlib with hotpot the following error message is displayed:

E5113: Error while calling lua chunk: ...home/datwaft/.config/nvim.hotpot/fnl/lib/cljlib/init.lua:2066: 'end' expected (to close 'if' at line 2060) near '('

This is the tree structure I am using for this test:

.
โ”œโ”€โ”€ fnl
โ”‚ย ย  โ”œโ”€โ”€ core
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ init.fnl
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ plugin.fnl
โ”‚ย ย  โ””โ”€โ”€ lib
โ”‚ย ย      โ”œโ”€โ”€ cljlib
โ”‚ย ย      โ”‚ย ย  โ”œโ”€โ”€ init.fnl
โ”‚ย ย      โ”‚ย ย  โ””โ”€โ”€ macros.fnl
โ””โ”€โ”€ init.lua

I only made the following modifications to the source of cljlib:

  1. I modified the name of the init-macros.fnl file to macros.fnl.
  2. I updated the path to the macros module from :init-macros to :lib.cljlib.macros in the init.fnl file.
  3. I updated the path to the fennel module from :fennel to :hotpot.fennel in the macros.fnl file.

This is the content of my init.lua file:

local hotpot_path = vim.fn.stdpath("data") ..
                      "/site/pack/packer/start/hotpot.nvim"
if vim.fn.empty(vim.fn.glob(hotpot_path)) > 0 then
  print("Could not find hotpot.nvim, cloning new copy to", hotpot_path)
  vim.fn.system({
    "git", "clone", "https://github.com/rktjmp/hotpot.nvim", hotpot_path
  })
end
require("hotpot")
require("core")

This is the content of my fnl/core/init.fnl file:

(require :core.plugin)

This is the content of my fnl/core/plugin.fnl file:

(require :lib.cljlib)

As additional information, I got cljlib working with aniseed with almost the same modifications and tree structure.

Evidence

image

Make API

  • Allow source-dir to be source-path where if it's a dir, we iterate contents, if it's a file, we just use the file
    • other args are the same, so evin with a one-file source-path, you still write a pattern match + fn handler.
    • Reasoning: ~/config/.../boostap.fnl -> ~/config/.../init.fnl without having to iterate the whole dir.
    • Benchmark
  • Add note re lua pattern gotchas
  • silent? QOL bool flip for verbosity level?

Does Fennel un-intentionally store options given between compile calls?

(Issue not directly related to Hotpot (?) but marked here for now.)

Related to bakpakin/Fennel#427 which demonstrates plugins hanging around unintentionally.

With the config:

require("hotpot").setup({
  provide_require_fennel = true,
  compiler = {
    modules = {
      correlate = true,
    },
    macros = {
      env = "_COMPILER",
      compilerEnv = _G,
      allowedGlobals = false,
    }
  }
})

The allowedGlobals flag may be retained in Fennel compiler options after calling fennel.eval for a macro.

  • Non-hotpot test case
  • confirm/non-confirm

Enable useBitLib option by default?

Lua 5.3 added bitwise operators (<<, >>, &, |, ~).

LuaJIT has the bit module.

Fennel has the functions lshift, rshift, band, bor, bxor, bnot.

By default, these compile to be Lua 5.3 operators. You can pass the option useBitLib to the Fennel compiler to make it use the bit module. This is not mentioned in the API reference so it may not be considered "stable" but it's what the Fennel CLI uses for the --use-bit-lib argument.

Given that hotpot targets Neovim specifically I think this should always be done.

Bogus diagnostics in macro modules?

The Fennel manual describes using macro modules to export commonly re-used macros. In macro modules, macros are defined not using (macro) but rather as plain (fn) functions. This leads to hotpot mistakenly treating macro code as "run-time" (rather than "compile-time") code, reporting errors such as

  • "unknown-identifier: assert-compile"
  • "symbols may only be used at compile time"

etc.

Is there some way to configure hotpot so that it knows how to distinguish between regular (run-time) modules vs. macro (compile-time) modules?

COOKBOOK API usage

The cookbook API guide needs some touch ups:

  • use vim.keymap.set
  • properly handle multi-line output (previously whichkey was making this "just work" by breaking nvims mode)

Cannot require cljlib from a macro file

Hello! It's me again with another issue.

A few minutes ago, I happily began to work on migrating my configuration from aniseed to hotpot; but, while trying to implement a few macros for packer, I found that I cannot require cljlib from the macro file without an error saying io global not found.

Here is the full error:

Click to expand
^I.../hotpot/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:133: in function <.../hotpot/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:122>
^I[C]: at 0x7fc3d2943490
^I[builtin#25]: at 0x7fc3d2944eb0
^I[C]: in function 'require'
^I/home/datwaft/.config/nvim.hotpot/init.lua:10: in main chunk
^I[C]: in function 'dofile'
^I/home/datwaft/.config/nvim/lua/cheovim/loader.lua:246: in function 'create_plugin_symlink'
^I/home/datwaft/.config/nvim/lua/cheovim.lua:14: in main chunk
^I[C]: in function 'require'
^I/home/datwaft/.config/nvim/init.lua:1: in main chunk

(import-macros {} :core.macro.pack)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Try looking to see if there's a typo.
* Try using the _G table instead, eg. _G.io

* Try looking to see if there's a typo.
* Try using the _G table instead, eg. _G.io if you really want a global.
* Try moving this code to somewhere that io is in scope.
* Try binding io as a local in the scope of this code.
stack traceback:
^I[C]: in function 'error'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:3282: in function 'assert-compile'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2208: in function 'assert_compile'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2373: in function 'symbol_to_expression'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2716: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1551: in function 'special'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2635: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1002: in function 'special'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2635: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1356: in function 'compile_body'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1370: in function 'special'
^I...
^I.../hotpot/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:133: in function <.../hotpot/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:122>
^I[C]: at 0x7fc3d2943490
^I[builtin#25]: at 0x7fc3d2944eb0
^I[C]: in function 'require'
^I/home/datwaft/.config/nvim.hotpot/init.lua:10: in main chunk
^I[C]: in function 'dofile'
^I/home/datwaft/.config/nvim/lua/cheovim/loader.lua:246: in function 'create_plugin_symlink'
^I/home/datwaft/.config/nvim/lua/cheovim.lua:14: in main chunk
^I[C]: in function 'require'
^I/home/datwaft/.config/nvim/init.lua:1: in main chunk if you really want a global.
* Try moving this code to somewhere that io

* Try looking to see if there's a typo.
* Try using the _G table instead, eg. _G.io if you really want a global.
* Try moving this code to somewhere that io is in scope.
* Try binding io as a local in the scope of this code.
stack traceback:
^I[C]: in function 'error'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:3282: in function 'assert-compile'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2208: in function 'assert_compile'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2373: in function 'symbol_to_expression'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2716: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1551: in function 'special'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2635: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1002: in function 'special'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2635: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1356: in function 'compile_body'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1370: in function 'special'
^I...
^I.../hotpot/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:133: in function <.../hotpot/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:122>
^I[C]: at 0x7fc3d2943490
^I[builtin#25]: at 0x7fc3d2944eb0
^I[C]: in function 'require'
^I/home/datwaft/.config/nvim.hotpot/init.lua:10: in main chunk
^I[C]: in function 'dofile'
^I/home/datwaft/.config/nvim/lua/cheovim/loader.lua:246: in function 'create_plugin_symlink'
^I/home/datwaft/.config/nvim/lua/cheovim.lua:14: in main chunk
^I[C]: in function 'require'
^I/home/datwaft/.config/nvim/init.lua:1: in main chunk is in scope.
* Try binding io

* Try looking to see if there's a typo.
* Try using the _G table instead, eg. _G.io if you really want a global.
* Try moving this code to somewhere that io is in scope.
* Try binding io as a local in the scope of this code.
stack traceback:
^I[C]: in function 'error'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:3282: in function 'assert-compile'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2208: in function 'assert_compile'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2373: in function 'symbol_to_expression'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2716: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1551: in function 'special'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2635: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1002: in function 'special'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:2635: in function 'compile1'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1356: in function 'compile_body'
^I...site/pack/packer/start/hotpot.nvim/lua/hotpot/fennel.lua:1370: in function 'special'
^I...
^I.../hotpot/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:133: in function <.../hotpot/start/hotpot.nvim/fnl/hotpot/searcher/module.lua:122>
^I[C]: at 0x7fc3d2943490
^I[builtin#25]: at 0x7fc3d2944eb0
^I[C]: in function 'require'
^I/home/datwaft/.config/nvim.hotpot/init.lua:10: in main chunk
^I[C]: in function 'dofile'
^I/home/datwaft/.config/nvim/lua/cheovim/loader.lua:246: in function 'create_plugin_symlink'
^I/home/datwaft/.config/nvim/lua/cheovim.lua:14: in main chunk
^I[C]: in function 'require'
^I/home/datwaft/.config/nvim/init.lua:1: in main chunk as a local in the scope of this code.

While searching for uses of the io lua module inside cljlib I found these:

; init.fnl
439:                   (do (io.stderr:write
462:                   (do (io.stderr:write
; init-macros.fnl
129:                  (io.stderr:write "WARNING: utf8 module unavailable, seq function will not work for non-unicode strings\n")

My suspicions are that fennel is not finding the io module on compilation time.

Compiler Configuration

Edit
Should allow for configuring general settings for compilers, macro and module separately.


Fennel allows for "compiler plugins", so Hotpot should support those, but... I am not sure any exist (?), or what you would want them to do, so until a hard use case appears this will probably sit in the todo list.

The likely API would be

-- init.lua

-- still need to do this
-- normal install system will be plugin-free
local hotpot = require("hotpot")

-- add plugins
local plugin_id = hotpot.add_plugin("my-plugin-module")
-- probably by modname, maybe return uid for each so you can remove_plugin? Or just reuse modname?

require("my-file-that-needs-plugin")

Windows support

Does Hotpot support Windows? Are there any specific install instructions? Keeps complaining hotpot.hotterpot not found.

(import-macros ...) compatibility with conjure

We autocompile fnl files as requested, meaning you can (require :my.fnl.mod) in your conjure session without having to do anything, but (import-macros ...) fails for some reason with module not found. The stacktrace doesn't include hotpot so maybe conjure hijacks those calls specifically.

It did look like it was hitting require with utils.path, would have thought it would work.

Tried various cwd's and package.path should be fine, no access to fennel.path if it's using that.

Hooks interface?

RE: #33

To avoid the cost of requiring fennel if you want to do "low level" stuff, a/some hooks would be nice.

There is probably only one real place to hook which is just after we require Fennel. Adding other hooks for will-load-module|macro or will-compile-module|macro could exist but are probably not that useful?

(fn compile-string [string options]
  (local fennel (require-fennel))

  ;; -------------
  ;; hook interface?
  ;; -------------
  (each [_ hook (ipairs config.hooks)] ; config.when_fennel? config.with_fennel? 
    (hook fennel))

  (when (not has-injected-macro-searcher)
    (table.insert fennel.macro-searchers 1 macro-searcher)
    (set has-injected-macro-searcher true))

  (local options (doto (or options {})
                       (tset :filename (or options.filename :hotpot-compile-string))))
  (fn compile []
    (pick-values 1 (fennel.compile-string string options)))
  (xpcall compile fennel.traceback))

and a hook would just be a function that accepts fennel and returns ... true|nil,error? Probably the hook should just raise if they have an error.

-- users responsibility to avoid repeats?
local once = false
local add_cloader = function(fennel)
  if once then return end
  table.insert(fennel["macro-searchers"], function(module_name)
     local filename = fennel["search-module"](module_name, package.cpath)
     if filename then
        local func = "luaopen_" .. module_name
        return function() return package.loadlib(filename, func) end, filename
     end
  end)
  once = true
end

require("hotpot").setup({
  provide_require_fennel = true,
  hook = {add_cloader}
})

Mostly this is just a question of names:

will_compile = {}
configure_fennel = {}
on|for|with|when|has_fennel = {}
when_load_fennel = {}

required_fennel = {} -- might cause confusion around regular "require fennel"
                     -- not popping the hook, though that could be made to work easily.

-- allows for future hooks in namespace
hook = {
  will_compile = {}
}

on = {
  require(d?)_fennel = {} -- requireD because we call *after* require, not intercepting require.
}

And also a question of once or many times. Do you want to configure fennel (once) or run a hook on every compile (many), why?

hotpot.nvim breaks Nix/Neovim/home-manager configuration

Apologies if this is the wrong place to report this, but this seems to be a "regression" of sorts with hotpot.

The error occurs while configuring Neovim with home-manager:

$ nix log /nix/store/sqrmgrw58sycvi99ldsdpwhxm3k5ilpv-neovim-0.6.1.drv
Generating remote plugin manifest
Error detected while processing /nix/store/jlznc3if8w0myi9h3v9xaqlih8zaqgh7-vimplugin-hotpot.nvim/plugin/hotpot.vim:
line    2:
E5108: Error executing lua Vim:E739: Cannot create directory /nix/store/silam09pv3pvvvx4zrpkjvccllfxggpn-vim-pack-dir/pack/home-manager/start/vimplugin-hotpot.nvim/lua/hotpot/api: permission denied
stack traceback:
	[C]: in function 'mkdir'
	.../home-manager/start/vimplugin-hotpot.nvim/lua/hotpot.lua:65: in function 'compile_dir'
	.../home-manager/start/vimplugin-hotpot.nvim/lua/hotpot.lua:66: in function 'compile_dir'
	.../home-manager/start/vimplugin-hotpot.nvim/lua/hotpot.lua:82: in function 'compile_hotpot'
	.../home-manager/start/vimplugin-hotpot.nvim/lua/hotpot.lua:105: in main chunk
	[C]: in function 'require'
	[string ":lua"]:1: in main chunk
remote/host: python3 host registered plugins []
remote/host: generated rplugin manifest: /nix/store/d1innpx3r0mrs1rxhbfh4sl80cv827bc-neovim-0.6.1/rplugin.vim
Generating rplugin.vim failed!

More info

hotpot.nvim broken commit hash: 72704e1

last hotpot.nvim commit that worked: 0e0e8df

Neovim version: 0.6.1 (fails with nightly, too)

hotpot plugin definition in my config

hotpot plugin usage in my neovim config

Thanks in advance for your insights ๐Ÿ˜

`...` is nil from Fennel but not from Lua

Hello!

Today, while I was testing utf.lua, a library that seems to promising to process regexes with utf-8 characters, I found a very strange bug related to hotpot.

When requiring the library from a fennel file the following error message is displayed:

/root/.config/nvim/lua/utf8/init.lua:2: attempt to index local 'module_path' (a nil value)

It seems that this library aliases ... as module_path, and when requiring a file from Fennel ... is nil, but when requiring it from Lua it's not (permalink).

local module_path = ...
module_path = module_path:match("^(.-)init$") or (module_path .. '.')

This could be related to those patches from #27.

This issue is strange because, as you can see in this branch of the reproduction repository, when requiring the module from init.lua there is no problem.

Additionally, as you can see in this branch, when the order of the requires change and you first require from the Lua file and after that from the Fennel file, the test passes. This is because the package was successfully loaded from Lua and doesn't need to be loaded again.

This could be a temporary fix.

How to reproduce

I created this repository to reproduce the issue using Docker: datwaft/hotpot-issue_35

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.