• Stars
    star
    674
  • Rank 64,641 (Top 2 %)
  • Language
    Lua
  • License
    MIT License
  • Created 11 months ago
  • Updated 18 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ–ΌοΈ Bringing images to Neovim.

πŸ–ΌοΈ image.nvim

Warning

This is very much a work in progress, there are many bugs, and there's lots to improve, but... we're getting there!

image.nvim is an attempt to add image support to Neovim.

image-2.mp4

Requirements

These are things you have to setup on your own:

After installing the magick LuaRock, you need to change your config to load it.

-- Example for configuring Neovim to load user-installed installed Lua rocks:
package.path = package.path .. ";" .. vim.fn.expand("$HOME") .. "/.luarocks/share/lua/5.1/?/init.lua;"
package.path = package.path .. ";" .. vim.fn.expand("$HOME") .. "/.luarocks/share/lua/5.1/?.lua;"

NixOS users need to install imageMagick and luajitPackages.magick (thanks to @donovanglover).
If you don't want to deal with setting up LuaRocks, you can just build your Neovim with the rock installed:

# https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/editors/neovim/utils.nix#L27
{ pkgs, neovimUtils, wrapNeovimUnstable, ... }:

let
  config = pkgs.neovimUtils.makeNeovimConfig {
    extraLuaPackages = p: [ p.luarocks p.magick ];
    withNodeJs = false;
    withRuby = false;
    withPython3 = false;
    # https://github.com/NixOS/nixpkgs/issues/211998
    customRC = "luafile ~/.config/nvim/init.lua";
  };
in {
  nixpkgs.overlays = [
    (_: super: {
      neovim-custom = pkgs.wrapNeovimUnstable
        (super.neovim-unwrapped.overrideAttrs (oldAttrs: {
          version = "master";
          buildInputs = oldAttrs.buildInputs ++ [ super.tree-sitter ];
        })) config;
    })
  ];
  environment.systemPackages = with pkgs; [ neovim-custom ];
}

Configuration

-- default config
require("image").setup({
  backend = "kitty",
  integrations = {
    markdown = {
      enabled = true,
      sizing_strategy = "auto",
      download_remote_images = true,
      clear_in_insert_mode = false,
    },
    neorg = {
      enabled = true,
      download_remote_images = true,
      clear_in_insert_mode = false,
    },
  },
  max_width = nil,
  max_height = nil,
  max_width_window_percentage = nil,
  max_height_window_percentage = 50,
  kitty_method = "normal",
  kitty_tmux_write_delay = 10, -- makes rendering more reliable with Kitty+Tmux
  window_overlap_clear_enabled = false, -- toggles images when windows are overlapped
  window_overlap_clear_ft_ignore = { "cmp_menu", "cmp_docs", "" },
})

Try it out with a minimal setup

Download minimal-setup.lua from the root of this repository and run the demo with:

nvim --clean -c ":luafile minimal-setup.lua"

Backends

All the backends support rendering inside Tmux.

  • kitty - best in class
    • Works great, is snappy and has very few artifacts (on my machine, at least).
    • Use the default mode, the unicode placeholder method is buggy for now.
  • ueberzug - backed by ueberzugpp
    • More genera, on-par with Kitty in terms of features, but slower.
    • Supports multiple images thanks to @jstkdng.
  • sixels - not implemented yet

Integrations

API

Check types.lua for a better overview of how everything is modeled.

local api = require("image")

-- from a file (absolute path)
local image = api.from_file("/path/to/image.png", {
  id = "my_image_id", -- optional, defaults to a random string
  window = 1000, -- optional, binds image to a window and its bounds
  buffer = 1000, -- optional, binds image to a buffer (paired with window binding)
  with_virtual_padding = true, -- optional, pads vertically with extmarks
  ...geometry, -- optional, { x, y, width, height }
})

-- from a URL
local image = api.from_file("https://gist.ro/s/remote.png", {
  id = "my_image_id", -- optional, defaults to a random string
  window = 1000, -- optional, binds image to a window and its bounds
  buffer = 1000, -- optional, binds image to a buffer (paired with window binding)
  with_virtual_padding = true, -- optional, pads vertically with extmarks
  ...geometry, -- optional, { x, y, width, height }
})

image:render() -- render image
image:render(geometry) -- update image geometry and render it
image:clear()

image:move(x, y) -- move image
image:brightness(value) -- change brightness
image:saturation(value) -- change saturation
image:hue(value) -- change hue

Thanks

The story behind

Some years ago, I took a trip to Emacs land for a few months to learn Elisp and also research what Org-mode is, how it works, and look for features of interest for my workflow. I already had my own document syntax, albeit a very simple one, hacked together with Vimscript and a lot of Regex, and I was looking for ideas to improve it and build features on top of it.

I kept working on my syntax over the years, rewrote it many times, and today it's a proper Tree-sitter grammar, that I use for all my needs, from second braining to managing my tasks and time. It's helped me control my ADHD and be productive long before I was diagnosed, and it's still helping me be so much better than I'd be without it today.

One thing Emacs and Org-mode had that I liked was the ability to embed images in the document. Of course, we don't "need" it, but... I really wanted to have images in my documents.

About 3 years ago, I made my first attempt at solving this problem but didn't get far. If you have similar interests, you might have seen the vimage.nvim demo video on YouTube.

It was using ueberzug, which is now dead. It was buggy and didn't handle things like window-relative positioning, attaching images to windows and buffers, folds, etc.

Kitty's graphics protocol was a thing, but it didn't work with Tmux, which I'll probably use forever or replace it with something of my own.

Now, things have changed, and I'm happy to announce that rendering images using Kitty's graphics protocol from Neovim inside Tmux is working, and it's working pretty well!

My plan for this plugin is to support multiple backends, provide a few core integrations, and an easy-to-use API for other plugin authors to build on top of. There is a lot of logic that deals with positioning, cropping, bounds, folds, extmarks, etc. that is painful and unrealistic to write from scratch for every plugin that wants to use images.

More Repositories

1

tsdiagram

Create diagrams and plan your code with TypeScript.
TypeScript
382
star
2

vimage.nvim

Lua
74
star
3

devstream.tv

Devstream is a website that allows you to watch live developer streams.
Vue
57
star
4

openMou

markdown editor
JavaScript
31
star
5

playlister

Instantly create shareable playlists.
Vue
9
star
6

syslang

Syslang is an opinionated document syntax inspired by Org, Markdown, and HyperLists.
C
9
star
7

auto

Auto is a TypeScript-powered command-line automation tool.
TypeScript
8
star
8

config

My personal configuration - NixOS, Neovim, and all the good stuff.
Lua
6
star
9

work

Convenient wrapper over git-worktree, using fzf for switching between trees and branches.
Shell
6
star
10

promptpack

CLI tool for packing files into a prompt for LLM usage.
TypeScript
5
star
11

silabe.js

JavaScript syllabification library for the romanian language. (Librarie JavaScript pentru despartirea in silabe in limba romana.)
JavaScript
5
star
12

zodbus

ZodBus is a fully-typed event bus powered by Zod, with nested namespace & wildcard support and payload validation.
TypeScript
5
star
13

parcel-plugin-static

Parcel plugin for copying everything inside a directory to the bundle directory.
JavaScript
4
star
14

go2

go2 is a simple cli utility that allows you to index the directories you use often and create some kind of alias for them without polluting your shell's environment.
JavaScript
4
star
15

totomato

Totomato is a cross-platform minimalistic Pomodoro application.
Vue
3
star
16

benchmate

Small but mighty benchmarking library for JavaScript
TypeScript
3
star
17

time-tracker.nvim

Automatic project / file time tracker for Neovim.
Lua
3
star
18

statelift

Minimalist proxy-based state management library for React (experimental).
TypeScript
2
star
19

vue-starter

JavaScript
2
star
20

git-service

A web service that operates on top of a git repository, able to trigger operations and expose repository information.
Rust
2
star
21

scripts

Scripts and other small things that I use and decided to share for various reasons.
Shell
1
star
22

langtoolkit

TypeScript
1
star
23

linter

Notes and configurations for my linting setup.
TypeScript
1
star
24

remat

Simple reminder scheduling tool.
TypeScript
1
star
25

jslanscan

Browser-based LAN scanning library and application.
JavaScript
1
star
26

js-benchmark-tool-comparison

Benchmarking experiments
JavaScript
1
star
27

cphchat

school project
JavaScript
1
star