And yes, the smart-asses of the 70/80s (aka LISP and Smalltalk) thought about that long time before anyone else. But hey, today's landscape is a bit more complex (think about CSS styles in a HTML embedded in a TypeScript enriched JavaScript JSX file).
The second aspect: LSP is great because it was a cross-vendor, cross-language initiative which had in its first year already two dozen languages on board in addition to half a dozen editors (VS Code, Emacs, Atom, VIM, ...). Emacs plugins could never deliver that because they were bound to Emacs.
I'm not super familiar with SLIME, but that's the goals of LangServ is to consolidate everything into a known protocol. There's also a spec for debugging.
Oddly enough the Wikipedia page for SLIME doesn't seem to mention Racket[0], but it does mention Clojure.
In the end, this is a project that is at least as much effort a creating a programming language.
It is possible, just require major engineering smartness (like writing and improving compilers, code generation, etc).
In fact... Racket has their own UI approach, but I'm not sure if it's just GTK under the hood or what, but it works cross platform.
Projects like sip and PySide show how much effort it takes to make Qt bindings form Python.
And all of this discussion just the bindings, not the actual widget libraries themselves and the effort that goes into those.
But generally, you are right. Language development is expensive enough. UI stack development is in difference to class lib development not a duty of a language developer.
What this article is about is the new(ish) open protocol originally developed for Visual Studio Code that is being adopted by quite a few other editors. The language server protocol (LSP) enables developers to write the kind of tools you're describing and have them support any editor (which has LSP support) on any OS. It's pretty cool. However it's also a fairly involved process writing one so many of the smaller languages haven't yet had the bandwidth to writing their own language servers.
With a REPL or playground, you've got all the libraries loaded, all the function definitions in a map in your interpreter, and if you have a partial identifier you can simply do a prefix search in the interpreter. The interpreter is live; define a new function, and it's added to the map, so it's available for subsequent completions. If the function definition is wrong, hey, it's a REPL, next line try again please.
In a stateless situation, or for a static language, you need to build that map. Ideally you use the compiler's front end, but then the front end needs to be hardened to recover properly from errors. It needs to be told about the cursor location, and when it hits the cursor location in the middle of an incomplete symbol, it needs to figure out what's appropriate to complete at that point based on the stack of scopes available, and jump back out to the editor (or use coroutines, or pause its thread, or whatever) with what it found. It's simply more work. And if you can't use the front end, because the front end wasn't built for it, and you can't modify it, well you're going to have to build what is effectively a new front end to solve the problem.
For those like me who have Vim burnt into their fingers and brain, there is Slimv[1] for Vim. Another alternative is Vlime[2] for Vim. Both these plugins are based on the same client-server architecture that SLIME is based on. In fact, these plugins rely on Swank TCP server (the same thing that SLIME also relies on). Swank receives SLIME commands from Slimv or Vlime and executes them. Of these two Vim plugins, I prefer Slimv personally because apart from supporting Common Lisp, it supports MIT Scheme and Clojure too. Vlime supports Common Lisp only at this time.