cursive 2025-11-12

FYI, while pairing, my boss told me “you don’t know how painful it is watching you manually handle imports”. 😞 anyone have tricks that don’t involve using namespace aliases? or is anyone using clojure-lsp to sidecar imports somehow?

Cursive is very good at importing symbols now. Typing a var name from another namespace brings up autocomplete, and hitting enter adds a :refer. And when pasting code, any unresolved vars have a context menu for importing them as well. Been using it for a week, no complaints! Thank you @cfleming

🎉 1

thanks for breaking that down @onetom, very helpful

@cfleming > I'm also curious, what is the better alternative? What do other editors (I'm assuming CIDER) do for this? My boss shared this with me today: if we have a function round2 we want to auto-import, he just types the symbol and runs cljr-add-missing-libspec and it adds the namespace reference. (and it presents a list of namespaces to choose from if it’s a duplicate name) https://github.com/clojure-emacs/clj-refactor.el/wiki/cljr-add-missing-libspec

you can also make up an alias like asdf/round2 and it will auto-alias the namespace that has round2 even if you’ve never used it

Great, glad it's working well! Thanks for letting me know.

I think the main thing I do is: 1. cmd+opt+o to find a symbol, press enter 2. copy the symbol there, scroll up to the namespace form 3. paste the symbol after the namespace name 4. copy both the namespace and symbol name together, undo the paste 5. cmd+e enter to go back to the previous namespace where I want to import it 6. scroll up to the namespace form, paste the namespace and name there. 7. wrap it in square brackets and insert :refer and wrap the symbol in square brackets too

I don’t understand. You don’t use namespace aliases? You fully qualify every symbol?

a namespace alias is created when you do [foo.bar :as f]. we have a lot of namespaces that we don’t alias, so it requires [foo.bar :refer [my-func]], so no we don’t fully qualify the symbols, we import them that way, but can’t automate that

Ah I gotcha. Huh I never use refer. And yeah, if that’s what you want, I dunno how tooling is supposed to automate it.

interesting, I didn’t know refer was rarely used

I just dunno the upside of it. If you use the ns often you can make it one letter, so 2 characters to type. In exchange you get a visual cue of its origin and tooling can auto import.

lemme count how many namespaces we have lol

1

Ime you can keep the aliases very short as long as you use it consistently across the codebase. Mine are mostly 1-3 chars.

636 namespaces, and 213k lines of code

I would think using aliases would sig help manage that. Otherwise you gotta make sure each symbol name is unique, yeah?

fwiw, I seem to only use :refer when using clojure.test

Is it because you have to manually add the imports? For me only a few of them work reliably, like (str/blank? and it suggests adding [clojure.string :as str. Most of the time I have to add them manually, but I'm on an older build now.

https://cursive-ide.com/userguide/editing.html > When you complete the name of a var using a namespace alias that isn't currently require'd, Cursive will automatically add a require to your ns form for you. Similarly, if Cursive sees an aliased var reference that it can't currently resolve it will prompt you with options to require it. I use this all of the time, but the mechanism only supports requires with aliases. It also only works with aliases you've already used in your project. So if you have [my-app.foo :as foo] in one namespace, then in another namespace Cursive is going to suggest Vars from foo when you start typing (foo/, and automatically require [my-app.foo :as foo].

➕ 2

I follow Sierra's :require :refer rule - disallowing :refer except for clojure.test, lazytest.core and the like. I find that with :refer a certain unease creeps in - I don't know exactly where a symbol is defined just by looking at it.

➕ 1

I'm planning to add refer support, let me see if I can get that in soon.

> my boss told me “you don’t know how painful it is watching you manually handle imports”. I'm also curious, what is the better alternative? What do other editors (I'm assuming CIDER) do for this?

1

hmm, :refer is everywhere in our codebase, good to know that it isn’t encouraged

and oops, clojure-lsp doesn’t actually auto-import them either

closest thing it does is to auto-import java classes, but not clojure symbols

but yeah it makes sense not to automate something that no one does, I thought it was common

I'm definitely going to do this, because I use it often enough that it would be useful.

❤️ 4

I suspect that that's definitely a suggestion rather than a rule, I certainly treat it that way. I don't want to be using test/deftest all the time.

➕ 1

yeah I suppose refer is still good for commonly used lib functions as recommended, so it would still be useful there (and would be an additional help to those of us who break the suggestion)

metabase probably follows these conventions, was interesting looking at their :refer forms

Yeah, it's officially frowned upon but I think a lot of people use it in practice.

fwiw, these are the main ideas that come to mind: 1. auto-importing from cmd+opt+o might be the most direct 2. auto-completing symbols when typing inside :refer [...] would also go a long way

thanks Colin

My plan was to do the same as with the aliases - as part of normal autocomplete, show symbols that have been referred in other parts of the project and dependencies, and offer those with a tail text in the completion indicating what will happen. That might be too many symbols, or too many irrelevant symbols - if so, then my plan was to hook that into the second press of auto complete, which is used a lot in e.g. Java for a more extensive search - I haven't used that for anything in Cursive yet.

👍 2

• using :refer on most frequently used lib namespaces definitely makes sense • even when using an ns alias, it looks stupid to write diff/diff, rmap/rmap, pp/pprint, coz it looks like stuttering, so i project-wide text search for :as pp, turn on showing the context, copy the [clojure.pprint :as pp] line, then paste into the current (ns ... (:require ...)) • to avoid the stuttering issue, i always try to name the public vars in a way they make sense, when read together w the namespace alias. e.g. xxx.source.xero/sync, instead of xxx.source.xero/sync-xero-source, even though it would be more readable while editing the ns itself and requires a :refer-clojure exclusion. it also leads to multiple sync functions, which is a bit annoying, while using symbol search. i wish i could just refine the results, like in orderless, so narrow them based on the namespace part. • for 2-3 nses, like [our.forked.rmap :as rmap :refer [ref rmap] :rename {ref $}], i have a 2-4 letter live template, which expands to this line, though i still have to navigate to the top of the file, use the live template, then go back to the last edit location with cmd-shift-backspace • we have a common NS, which is required in most other NSes, because it's like clojure.core extension, but i don't want to patch clojure.core, because that would introduce NS-load-order issues. for that we just type gc<tab> which expands to [gini.common :refer :all] • most other things are aliased, BUT preferably with a single-segment kebab-cased symbol, with some words reversed to better match english grammar, e.g. [ginoco.source.quickbooks :as qb-source] • we try to keep these require clauses consistent, so cursive can unambiguously auto-insert them during auto-completion or using the opt-enter intention as a result most of the time we just type, e.g. qb-source/<ctrl-opt-i> (mapped to code completion/`basic` action) to get a selection of its vars. once we make our selection, cursive inserts the corresponding :require line by itself.