Skip to content

kisuryoza/tangerine.nvim

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🍊 Tangerine 🍊

Neovim version GNU Neovim in Emacs version

AboutInstallationSetupCommandsAPIDevelopment

About

Tangerine provides a painless way to add fennel to your config.

Features

  • 🔥 BLAZING fast, compile times in milliseconds
  • 🌊 200% support for interactive evaluation
  • 🎍 Control over when and how to compile
  • 🎀 Natively loads nvim/init.fnl

Comparison to other plugins

HOTPOT 🍲
  • Abstracts too much away from user.
  • Hooks onto lua package searchers to compile [harder to debug]
ANISEED 🌿
  • Excessively feature rich to be used for dotfiles.
  • Blindly compiles all files that it founds, resulting in slow load times.

Installation

  1. Create file plugin/0-tangerine.lua to bootstrap tangerine:

NOTE: if you are using lazy plugin manager, you should create /init.lua instead.

-- ~/.config/nvim/plugin/0-tangerine.lua

-- pick your plugin manager, default [standalone]
local pack = "tangerine" or "packer" or "paq"

local function bootstrap(url, ref)
	local name = url:gsub(".*/", "")
	local path = vim.fn.stdpath [[data]] .. "/site/pack/".. pack .. "/start/" .. name

	if vim.fn.isdirectory(path) == 0 then
		print(name .. ": installing in data dir...")

		vim.fn.system {"git", "clone", url, path}
		if ref then
			vim.fn.system {"git", "-C", path, "checkout", ref}
		end

		vim.cmd [[redraw]]
		print(name .. ": finished installing")
	end
end

-- for git head
bootstrap("https://github.com/udayvir-singh/tangerine.nvim")

-- for stable version
bootstrap("https://github.com/udayvir-singh/tangerine.nvim", "v2.3")
  1. Call tangerine setup() function:
-- ~/.config/nvim/plugin/0-tangerine.lua

require "tangerine".setup {
	[[ config, see below ]]
}
  1. Invoke :FnlCompile manually or add hooks in setup.

🎋 Now start writing your config in ~/.config/nvim/init.fnl.

🌺 Optionally you can also install hibiscus for macros.


Packer

You can use packer to manage tangerine afterwards [only do this if you haven't used ref option in bootstrap]:

(local packer (require :packer))

(packer.startup (lambda [use]
  (use :udayvir-singh/tangerine.nvim)))

Using hibiscus macros:

(require-macros :hibiscus.packer)

(packer-setup {}) ; bootstraps packer

(packer
  (use! :udayvir-singh/tangerine.nvim))

Paq

(local paq (require :paq))

(paq [
  :udayvir-singh/tangerine.nvim
])

Setup

Default config

Tangerine comes with sane defaults so that you can get going without having to add much to your config:

local nvim_dir = vim.fn.stdpath [[config]]

{
	vimrc   = nvim_dir .. "/init.fnl",
	source  = nvim_dir .. "/fnl",
	target  = nvim_dir .. "/lua",
	rtpdirs = {},

	custom = {
		-- list of custom [source target] chunks, for example:
		-- {"~/.config/awesome/fnl", "~/.config/awesome/lua"}
	},

	compiler = {
		float   = true,     -- show output in floating window
		clean   = true,     -- delete stale lua files
		force   = false,    -- disable diffing (not recommended)
		verbose = true,     -- enable messages showing compiled files

		globals = vim.tbl_keys(_G), -- list of alowedGlobals
		version = "latest",         -- version of fennel to use, [ latest, 1-2-1, 1-2-0, 1-1-0, 1-0-0, 0-10-0, 0-9-2 ]

		-- hooks for tangerine to compile on:
		-- "onsave" run every time you save fennel file in {source} dir
		-- "onload" run on VimEnter event
		-- "oninit" run before sourcing init.fnl [recommended than onload]
		hooks   = {}
	},

	eval = {
		float  = true,      -- show results in floating window
		luafmt = function() -- function that returns formatter with flags for peeked lua
			return {"/path/lua-format", ...} -- optionally install lua-format by `$ luarocks install --server=https://luarocks.org/dev luaformatter`
		end,

		diagnostic = {
			virtual = true,  -- show errors in virtual text
			timeout = 10     -- how long should the error persist
		}
	},

	keymaps = {
		-- set them to <Nop> if you want to disable them
		eval_buffer = "gE",
		peek_buffer = "gL",
		goto_output = "gO",
		float = {
			next    = "<C-K>",
			prev    = "<C-J>",
			kill    = "<Esc>",
			close   = "<Enter>",
			resizef = "<C-W>=",
			resizeb = "<C-W>-"
		}
	},

	highlight = {
		float   = "Normal",
		success = "String",
		errors  = "DiagnosticError"
	},
}

Example Config

Here is config that I use in my dotfiles:

{
	-- save fnl output in a separate dir, it gets automatically added to package.path
	target = vim.fn.stdpath [[data]] .. "/tangerine",

	-- compile files in &rtp
	rtpdirs = {
		"plugin",
		"colors",
		"$HOME/mydir" -- absolute paths are also supported
	},

	compiler = {
		-- disable popup showing compiled files
		verbose = false,

		-- compile every time changed are made to fennel files or on entering vim
		hooks = {"onsave", "oninit"}
	}
}

Commands

Compiling

:FnlCompileBuffer

Compiles current active fennel buffer

:FnlCompile[!]

Diff compiles all indexed fennel files

If bang! is present then forcefully compiles all source files

:FnlClean[!]

Deletes stale or orphaned lua files in target dir

If bang! is present then it deletes all compiled lua files

Evaluation

:Fnl {expr}

Executes and Evalutate {expr} of fennel

:Fnl (print "Hello World")
  -> Hello World

:Fnl (values some_var)
  -> :return [ 1 2 3 4 ]

:FnlFile {file}

Evaluates {file} of fennel and outputs the result

:FnlFile path/source.fnl

:FnlFile % ;; not recommended

:[range]FnlBuffer

Evaluates all lines or [range] in current fennel buffer

mapped to gE by default.

Peeking

:[range]FnlPeek

Peek lua output for [range] in current fennel buffer

mapped to gL by default.

:FnlGotoOutput

Open lua output of current fennel buffer in a new buffer

mapped to gO by default.

Window

:FnlWinNext [N]

Jump to [N]th next floating window created by tangerine

mapped to CTRL-K in floats by default.

:FnlWinPrev [N]

Jump to [N]th previous floating window created by tangerine

mapped to CTRL-J in floats by default.

:FnlWinResize [N]

Increase or Decrease floating window height by [N] factor

mapped to CTRL-W = to increase and CTRL-W - decrease by default.

:FnlWinClose

Closes current floating window under cursor

mapped to ENTER in floats by default.

:FnlWinKill

Closes all floating windows made by tangerine

mapped to ESC in floats by default.

FAQ

Q: How to make tangerine compile automatically when you open vim

A: add hooks in config:

require [[tangerine]].setup {
	compiler = {
		-- if you want to compile before loading init.fnl (recommended)
		hooks = {"oninit"}

		-- if you only want after VimEnter event has fired
		hooks = {"onenter"}
	}
}

Q: How to tuck away compiled output in a separate directory

A: change target in config:

require [[tangerine]].setup {
	target = "/path/to/your/dir"
}

Q: How to make impatient work with tangerine

A: just bootstrap and require impatient before calling tangerine:

bootstrap "https://github.com/lewis6991/impatient.nvim"

require [[impatient]]

require [[tangerine]].setup {...}

Q: How to use lua files interchangeably with fennel files

A: lua files can simply be stored in fnl dir:

fnl
├── options.lua
└── autocmd.fnl
; just require both normally
(require :options)
(require :autocmd)

Q: How to fix errors in macros while migrating from hotpot

A: make sure that macro files are suffixed with -macros.fnl.

utils
├── neovim-macros.fnl
└── packer-macros.fnl

see #2 for more information

Api

By default tangerine provides the following api:

:Fnl tangerine.api

-> :return {
     :compile {
       :all    (function 0)
       :buffer (function 1)
       :custom (function 2)
       :dir    (function 3)
       :file   (function 4)
       :rtp    (function 5)
       :string (function 6)
       :vimrc  (function 7)
     }
     :clean {
       :rtp      (function 8)
       :target   (function 9)
       :orphaned (function 10)
     }
     :eval {
       :buffer (function 11)
       :file   (function 12)
       :peek   (function 13)
       :string (function 14)
     }
     :win {
       :next    (function 15)
       :prev    (function 16)
       :close   (function 17)
       :killall (function 18)
       :resize  (function 19)
     }
     :goto_output (function 20)
     :serialize   (function 21)
   }

Compiler Api

This section describes function for tangerine.api.compile.{func}

compile-string

 (compile.string {str} {opts?})

Compiles string {str} of fennel, returns string of lua.

Parameters:
{
	:filename <string>
	:globals  <list>
}

compile-file

 (compile.file {source} {target} {opts?})

Compiles fennel {source} and writes output to {target}.

Parameters:
{
	:filename <string>
	:globals  <list>
}

compile-dir

 (compile-dir {source} {target} {opts?})

Diff compiles files in {source} dir and outputs to {target} dir.

Parameters:
{
	:force   <boolean>
	:float   <boolean>
	:verbose <boolean>
	:globals <list>
}

{opts.force} disables diffing if set to true

Example:
(tangerine.api.compile.dir
	:path/fnl
	:path/lua
	{ :force false :float true :verbose true })

compile-buffer

 (compile-buffer {opts?})

Compiles the current active fennel buffer.

Parameters:
{
	:float    <boolean>
	:verbose  <boolean>
	:filename <string>
	:globals  <list>
}

compile-vimrc

 (compile-vimrc {opts?})

Diff compiles config.vimrc to config.target dir.

Parameters:
{
	:force    <boolean>
	:float    <boolean>
	:verbose  <boolean>
	:filename <string>
	:globals  <list>
}

{opts.force} disables diffing if set to true

compile-rtp

 (compile.rtp {opts?})

Diff compiles fennel files in config.rtpdirs or {opts.rtpdirs}.

Parameters:
{
	:rtpdirs  <list>
	:force    <boolean>
	:float    <boolean>
	:verbose  <boolean>
	:globals  <list>
}

{opts.force} disables diffing if set to true

Example:
(tangerine.api.compile.rtp {
	:rtpdirs ["colors" "plugin" "$HOME/mydir"]
	:force   false
	:float   true
	:verbose true })

compile-custom

 (compile.custom {opts?})

Diff compiles fennel files indexed in config.custom or {opts.custom}.

Parameters:
{
	:custom   <list>
	:force    <boolean>
	:float    <boolean>
	:verbose  <boolean>
	:globals  <list>
}

{opts.force} disables diffing if set to true

Example:
(tangerine.api.compile.custom {
	:custom  [["~/path/fnl" "~/path/lua"]]
	:force   false
	:float   true
	:verbose true })

compile-all

 (compile.all {opts?})

Diff compiles all indexed fennel files in config.

Parameters:
{
	:force    <boolean>
	:float    <boolean>
	:verbose  <boolean>
	:globals  <list>
	:rtpdirs  <list>
	:custom   <list>
}

{opts.force} disables diffing if set to true

Cleaning Api

Provides functions to clean stale / orphaned lua files in target dirs.

This section describes function for tangerine.api.clean.{func}

clean-target

 (clean.target {source} {target} {opts?})

Deletes orphaned? {target} after comparing against {source}.

Parameters:
{
	:force <boolean>
}

{opts.force} deletes {target} without comparing if set to true

clean-rtp

 (clean.rtp {opts?})

Deletes all orphaned lua files in config.rtpdirs or {opts.rtpdirs}.

Parameters:
{
	:force    <boolean>
	:float    <boolean>
	:verbose  <boolean>
	:rtpdirs  <list>
}

{opts.force} deletes all compiled files if set to true

clean-orphaned

 (clean.orphaned {opts?})

Deletes all orphaned lua files indexed inside target dirs.

Parameters:
{
	:force    <boolean>
	:float    <boolean>
	:verbose  <boolean>
	:rtpdirs  <list>
}

{opts.force} deletes all compiled files if set to true

Evaluation Api

This section describes function for tangerine.api.eval.{func}

eval-string

 (eval.string {str} {opts?})

Evaluates string {str} of fennel, pretty prints the output.

Parameters:
{
	:float    <boolean>
	:virtual  <boolean>
	:filename <string>
	:offset   <number> ;; line offset for errors
}

eval-file

 (eval.file {path} {opts?})

Evaluates {path} of fennel, pretty prints the output.

Parameters:
{
	:float    <boolean>
	:virtual  <boolean>
	:filename <string>
}

eval-buffer

 (eval.buffer {start} {end} {opts?})

Evaluates lines {start} to {end} in current fennel buffer.

Parameters:
{
	:float    <boolean>
	:virtual  <boolean>
	:filename <string>
}

eval-peek

 (eval.peek {start} {end} {opts?})

Peek lua output for lines {start} to {end} inside a scratch buffer.

Parameters:
{
	:float    <boolean>
	:virtual  <boolean>
	:filename <string>
}

Utils Api

goto_output

 (tangerine.api.goto_output)

Open lua source of current fennel buffer in a new buffer.

serialize

 (tangerine.api.serialize {...})

Returns human-readable representation of {...}.

Example:
(tangerine.api.serialize example)
-> ":return [ 1 2 3 4 ]"

Windows Api

Provides functions to interact with floating windows created by tangerine.

This section describes function for tangerine.api.win.{func}

win-next

 (tangerine.api.win.next {steps?})

Switch to next floating window by 1 or N {steps?}.

win-prev

 (tangerine.api.win.prev {steps?})

Switch to previous floating window by 1 or N {steps?}.

win-resize

 (tangerine.api.win.resize {factor})

Changes height of current floating window by {factor} of N.

win-close

 (tangerine.api.win.close)

Closes current floating window, switching to nearest neighbor afterwards.

win-killall

 (tangerine.api.win.killall)

Closes all floating windows created by tangerine.

Fennel Api

fennel-load

 (tangerine.fennel {version?})

Provides underlying fennel used by tangerine

{version} can be one of [ "latest" "1-2-1" "1-2-0" "1-1-0" "1-0-0" "0-10-0" "0-9-2" ]

Development

Requirements

Program Description
pandoc generates vimdoc
lua runs included fennel
make runs build instructions
watchexec build on changes (optional)
bash runs shell scripts
utils coreutils findutils gawk curl

only GNU/utils work, 9base or busybox should not work

Building from source

git clone https://github.com/udayvir-singh/tangerine.nvim
cd tangerine.nvim

make <git-hooks>
make <target>

see make help or below for information on targets.

Make Targets

Target Description
:fnl compiles fennel files
:deps copy required deps in lua folder
:vimdoc runs panvimdoc to generate vimdocs
:fnldoc generates module level documentation
:build combines :fnl :deps :vimdoc :fnldoc
:watch-build watches source dir, runs :build on changes
:clean deletes build and install dir
:install install tangerine on this system
:runner compiles test runner library
:test runs unit tests, will erase nvim config

To build tangerine run:

$ make clean build
# or
$ make watch-build

To install tangerine run:

$ make install

Git Hooks

Target Description
git-pull safely fetches git repo, prevents conflicts with local changes
git-skip makes git ignore changes to build files
git-unskip reverts git-skip, makes build files trackable
Example workflow:
$ make git-skip # first thing that you should be running

# makes changes to tangerine
$ ...
$ make clean build

# commit changes
$ git commit -a -m "<msg>"

# cleanly fetch from origin
$ make git-pull

LOC Helpers

Helpers to generate detailed summary about lines of code in source files:

$ make loc-{language}
Supported Languages:
  • fennel / test
  • bash
  • markdown
  • makefile
  • yaml
Examples:
$ make loc-fennel

$ make loc-bash

End Credits

  • myself: for making this plugin
  • myself: for refactoring this plugin
  • myself: for bloating this plugin...
:: おれとして白眼くらする蛙かな ::

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Fennel 79.6%
  • Shell 14.9%
  • Makefile 5.5%