[HN Gopher] Lisp in Vim with Slimv or Vlime (2019)
___________________________________________________________________
Lisp in Vim with Slimv or Vlime (2019)
Author : Tomte
Score : 81 points
Date : 2021-12-19 07:51 UTC (15 hours ago)
(HTM) web link (susam.in)
(TXT) w3m dump (susam.in)
| clircle wrote:
| I wonder how this compares to my favorite combo, Emacs+Evil+Sly.
| User23 wrote:
| Me too. The primary use case for Emacs is writing Emacs init
| files[1], which are themselves a dialect of Lisp. Because of
| this, it's a solid tool out of the box for working with
| s-expressions. On the other hand, The vi family is historically
| very much a line oriented editor, so I'd be very interested in
| seeing a screencast of what an optimized vim CL workflow looks
| like.
|
| On a tangent, I feel the popularity of vi style bindings is
| more of an indictment of the standard substandard terminal
| based keyboards we use. Emacs bindings make a lot more sense
| ergonomically on a space cadet style keyboard where control and
| meta are comfortably pressed with the thumb.
|
| [1] Haha, only serious.
| clircle wrote:
| On your tangent, I use vi bindings _and_ map Ctrl to Alt, so
| that I can chord using only thumb.
| mixedmath wrote:
| I frequently hear about how amazing the experience of coding
| interactively with lisp is. I learned a bit of lisp (at the level
| of Practical Common Lisp) and scheme (via SICP) once upon a time,
| but I never coded interactively. Is there a way to demonstrate
| the power and utility to someone like me? Perhaps there are good
| videos or streams or materials specifically on or using the
| interactive development?
| Jach wrote:
| I'm a bit fond of the short 5-part series here
| https://malisper.me/debugging-lisp-part-1-recompilation/ that
| covers some of the debugging aspects, it's got some animated
| gifs. But there are several screencasts referenced on
| https://lisp-journey.gitlab.io/resources/ that may be worth
| exploring, though the fastest method is probably to just try
| building something yourself with the constraint that you never
| restart your Lisp image. Not too long ago I ported an old 2D
| maze generator I made in pygame to CL with SDL2, then while I
| had it up I decided I should add a solver to it, so ported an
| old A-star implementation I wrote in C++ and hooked up drawing
| (with dots) a path from any point to any other point. Then I
| wanted to draw a nicer sprite path that connected and handled
| corners by curving, so I swapped those in and then one-by-one
| recompiled the code with new ifs to handle each corner case to
| select the right path tile. Having to close and relaunch and
| reset the test points (and save and restore the maze seed)
| every time I made a code change would have been rather tedious.
|
| If you've worked in Java, download the JRebel extension for
| more complete hot-reloading support, and that'll give you an
| approximation of the interactive development experience. It's
| especially useful for web apps where you can change the code
| for an endpoint (or used by several endpoints, whatever) and
| can then just test it out with new requests, no need to restart
| the server.
| Jtsummers wrote:
| That first link is the one I was trying to recall. It's a
| good introduction to it.
|
| I had some fun doing "debugger driven development" with Lisp
| for the Synacor Challenge. Basically, you have to implement
| an interpreter/VM and there are some number of instructions
| (around 20?). Instead of trying to correctly implement all of
| them from the start, I had a core loop like this (not
| exactly, summarized): (loop with pc = 0
| for instruction = (aref memory pc) do (ecase
| instruction ))
|
| _ecase_ will signal an error whenever there is no matching
| case, taking you to the debugger. I read what instruction
| caused the error, checked the spec, implemented it, and
| resumed the program. Throw in a few asserts as sanity checks
| to complete the process. I don 't recall the instruction set,
| but suppose that "add a b c" means add the values in
| registers a and b and store in c, then maybe I'd do something
| like this: (10 ;; or whatever opcode meant
| ADD (... logic for addition ...) (assert (=
| c (+ a b))) ;; with whatever was needed to obtain these
| values correctly
|
| If I implemented something incorrectly, I just rewrote the
| logic, recompiled, and restarted again. It was an enjoyable
| way to build the system, but of course it also relied on
| having a fairly comprehensive notion of what the end result
| would be and I did have to refactor at the end. But I had
| some good test cases by that point so refactoring wasn't bad.
|
| I did the same thing for another project where I had a
| variety of input files that exercised various parts of the
| system and just continuously iterated until I got the
| expected result for an input relying on the debugger
| (triggered by _ecase_ and _assert_ and _(error
| 'unimplemented)_) to detect where I hadn't implemented
| something or had implemented it incorrectly or incompletely
| (like maybe one input exercises a particular edge case that
| others didn't). Once a file was properly processed, I wrote
| that up as a proper test, and moved on to the next file.
| Which then made the refactoring easy because I had a
| comprehensive test suite.
|
| http://challenge.synacor.com
| tempodox wrote:
| SBCL + vim + slimv is a really nice setup and I'm a happy user of
| that combination.
|
| I wrote myself a shell script that opens a new terminal tab
| running SBCL with the swank server, so the "connect" from vim is
| fully automated.
| imachine1980_ wrote:
| Can you Share it ?????
| tempodox wrote:
| Be advised, this is for macOS.
|
| There are two wrapper scripts, for Terminal (`ritt`) and for
| iTerm (`riitt`), in addition to the `swank-lisp` script.
| Choose one of the wrapper scripts for your use case.
|
| The relevant lines in ~/.vimrc, adjust your `sbcl` path:
| let g:slimv_swank_cmd = '!ritt swank-lisp -d "' . getcwd() .
| '"'
| let g:slimv_lisp = '/usr/local/bin/sbcl' let
| g:slimv_impl = 'sbcl' let g:slimv_ctags = 'ctags'
|
| `ritt` ("run in Terminal tab") for use with Terminal.app:
| #!/usr/bin/env osascript
| on run arglist if (count of arglist) > 0 then
| -- The command to run is built from blank-separated script
| arguments. set text item delimiters to {" "}
| set theCommand to arglist as string tell
| application "Terminal" activate
| -- Make a new Terminal tab just like the current one.
| tell application "System Events" to keystroke "t" using
| {command down} set newTab to the last tab
| of front window -- Run the command in the
| new tab. do script theCommand in newTab
| end tell end if -- Try to cause a minimum
| of disturbance in the calling environment instead of
| outputting random AppleScript values. return ""
| end
|
| This is `riitt` ("run in iTerm tab") for use with iTerm.app:
| #!/usr/bin/env osascript
| on run arglist if (count of arglist) > 0 then
| -- The command to run is built from blank-separated script
| arguments. set text item delimiters to {" "}
| set theCommand to arglist as string tell
| application "iTerm" activate
| -- Make a new Terminal tab just like the current one.
| tell application "System Events" to keystroke "t" using
| {command down} set newTab to the last tab
| of front window -- Run the command in the
| new tab. write (current session in newTab)
| text theCommand end tell end if
| -- Try to cause a minimum of disturbance in the calling
| environment instead of outputting random AppleScript values.
| return "" end
|
| And here the `swank-lisp` script (adjust the `swankdir` to
| your install location): #!/bin/bash
| swankdir="${HOME}/.vim/bundle/slimv.git/slime"
| self=$(basename "$0") umask 022 set -u
| Usage() { cat <<EOD >&2 Usage: $self
| [-d <working-dir>] EOD exit 1 }
| # Argument Scanning if [ "$*" = "--help" ] then
| Usage fi devDir="${HOME}/Develop/Lisp"
| while getopts "d:X" opt do case "$opt" in
| (d) if [ -n "$OPTARG" ] then
| devDir="$OPTARG" fi ;;
| (X) set -x ;; (?) #
| Unknown option Usage ;;
| esac done # Shift away parsed option flags
| shift $((OPTIND - 1)) # Change to user's
| development directory, so files are easier to locate.
| cd "$devDir" || exit $? sbcl --dynamic-space-size
| 16384 --load "${swankdir}/start-swank.lisp" echo #
| Newline before next shell prompt.
| jhgb wrote:
| I wonder if Neovim wouldn't be an even better option for this.
| Isn't slimv written in that dreadful extension language for
| Vim? I may have seen it years ago and don't remember anymore.
| ByteJockey wrote:
| Modern vim also has python, perl, ruby, and lua support in
| addition to vimscript (taking a quick look at the features in
| my local vim).
|
| Though the neovim community does go pretty heavy towards lua
| compared to the traditional vim community.
| jhgb wrote:
| I know it does, but it's up to the extension's writer to
| use them properly.
|
| > the neovim community does go pretty heavy towards lua
|
| And that's why I like them.
| ByteJockey wrote:
| Fair. My point was more that you didn't have to make a
| non-portable extension just to use lua.
| ViViDboarder wrote:
| Fennel lisp is pretty popular in the Neovim community,
| actually.
| vindarel wrote:
| and the necessary addition: you can use VSCode or Atom or Sublime
| or Jupyter notebooks with good to very good plugins for CL
| development, you are not tied to Emacs or Vim (anymore) \o/
| https://lispcookbook.github.io/cl-cookbook/editor-support.ht... &
| https://lispcookbook.github.io/cl-cookbook/vscode-alive.html
| alekq wrote:
| The same author also made Emacs4CL - minimal configuration of
| stock/vanilla Emacs for Common Lisp development:
|
| https://github.com/susam/emacs4cl
| Jach wrote:
| I've been really happy with slimv. There are a few things missing
| that I'd like to have were I to find myself working on a really
| large program with a bunch of other programmers, though I suspect
| the commercial Lisps offer a good approximation. Besides the
| trivial things like more auto-refactoring tools (thanks to cross-
| referencing I can at least get a list of all the locations
| something is used and jump to edit them one by one if necessary)
| and project organization tools (I've started using @export from
| https://github.com/m2ym/cl-annot rather than going back to my
| package definition to keep adding symbols to the export list) I'd
| like a better line debugger. It hasn't been a hurdle so far
| because what's there is good enough (as the article describes,
| when you hit the debugger you get your stack, you can inspect
| stuff in the frame, you can recompile and then restart
| computation from a frame instead of aborting the whole thing). If
| your declaim settings are right you can also step your code and
| so on within vim but it's kind of clunky, I'd rather launch a
| dedicated GUI that's at least as nice as the old Insight GDB
| wrapper. When inspecting complex data I've started to use the
| McCLIM app Clouseau:
| https://github.com/McCLIM/McCLIM/tree/master/Apps/Clouseau I
| bound ,ci to call (clouseau:inspect) on the symbol and that
| launches a nice enough GUI to explore it. (Repeated periodically
| in a thread also serves as a poor man's variable watcher...) A
| handful of other vim plugins make the full experience even better
| (even when not writing lisp).
|
| It's been pretty amusing watching the LSP landscape evolve for
| other languages, it's almost like swank for CL. But it's rather
| nice to have the server be embedded in the process itself. On my
| personal web server I have a compiled lisp binary running, but I
| shipped it with swank listening on a local port, so if I want to
| change something without rebuilding and redeploying I can just
| SSH in while forwarding port 4005, connect to the lisp image with
| my local editor, and recompile functions or whatever. At my last
| job I also inserted ABCL into the huge Java app on my dev box and
| had it start a swank server, letting me connect with vim and mess
| around -- it was mostly useful for quickly launching system tests
| which otherwise had a dedicated clunky browser UI, and writing
| some code to quickly extract or insert data. I had some designs
| to write some webdriver tests in Lisp and demo how the debugging
| experience when one fails can be much better (not having to
| restart the whole flow because a UI element changed its class
| name or whatever and threw an exception) so as to introduce the
| language to the broader company officially (and hopefully push
| for officially sanctioned use), but never got around to it before
| I left.
| jfvinueza wrote:
| I've been using Conjure (https://github.com/Olical/conjure) for
| Clojure and Janet and it's been working wonders.
| ARandomerDude wrote:
| Came here to say the same thing. Conjure is amazing. I use
| Conjure + ShadowCljs for React and React Native development and
| couldn't be happier.
| lc9er wrote:
| I use Conjure for writing Fennel, which in turn can be used to
| customize nvim. It's a pretty great plugin.
| mark_l_watson wrote:
| My manager at my last job was a real wizard with Vim+Common Lisp,
| he was much more facile than I am with Emacs+CL.
|
| To be honest, when I am reading other people's Common Lisp code,
| if there are many files in their projects, I prefer VSCode. And
| for my own hacking joy I like LispWorks, usually using the IDE,
| but sometimes using Emacs.
| atdt wrote:
| If you're using emacs as an IDE, what advantage do you get from
| using LispWorks over the free alternatives like SBCL?
| mark_l_watson wrote:
| LispWorks is a little more facile for me, I don't think about
| the IDE, just think about the task on hand.
|
| It is the same way with Clojure: IntelliJ+Cursive is just
| more facile for me than with Emacs.
___________________________________________________________________
(page generated 2021-12-19 23:01 UTC)