sodapopcan

sodapopcan

Mixer.vim - (Classic) Vim plugin providing text objects and niceties for working with Mix projects

I’ve heard that if you’re not embarrassed by v1 of your product Vim plugin then you’ve released too late.

I’ve been sitting on this the past couple of months and while there is plenty I still have planned (a good amount of stuff is in the works just not in this version), I decided I should cut a release so the few people who will be interested can start using what’s available.

So, I’m happy to announce mixer.vim. Mixer is somewhat similar to elixir-tools.nvim only it’s written in vim9script so that Vim users can have nice Elixir things too. It assumes you have elixir.vim installed.

Here is the features section of the README for posterity:

Features

  • Text objects

    • ad/id - Any macro with a do block. Works on user-defined macros as well as keyword syntax (though the latter needs a little improvement).
    • aD - Like ad but include any assignment and/or attached comments (iD exists for convenience but is identical to id).
    • af/if - A function/macro definition
    • aF - Like af but include all heads, docs, annotations, attr and slot declarations, and even do_ prefixed versions (iF exists for convenience but is identical to if).
    • iS/aS- A sigil
    • im/am- A map or struct
    • iM/aM- A module
    • ic/ac- A comment or documentation
  • Conveniences

    • 'commentstring' is dynamically set in embedded HEEx/Surface.
    • matchit works in embedded HEEx/Surface templates.
    • Automatically sets :compiler if the appropriate plugin is found.
    • [experimental] Remaps ctrl-] in templates that will jump to a phx-hook definition (it’s pretty smart about it) or event handlers on other phx- attributes. Unfortunately this has a dependency on git-grep atm.
  • Commands

    • :Mix runs a mix command with autocomplete. Uses dispatch, neomake, asyncrun, or asyncdo if available.
    • :Deps doesn’t just wrap Mix deps but adds functionality like dynamically adding packages under your cursor (:Deps add floki, for example) or jumping to your deps
      function no matter what you’ve called it (:Deps with no args).
    • :Gen is a unified command for running gen tasks (with autocomplete!), eg:
      • :Gen migration add_name_to_users
      • :Gen live Accounts User users name:string age:integer
    • :IEx starts a :term window running iex. Within a mix project it will assume -S mix. Use :IEx! to get a plain session within a mix project.

:help mixer has more!

Most Liked

ca1989

ca1989

Thank you for the effort! It’s very appreciated

sodapopcan

sodapopcan

The :IEx command now includes a hacky “connected REPL” or “Discount Connected REPL” as I like to call it. You could also say it’s a “We have connected REPLs at home” if you’re into that meme. I wouldn’t go so far as to say it’s the GoBots of connected REPLs because GoBots were cooler than this.

In short, you can start an iex session in a Vim :term and every time you save the buffer it will load the changes into the terminal. It even works with parts of a buffer via ranges/counts/visual selection.

In any event, it’s hard to describe so I made a short-ish screencast. It’s my first one ever so be nice if you choose to watch it… or don’t be nice, either is cool.

sodapopcan

sodapopcan

I haven’t given an update on this project in a while so figured I’d share a newer thing. I’ve only been using it a week so it’s not super polished yet.

I’ve been playing around with htmx lately which means I’ve been using classic controllers for the first time in a while which finally gave me the push to implement the :R command. If you are unfamiliar, this is similar to rails.vim’s :R here for hopping to “related” files (and almost entirely different than projectionist’s idea of “related”).

In a nutshell:

  • Jump from controller to heex/template (context aware based cursor position) - this works whether you use dedicated heex files or components in the HTML module. Outside of a controller action it will jump to the HTML/view module
  • Jump to and from HEEx in a LiveView/Component/Hologram/Surface (this is implemented with the jumplist)
  • Jump from schema to context.
  • Jump from context to schema (context aware based on function name)—YMMV on this one as it uses some pretty hilarious brute forcing to find a file. Still tweaking it.
  • Jump between Router and Endpoint.
  • Go back one migration.
  • There are a few more places it works and more coming.

This is currently non-configurable since for all I know I’m the only one who uses this plugin.

I’ve also added some experimental (and so far undocumented) general Projectionist support (to try it out add let g:mixer_enable_projections = v:true to your vimrc). I’m still tweaking it but the big idea here is that it uses its own heuristics (not to be confused with projectionist’s codified heuristics) to determine your project’s layout and defines projections based on this. There is a lot of detail here so I won’t go into it but briefly:

  • Edomain - Edit a file in lib/my_app or lib/core.
  • Eweb - Edit a file in lib/my_app_web or lib/web.
  • Emigration - With no arguments will jump to the latest migration.
  • a whole host of others

I’m still working on this and I may end up implementing my own version as Projectionist isn’t too well suited for typical Phoenix project layouts (if there is indeed such a thing).

Where Next?

Popular in Announcing Top

zachdaniel
Ash Framework 3.0: Official Release! I’m here with the fine folks at Gig City Elixir, pushing the button live on stage :sunglasses: T...
New
isaias-dias-machado
IEx’s h macro is great but it lacks a pager, so I built a small tool that caches documentation and lets you fuzzy search through it in yo...
New
hauleth
PhoenixBakery is library for Phoenix 1.6 (and later) that provides modules implementing Phoenix.Digester.Compressor. There are currently ...
New
shahryarjb
The Chelekom project is a library of Phoenix and LiveView components generated via Mix tasks to fit developer needs seamlessly. One of i...
New
kzemek
I’ve recently released v0.2.0 of my Python interop library, Snex. This version rolls up all work-in-progress improvements that have been...
New
garrison
Hobbes is a scalable, fault-tolerant transactional record store written in Elixir. Hobbes is designed to be: Scalable - Hobbes can sha...
New
lucaong
CubDB is an embedded database written in pure Elixir, designed for robustness and minimal use of resources. It strives to be as developer...
New
rms.mrcs
Hi there :waving_hand: Just dropping by to share PhonixLiveState, a lib I’ve just published. It’s still VERY RAW, but already in a reas...
New
murrgelb
Efx is a library to define and test side effects declaratively. It is basically a very focused mocking framework, reducing implementation...
New
fhunleth
Elixir Circuits is a set of libraries for interacting with hardware. We previously announced Circuits.UART, and now we’re ready to announ...
New

Other popular topics Top

lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement