Lisp Flavoured Rust

TLDR: Is there some hack that provides lisp-syntax and rust semantics?

Long Version:

I have been using Rust for a few months now, and have worked through "Rust by Example."

One thing that I really miss -- is paredit. I'm currently using IntelliJ, and alot of editing ops ends up resulting in unbalanced ({{ ]}) that then needs to be manually balanced. With paredit, editing seems to take no conscious thought, wherewas with IntelliJ/Rust, I'm constantly context switching between
"what code do I want to write"
"how do I make this edit happen?"
"wtf??? where is the unblanced $R*@* ({{}]) ?"

One concrete example is:
foo.bar(2, 3, 4) vs (foo.bar 2 3 4) .

In the latter, I navigate to the '(', hit d%, and I have deleted he expression, and can put it elsewhere as I wish. In the former, I still haven't found a nice way of cutting the entire expr.

I realize this sounds heretical, but is there any project that provides a thin layer of Lisp taht translates to Rust?

It may be small help, but d% does work that way in vi, if you navigate to the f instead of the (. I do this regularly. You don't have to be on the bracket to jump to the matching bracket because it will seek forward (within the same line) automatically.

I find vi keybindings in most IDEs to be hit or miss, but perhaps your IntelliJ setup works the same way?

@trentj: But it won't work on something like x.foo().bar(23);

I still haven’t found a nice way of cutting the entire expr.

There's one: extend selection. If you use Windows or Linux, it's bound to ctrl+w, if you use MacOS, it's something less convenient, ⌥↑.

Extend selection works by selecting larger syntactic nodes. In a sense, it is paredit, extended to work with arbitrary syntax, and not just well-balanced parenthesis.

So, for "delete foo.bar(2, 3, 4)", you need to place cursor anywhere inside the expresion, press ctrl+w a couple of times, and then ctrl+x. This way, you can also move the expression elsewhere.

There's also a quick way to select multiline blocks, like a foo function in this snippet:

impl S {
    fn foo() {
        // lots of code
    }
}

Place a caret at the beginning of the fn foo line, and press ctrl+W: it'll select the syntactic construct that starts at this line.

You can also use ctrl+w for navigation: say, you are at the bottom of the large impl block, and you want to go to the beginning on the block: you press ctrl+w a couple of times to select the whole block, and then press Left to remove the selection and simultaneously place the cursor at the start of it.

Ctrl+w also works with multiple cursors: you select stuff with ctrl+w, then you press alt+j several times to select all occurrences, then you press ctrl+w couple more times (it works independently for each selection), and then do some refactoring.

It's curios that up until recently, only IntelliJ implemented this very useful feature. However recently Atom also has gained this ability: Atom 1.32 | Atom Blog.

I've also have written a quick hack for Emacs to do this (which can be extended to vim as well): Semantic aware extend selection for Emacs (and Vim, if **you** write vimscript ;))

It also was one of the first features, added to rust-analyzer: extend selection via LSP · rust-lang/rust-analyzer@26262aa · GitHub

1 Like

I'm using IntelliJ + VIM Plugin. Is there a "Action" I can bind to a Vim hotkey? (For extend selection).

:actionlist extend

gives me

EditorTextEnd
EditorTextEndWithSelection

Neither which seems to be the extend selection we want.

I think the action name is EditorSelectWord, though there are some know problems when using it with IDEA Vim: https://youtrack.jetbrains.com/issue/VIM-510

Since you use vim, this problem is more or an editor trick than the syntax of a language (S-expression that you want).

forward deleting:
d2f) or d$
backwards deleting:
v^x and v?x<CR>x
are enough for most of your cases.

d$/y$ are rarely the right answer as I often want an arg of a function call or some expression that is a multi line chain

Also, what I really want is not to have to think rather than other vim shortcuts. One of my favorite paredit navigation techniques in emacs/vim-emulation mode is:

h -- outer sexp
l -- inner sexp
j/k -- next/prev sexp at same level
y% -- yanks entire sexp

The other nice thing about paredit editing is that you can use ace jump on ()'s, -- so you can jump to arbitrary ( or ) within 1-2 key strokes. This allows editing of the form where you jump somwhere on the screen, grab a sexp, jump else where, paste it there, and so forth.

It's not clear to me I can get anywhere this level of fluid editing with IdeaVIM + Rust syntax.

Also, to be clear, I'm a big fan of rust semantics, I just like the uniformity of () syntax.

Now I recall the problem: you have to switch to visual mode before invoking structural selection.

you can use ace jump on ()'s

There are several ace jump implementations for IDEA, but, surprisingly, this lesser know one is the best: https://plugins.jetbrains.com/plugin/9803-acejump-lite, at least to my personal taste.

1 Like

You may also be interested in https://github.com/carp-lang/Carp/blob/master/docs/LanguageGuide.md

2 Likes

@steveklabnik : Carp, as of today, doesn't seem production ready yet. I'm really looking for a thin syntactical layer over Rust so I get all the engineering of Rust for free.

1 Like