[HN Gopher] Bash-LSP: A language server for Bash
       ___________________________________________________________________
        
       Bash-LSP: A language server for Bash
        
       Author : ducktective
       Score  : 121 points
       Date   : 2021-04-01 16:59 UTC (6 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | alsetmusic wrote:
       | I clicked through to the point of skimming the documentation for
       | tree-sitter before giving up on understanding this quickly. There
       | are too many components that I haven't seen for me to extrapolate
       | out and get to what this does in general terms.
       | 
       | Could anyone with more knowledge please explain what this is and
       | how one might utilize it? Fwiw, I'm deeply familiar with Bash; I
       | just don't recognize the rest.
        
         | sabellito wrote:
         | Language Servers are pieces of software that implement IDE-like
         | features (like go to definition, find usages, call-hierarchy,
         | rename method, etc) for a given language in an editor-agnostic
         | way.
         | 
         | With that, any editor that supports Language Servers can use
         | those to provide better support to a language without
         | implementing any details.
         | 
         | In this case, you can see some of the supported editors in the
         | README itself: https://github.com/bash-lsp/bash-language-
         | server#clients
        
         | zeusk wrote:
         | LSP is a protocol for IDE/editors to analyze code files and
         | provide functionality like intelligible code search
         | (definition, references etc)
        
         | [deleted]
        
         | adonovan wrote:
         | Language Server Protocol (LSP) is a standard protocol for
         | "plain old" editors (clients) to make RPCs to local processes
         | that understand the syntax, references, and types of a
         | particular programming language (servers). This reduces the
         | work to support M servers and N clients to M+N, whereas the
         | traditional monolithic approach required M*N integrations. This
         | particular project adds a server for Bash support.
        
         | JoBrad wrote:
         | To add to the other comments, VSCode docs has a good overview
         | of the motivation and usage of a Language Server.
         | https://code.visualstudio.com/api/language-extensions/langua...
        
         | widdershins wrote:
         | The other comments explained what LSP is - I'll explain what
         | tree-sitter is. It's a clever parser that is very fast when it
         | comes to reparsing a slightly changed file (it's
         | 'incremental'). It's also very good at handling errors and
         | continuing to parse your file.
         | 
         | You write a grammar in json and it gets compiled to a shared
         | library via C.
        
       | brendanfalk wrote:
       | This is really cool and having spoken with the lead dev, Kenneth,
       | I trust that this will continue to be well supported.
       | 
       | This is built on tree-sitter, but there are a couple of other
       | interesting shell parser projects:                 *
       | https://github.com/mvdan/sh       *
       | https://github.com/koalaman/shellcheck
       | 
       | At Fig (withfig.com), we had to write a bash parser from scratch.
       | These projects all work well in the IDE context, but in a repl
       | environment (ie when typing in your terminal) they don't support
       | incomplete commands very well. e.g if I type `echo "$(` the above
       | parsers will break as the double quote and parentheses are not
       | closed.
        
         | macrael wrote:
         | We use shellcheck all the time. Any real differences in between
         | these three parsers?
        
           | brendanfalk wrote:
           | All three are good, well maintained projects.
           | 
           | Tree-sitter is more general: it aims to provide support for
           | many languages and so its bash support is lacking a little.
           | But it's very fast. It's designed for IDEs (hence why bash-
           | lsp is using it). It caches its results and only re-parses on
           | newly changed code blocks.
           | 
           | sh by mvdan and shellcheck are both built specifically for
           | the shell. They both have really robust grammar. shellcheck
           | is great for error handling. sh is great for building ASTs
           | (it's more of a true parser)
           | 
           | As always, it depends on your use case. If you need a
           | descriptive summary of errors / warnings in a shell script
           | and performance isn't crucial, use shellcheck. If you need a
           | really robust parser and AST output, use sh. If performance
           | is crucial and/or you eventually want to support different
           | languages, use tree-sitter.
           | 
           | Please feel free to jump in if I am wrong here!
        
             | bewuethr wrote:
             | To me, the main value of sh is shfmt - I use it like gofmt
             | and never have to think about formatting again. It also
             | integrates with GitHub's super-linter, where you can have
             | your preferences in an .editorconfig file and then enforce
             | them automatically.
        
         | pforret wrote:
         | I'm really interested in fig. I develop lots of bash scripts
         | and I would love to see how new scripts can also from fig
         | autocompletion.
        
           | brendanfalk wrote:
           | Cool! Some of the biggest problems we have seen are:
           | * scripts being poorly documented: what's the point of having
           | a script if no one knows how to use it       * scripts going
           | stale: often built by one person / an infra team. When they
           | break, no one knows how to fix them       * creating scripts:
           | bash isn't the most popular language these days, but it's
           | still supported just about everywhere. How can we make
           | building them easier and faster but still just as powerful
        
       | usbline wrote:
       | Development tools like this with an obscene amount of
       | dependencies, not to mention multi-language dependencies, is
       | extremely worrying and irresponsible for the future of software
       | development. Especially since they're not even native to bash's
       | environment! If you would have told me 5 years ago I'd need to
       | install node and typescript in order to get auto completion for
       | bash, I'd have called you crazy. Yet here we are.
        
         | [deleted]
        
         | brundolf wrote:
         | I look forward to your dependency-free implementation!
        
         | tester756 wrote:
         | on the other hand...
         | 
         | software is so modular nowadays that you can write language-
         | server in C#, for an Typescript IDE/Editor that helps you to
         | write Bash scripts for Linux.
        
         | methyl wrote:
         | > Development tools like this with an obscene amount of
         | dependencies, not to mention multi-language dependencies, is
         | extremely worrying and irresponsible for the future of software
         | development
         | 
         | Care to elaborate why?
        
           | usbline wrote:
           | >Care to elaborate why?
           | 
           | Not particularly, since it'll only fall on deaf ears
           | considering HN's demographic.
        
             | methyl wrote:
             | So you want to tell, it's better to have no tool at all
             | (given pre-tree-sitter Bash LSP doesn't exist), than to
             | have a tool with a lot of dependencies? I get that some may
             | avoid having huge number of dependencies on production, but
             | when it comes to local development tools, I couldn't care
             | less. It's 2021, I can buy 1 TB SSD for less than 100
             | bucks.
        
               | kazinator wrote:
               | You maybe able to buy a TB SSD for < $100, but you can't
               | make sense of the ball of mud that is on it.
        
             | ggregoire wrote:
             | Curious what you think HN's demographic is. Most people on
             | that site probably agree with you, although "extremely
             | worrying and irresponsible for the future of software
             | development" is obviously quite exaggerated.
        
         | nicoburns wrote:
         | What do you expect a bash language server to be written in?
         | Bash?
        
           | mdip wrote:
           | You said it, sarcastically, but that didn't mean I didn't
           | think it. At first blush it sounds a little crazy, but the
           | more I think about it...
           | 
           | Consider my problem: I use `zsh` and have created, collected
           | and organized a large number of completions which I
           | synchronize among several workstations. It _frustrates me to
           | no end_ that I cannot take advantage of these completions in
           | very many other convenient places, like VSCode[0]. The
           | benefit of writing it in `zsh` (I can 't speak for bash) is
           | that seems like it'd be pretty simple to wire up the LSB as a
           | sort of "completions proxy" that simply takes the inputs,
           | passes them to a completion script, parses the output and
           | formats it in the appropriate JSON response. The utility of
           | being able to have a single script (or set of scripts) that I
           | can include in my shared profile directory which will run and
           | handle a `zsh` LSB implementation on-demand (i.e. doesn't
           | need installing, sits in my scripts directory and runs
           | everywhere) would be a huge feature.
           | 
           | This will speak to my ignorance, but can you host a web
           | server (in a manner that can be consumed) from just bash and
           | a lean environment[1]? Could you host an LSP without one
           | (i.e. is there enough to use a socket and would it be enough
           | to point it at the right place/scheme?). I believe there are
           | `zsh` extensions which can facilitate some/all of this, but
           | I'm not sure if it would work out of the box. The downside to
           | developing it in `zsh`, other than the language itself[2] is
           | performance. Both of those, assuming "the hosting/serving"
           | can be handled easily, don't represent big problems, maybe
           | they are. But performance and the language should be up to
           | what remains outside of that.
           | 
           | [0] I had `nvim` set up correctly, once to work with
           | completion scripts and was able to translate that into VSCode
           | doing the same, about two years ago. I'm still not fully
           | convinced I didn't just dream this up because the few times
           | I've looked into it, since, I've gotten nowhere (admittedly,
           | I've put little effort into researching).
           | 
           | [1] I'm thinking 'busybox', minimal gnu-related things,
           | ideally requiring as little as possible beyond a relatively
           | recent version of `bash` so that "if it's got bash, I can use
           | it".
           | 
           | [2] I use `zsh` because it's easier for me to write things in
           | it than `bash`, and at times it can be fun. But there's a
           | reason we don't build solutions using it.
           | 
           | [3] Everything's a string...
        
         | mikewhy wrote:
         | > If you would have told me 5 years ago I'd need to install
         | node and typescript in order to get auto completion for bash,
         | I'd have called you crazy.
         | 
         | This line right here means there's no runtime dependencies
         | https://github.com/bash-lsp/bash-language-server/blob/fa5a65...
         | 
         | edit: turns out there are runtime dependencies (see child
         | comments). Still, typescript is not one of them.
        
           | dvlsg wrote:
           | I think there are runtime dependencies, just not at the root
           | level of the repo.
           | 
           | https://github.com/bash-lsp/bash-language-
           | server/blob/fa5a65...
        
             | mikewhy wrote:
             | Ah, nice catch. I'll revise my comment.
        
           | usbline wrote:
           | Node is not a runtime now? :)
        
             | mikewhy wrote:
             | No more than Bash :):):)
             | 
             | And either way, you don't need TypeScript to run this
             | language server. You just need node. If you're not happy
             | with that, well, consider this repo a reference and get
             | cracking.
        
           | kazinator wrote:
           | Doesn't TypeScript work by transpilation to JavaScript? In
           | which case, it is _never_ a run-time dependency; JavaScript
           | is.
        
         | nikolay wrote:
         | YARGM (Yet Another Rube Goldberg Machine)
        
         | TechBro8615 wrote:
         | You can always tell who hasn't used a tool because they leave
         | comments like this. Same thing with complaints about
         | node_modules. Anyone who's actually worked with frontend
         | tooling knows it's light years ahead of the tooling in most
         | backend languages.
         | 
         | The developer experience out of the box with TypeScript +
         | VSCode + Next.js is 1000x better than any stack I've ever
         | worked with in Python, for example. So what if you need to pull
         | in some dependencies? At least I don't need to figure out what
         | the best way to setup a Python environment is this month.
         | 
         | (In fact, the current Python package manager du juor, Poetry,
         | took most of its ideas from what Yarn implemented five years
         | ago.)
         | 
         | And what's this about being irresponsible? You can easily pin
         | your dependencies, use a lockfile, and even bake the cache into
         | your Docker images. There's no reason you can't have a program
         | that will run the same in two years as it does now. And setting
         | that up is a lot easier than it is with other languages.
        
           | tasogare wrote:
           | > Anyone who's actually worked with frontend tooling knows
           | it's light years ahead of the tooling in most backend
           | languages. The developer experience out of the box with
           | TypeScript + VSCode + Next.js is 1000x better than any stack
           | 
           | You should practice your April fools jokes to be less
           | obvious, that post is not gonna make it.
        
           | mdip wrote:
           | I don't know that I'd agree with all of those statements, but
           | my expertise lies in C#, with a bit of
           | TypeScript/JavaScript/Front-end Web thrown in from time to
           | time. I used to write a lot in C++, have dabbled in C...
           | 
           | The reason I don't write _everything_ in TypeScript has
           | nothing to do with TypeScript. Language-wise, it is my
           | favorite experience, hands down. I can express things in a
           | type-safe, strict manner, and do things generically that
           | simply cannot be done _outside_ of dynamic languages, while
           | still gaining the benefits of a statically typed language.
           | 
           | Not taking node into account[0], TypeScript on its own is my
           | favorite language and it's _not_ the one I write software in
           | every day. While I agree with your arguments around pinning
           | and such, node is a bit of a victim of its own success and
           | suffers from dependency-hell in a way that is truly unique
           | and interesting all on its own. The only way to be certain
           | that code is good is if you write it, barring that ... a
           | trusted, supported third-party for the important things, and
           | inspect the rest. The problem on the node side is the
           | impossibility of the last task, and if you aren 't doing it,
           | neither is your trusted third-party. I'm not saying it's
           | hopeless -- I'd even wager a guess there's a comment in my
           | past that is far more harsh on `npm` than it
           | deserved/deserves[1].
           | 
           | I don't think "node-based" solutions for shell are bad. The
           | biggest problem I tend to run into with shell scripts in
           | constrained environments are related to dependencies. With
           | node, `install`, done (usually). I target "what's probably
           | there" like most people. Sometimes it's not. In the past,
           | when this was a bigger problem than it is now for me, I would
           | throw my hands up and build it in whatever I wanted because
           | "if I had to get a waiver to add `jq` or some other thing to
           | this box, I might as well have them put `python` on there" --
           | same amount of work arguing over BS but less work writing it.
           | I'd probably apply that to `node` these days but those
           | problems aren't mine any longer. :)
           | 
           | [0] Which some will point to `npm` as the _whole reason they
           | use node_ while others will point out why it 's the entirety
           | of its problems.
           | 
           | [1] And I hate the attitude of some that implies `npm`s
           | problems have easy solutions, "if they just ...". No. It's
           | almost everyone's first language. It's really easy to publish
           | packages. There's a gajillion of them out there. (Yet, it
           | works ... every? ... time I need to solve something using
           | it.)
        
           | rowanG077 wrote:
           | Are you serious? About a third of my job is frontend with
           | typescript. The rest is backend and some application dev and
           | embedded. Frontend is seriously the worst environment. It's
           | great if the magic works. But that's the easy part. Once
           | something breaks, and it will, you have to descend to the
           | seventh circle of hell to figure out where something in this
           | mount everest of tooling and dependencies broke.
           | 
           | I love the idea of frontend dev. But the tooling takes all of
           | the fun out of it.
        
             | mdip wrote:
             | But I don't think your problems with FE Dev/TypeScript are
             | "TypeScript" problems so much as they're problems around
             | the tooling you're using with `node`.
             | 
             | And I agree. Unless it works out of the box, it's a half-
             | day of profanity at least.
             | 
             | But writing a command-line tool in TypeScript doesn't
             | require any of that. The comment focused on FE development
             | with Next.js -- I have no experience with that, but a
             | simple React-based solution using `create-react-app` works
             | out-of-the-box for a lot of things[0]. I will say, it does
             | sometimes feel like everything TypeScript gets right is
             | made up for by everything "all of the bundlers/tooling
             | around it" screws up, but it's gotten monumentally better.
             | You're always going to be weighing pain points against
             | eachother, and folks that do front-end web development all
             | day long are going to find the problems they routinely
             | encounter to be "simple", possibly even "intuitive" based
             | on how the rest of the ecosystem works.
             | 
             | From my perspective -- partly on the inside, partly on the
             | outside -- I seem to have to muck around with the
             | equivalent of "build scripts" about as often as I used to
             | (not) enjoy in the C/C++-land. But dammit-all if "time to
             | completely working" in TypeScript isn't always twice as
             | quick. TypeScript, configured correctly, catches so many
             | run-time issues at compile-time[1]. For me, the distance
             | between "it runs" and "it runs correctly" is often shorter
             | in TypeScript despite it not being my primary language.
             | 
             | [0] To be sure, it's hard for me to say `create-react-app`
             | without the obligatory `fscking` inserted... it's got many
             | problems, but at least half the time it's an implementation
             | detail.
             | 
             | [1] Static-type-checking time?
        
         | fouric wrote:
         | > irresponsible for the future of software development
         | 
         | Not true. This is _highly interchangeable tooling_ - it can
         | have whatever dependencies you want, because there 's no
         | "dependency explosion" that happens with libraries. LSP is a
         | standardized protocol - you can swap it out with anything you
         | like.
         | 
         | Moreover, people rarely build interactive tools on top of other
         | interactive tools. Now, if this were a _library_ with a bunch
         | of dependencies, that would be a whole different matter - then
         | any program or library that used this would get all of the
         | transitive dependencies - but, it 's not.
         | 
         | Go and reimplement this tool yourself. RIIR, make a statically-
         | linked 500kb executable with no perceptual execution time, and
         | eat their lunch, because your tool is a drop-in replacement.
         | 
         | Is a Node dependency a bad idea for this tool? Arguably yes. Is
         | it "irresponsible for the future of software development"? That
         | statement is so false that I suspect it's being used to try to
         | emotionally manipulate readers instead of making a coherent
         | argument.
         | 
         | Also...are you aware that Bash already tab-completion, even if
         | it's not automatic?
         | 
         | I'm beginning to wonder if this is a very subtle April Fool's
         | post...
        
         | cle wrote:
         | Node and TypeScript have the best Language Server tooling,
         | because that is what Microsoft uses for VS Code.
        
           | ttt0 wrote:
           | "JavaScript is the best language for writing HTTP servers,
           | because that is what web browsers use."
           | 
           | Doesn't make any sense. LSP is just a protocol. You can write
           | language servers in whatever language you want.
        
             | kazinator wrote:
             | But, look at this project.
             | 
             | They took a Bash parser written in C from the Tree-sitter
             | project, and are using the C as a compiled WebAssembly blob
             | out of TypeScript.
             | 
             | And, actually, that Tree-sitter Bash parser is specified or
             | generated using JS somehow; the project for producing it
             | uses TypeScript also.
             | 
             | That's how easy it is to write LSP server in any language?
             | 
             | Maybe it's done this way so that the LSP can be integrated
             | right into the editor itself, so as not to have to run
             | somewhere else as an external piece.
        
             | cle wrote:
             | What are you talking about? TypeScript has the best
             | Language Server libraries, if you want maximum productivity
             | when making a Language Server, you run with TypeScript. I
             | don't even like TypeScript but I can at least acknowledge
             | that it can make sense to implement a Language Server in
             | it.
             | 
             | Personally I would have used Go for this exact reason, but
             | it's reasonable to use TypeScript too.
        
         | brobdingnagians wrote:
         | I like minimalism, I agree with cutting down dependencies, but
         | the person who does the work gets to pick the language. If I
         | did it, I'd do it in C, Rust, or Kotlin, but I appreciate
         | having an LSP for a new language nonetheless. Looks like it has
         | no runtime library dependencies, then that removes risk of
         | supply chain issues, so I think they've done a good job.
        
         | michael1999 wrote:
         | Do you really think someone would write a lexer, a parser, and
         | an implementation of the LSP protocol for Bash in Bash?
        
           | kazinator wrote:
           | But there is a lexer and parser for Bash inside Bash. Bash
           | could either provide the LSP protocol itself, or else open up
           | some primitives for a script to gain access to the info
           | somehow.
        
           | usbline wrote:
           | There's more languages native to unix-land than Bash, you
           | know. Find me a linux distro that doesn't have GCC or Clang
           | installed by default, or even Python for that matter.
        
             | mikewhy wrote:
             | What about C and Python are "native to Bash's environment"
             | though? That's the complaint the person you're responding
             | to is touching on.
             | 
             | Also, lots of Linux distributions don't come with GCC and
             | Clang by default (Ubuntu, Debian, OpenSUSE).
        
               | akvadrako wrote:
               | Bash is written in C so depending on C doesn't add a
               | dependency.
               | 
               | Python is also the 2nd most popular scripting language in
               | the Linux world; it's even part of the Freedesktop base
               | runtime. Though I don't know if it's standard in BSDs.
        
         | stevenhuang wrote:
         | Yeah.
         | 
         | When I gave this a shot a while back, I looked at its
         | dependencies and it was way larger than the footprint of coc-
         | clangd for some reason.
         | 
         | Wasn't a good signal so decided to remove it after that.
        
           | mikewhy wrote:
           | clangd is already a language server, so coc-clangd can be
           | small since it only needs to be a bridge between the two.
        
             | stevenhuang wrote:
             | That makes sense. I'll likely revisit this plugin then,
             | thanks.
        
         | delusional wrote:
         | It also means that your text editor is now a distributed
         | system.
        
         | gkfasdfasdf wrote:
         | This is an interesting criticism. So a bash language server
         | must be written in bash? I think _that_ would be indeed be a
         | software dev monstrosity.
        
         | kazinator wrote:
         | > _node and typescript in order to get auto completion for
         | bash, I 'd have called you crazy_
         | 
         | It's worse than you think.
         | 
         | This uses something called Tree-sitter: some project written in
         | C for providing parsers for numerous languages.
         | 
         | The Tree-sitter parser for Bash itself somehow requires
         | Typescript, though the parser is in C.
         | 
         | This Bash-LSP project uses a binary blob of that parser: it is
         | C compiled as C++ into WebAssembly.
         | 
         | Bash-LSP, as well as the Tree-sitter Bash parser, can basically
         | be called IDE tooling written by and for TypeScript
         | programmers, who sometimes have to mess with Bash scripts.
         | 
         | The target audience doesn't mind TypeScript and Node
         | dependencies, and in fact likely finds that preferrable to any
         | other kind of dependency, because working with TypeScript
         | dependencies is fresh in their minds, requiring little ramp-up
         | to handle another one.
        
           | nonbirithm wrote:
           | > The Tree-sitter parser for Bash itself somehow requires
           | Typescript, though the parser is in C.
           | 
           | This is not necessarily true if you can write a compiler for
           | a tree-sitter grammar that outputs the parser code in your
           | favorite language. I know semgrep does this to make parsers
           | for OCaml. But, of course, that's more work to be done.
        
       | gkfasdfasdf wrote:
       | I have been using this for a year or so and it is awesome. I use
       | with neovim + LanguageClient-neovim. I don't really understand
       | why people are complaining about the dependencies - on macos just
       | brew install node@14 and npm install -g bash-language-server.
       | Check for updates occasionally via npm outdated -g. I really have
       | no idea what the dependencies are other than node and nor do I
       | care - its just another app on my system.
        
       ___________________________________________________________________
       (page generated 2021-04-01 23:01 UTC)