[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)