Yes, I am in a similar lost state as well. I’ve written about this from the “shell” perspective here.
I do want to invest my time into an editor/shell platform, but all existing ones provide only pieces of what I need. Emacs has the right “is an OS” mindset, UI idioms and daemon mode, VS Code has a dependable extension ecosystem and adequate configuration workflow, IntelliJ has the right amount of out-of-he-box polish and attention to details. None have a reasonable extension language :)
My current solace is that I work on an LSP server, so, if an ideal editor is to be created, I’ll be able to use it. Even than, I am not completely sold on the LSP approach, and still have doubts that maybe IntelliJ-like polyglot IDE brain is a better approach overall.
dynamic, open world runtime (as you want to eval user code and load plugins)
reasonably fast runtime (sometimes the amount of data to process might be substantial)
statically/gradually typed (so that’s it’s possible to autocomplete your way through dotfiles without knowing stuff up front. This might be possible to achieve using smalltalk-like dynamic introspection instead of static analysis based approach. I am betting on types though, as I’ve never experience “discoverability via autocomplete” in elisp or clojure in practice).
support for modularity, so that diamond dependencies are not a problem (Julia is interesting as dynamic language which has this)
reasonable semantics and built in idioms for grunt work tasks. Things like “no two nulls” and “reasonable collections and iterators”
big ?: monkey-patchability, a-la Emacs advice system. That’s definitelly a plus for each isolated user, but I don’t know if that’s good or bad for the ecosystem as a whole, as it goes directly against modularity.
big ?: DSL capabilities? The current fashion (Swift, Kotlin, Dart) is that UI should be described in code, mostly as data, and that it is important enough to have special support in the language/compiler.
I think Common Lisp meets all these points well (some might disagree on iterators and sequences). Only trouble is that GNU Emacs hasn’t been rewritten in it yet!
Even than, I am not completely sold on the LSP approach, and still have doubts that maybe IntelliJ-like polyglot IDE brain is a better approach overall.
Can you expand on what this approach is? Is it just the idea of having all the parsing and semantic analysis be performed in-process, or is it something more precise? Very curious about this.
The main thing is using the same data structures for different programming languages. Sort-of LLVM for front ends.
In IntelliJ, you can use the same code to process Rust and Java syntax trees. This results in some code-reuse, and somewhat better user experience for polyglot codebases, as its relatively easy to implement cross references between different languages.
But front ends differ much more than backends, so, unlike LLVM, IntelliJ isn’t exactly a holly grail of code reuse.
The main thing is using the same data structures for different programming languages. Sort-of LLVM for front ends.
Ah, I see, kind of like TreeSitter but with additional semantic information? I think Langkit kind of matches this description too, but the only end user for that is the Ada language.
Yup. Off the top of my head, IntelliJ provides the following in a reasonably language agnostic fashion:
parsers and syntax trees (basically, tree sitter)
file indexing infrastructure
tree stub indexing infrastructure (the effectiveness of it does depend on language semantics)
code formatters
basic IDE features, which depend only on the syntax tree
approximate reference search infrastructure
an API to GUI parts of ide, so just you don’t have to re-invent a million small things like associating icons with specific kinds of syntax nodes.
Note that actual “language semantics” bits are implemented by each language separately, there are common patterns, but little common code there. The exception are Java-like languages (Java, Kotlin and maybe Groovy) which have a “unified ast” framework for implementing polyglot refactors.
Personally, I’m interested in an idea presented in http://userland.org (I’ve been exploring similar space before that, inspired by Bret Victor’s famous “IInventing on principle” talk). Trying to do something in this area, but on hold due to higher priorities (but it never stops to itch me).
I guess some of those items are already addressed, but I have yet to see a Neovim GUI going fully “native without TUI aspects.”
This is basically what I want to achieve with nwin. But there’s long hard road before getting there…
See, configuration should be stupid and limiting. It should be key = value, period.
Hard disagree there. There is no actual separation between configuring and writing plugins. Writing plugins is just an advanced way of specifying the way software should be configured.
I think that configuration can be done via code, but it does not mean it should. The reason for that is mainly for cognitive complexity reasons. If you are the author of your application, you will very likely know how to script it. You will know all the quirks and all the little things to know that you will, obviously, have well documented (right?!). Your users will not have this kind of knowledge.
This sounds absurd to me. Your configuration belongs to you and it doesn’t make sense for somebody else to copy it from your dotfiles, they should write their own instead. I would add that there is absolutely no difference between a Lua API and a simpler “set these values” way of configuring software. Both the Lua API and the “simple configuration options” need to be documented in a way that can be understood by the end user and that’s where the actual problem lies. For example, Vim has the simple key-value system the author argues for and it isn’t simple to use. Discoverability is pretty bad and the documentation is often very hard to understand.
There is no actual separation between configuring and writing plugins. Writing plugins is just an advanced way of specifying the way software should be configured.
IIUC, from this perspective, the typechecking is also intertwined with/acting as a kind of templating. But I believe due to the type checking being always “narrowing down”, it should be non-Turing-complete, and also the syntax looks really approachable. In other words, I believe it’s a somewhat powerful typesystem, but with an impressively approachable syntax and mental model for users. But I’m neither PLT guy, nor deep into CUE itself, haven’t had much time for it yet, and long ago when I tried it had poor error reporting, which made me backlog it. So I may well be misunderstanding things.
I appreciate the callout of neovide in your readme. I’ve been thinking about what it would take to create a similar experience in a full neovim gui using externalized windows. If you don’t mind me asking (I haven’t looked at the code) is that how you built this? Or did you implement the multigrid extension?
It may be possible in neovide to set a mode which causes top level windows to be opened as external windows in a similar way. That way you get the polished neovim experience but with the benefits you’re shooting for in nwin.
Regardless, I always love to see new neovim guis, especially written in rust ;)
I’ve been thinking about what it would take to create a similar experience in a full neovim gui using externalized windows. If you don’t mind me asking (I haven’t looked at the code) is that how you built this? Or did you implement the multigrid extension?
I rely on the “ext_win” extension that hasn’t been merged yet: https://github.com/neovim/neovim/pull/13504 (the reason I’m pointing to my neovim fork rather than this PR is that I have lots of experimentatl patches that I’m not sure are really needed).This extension indeed force-enables multigrid.
I’m surprised you’ve been thinking about this though - I remember you were not very interested in this idea when I asked you about it a year ago on reddit (actually I re-read the thread and I seem to have missed the two more favorable replies you gave me after saying you weren’t very interested).
The lack of interest I remembered (and the fact that I can’t get Neovide to work on any of my computers due to weird Vulkan errors) is the reason I started a new project - Nwin is pure SDL2, which is a PITA to make fast but works on all of my machines. Also, I think specifically targetting i3/Sway rather than all window managers across all OS will allow me to take shortcuts architecture-wise and make a deep integration with the window manager much easier.
Starting this project “from scratch” also forced me to lay down the foundations of the architecture and to notice (what I would consider) a lot of shortcomings in neovim-lib, to the point where I’m thinking about writing my own client lib to make my code a bit cleaner, saner and safer. Had I relied on Neovide I’d probably have missed all the things I dislike about neovim-lib :).
I wish you luck! Like I mentioned, more guis is always good. I’ll be watching the repo to see if theres any shared components or learnings to be had.
Targeting a single OS and window manager is definitely an interesting way to go. Rather than taking the greatest common denominator of support, you’re able to implement new things faster.
Re vulkan issues. This is definitely something I’m targeting in the not too distant future with an OpenGL renderer. Skia supports it as a target, so it should be possible, just working out some issues.
I really like this, I honestly feel exactly the same way. I’ve always liked neovim, and I really like Doom Emacs, but I could never get into configuring it properly, so I always end up back in nvim. And these configuration issues are essentially what makes me still use editors like VSCode for some bigger projects - they are already configured, properly! I don’t have to figure out how to set up LSP, it’s already done for me. That’s something I’ve been trying to recreate with nixvim, using Nix to generate a neovim config, but the whole “configuration as code” thing makes this impractical a lot of times, and I’ve nearly given up on it several times now because of it.
But I’m not sure exposing configuration as code is necessarily a bad thing, because it just lets you do more. For example, I have had for a while a line in my vimrc which converts the selected text into subscript and superscript unicode characters. This would never be doable with just a plain configuration language, but I could just grow it organically without making a whole new plugin (though I’ve looked into it already because I can definitely see the use case). So I’m not sure if we should throw out the scripting configuration, I think it definitely has its place.
Yes, I am in a similar lost state as well. I’ve written about this from the “shell” perspective here.
I do want to invest my time into an editor/shell platform, but all existing ones provide only pieces of what I need. Emacs has the right “is an OS” mindset, UI idioms and daemon mode, VS Code has a dependable extension ecosystem and adequate configuration workflow, IntelliJ has the right amount of out-of-he-box polish and attention to details. None have a reasonable extension language :)
My current solace is that I work on an LSP server, so, if an ideal editor is to be created, I’ll be able to use it. Even than, I am not completely sold on the LSP approach, and still have doubts that maybe IntelliJ-like polyglot IDE brain is a better approach overall.
What would you say makes a good extension language? I am personally fond of Elisp, but that is probably also because I use it regularly.
I think Common Lisp meets all these points well (some might disagree on iterators and sequences). Only trouble is that GNU Emacs hasn’t been rewritten in it yet!
No, but Lem is developed: https://github.com/lem-project/lem/ (ping @Moonchild)
https://github.com/robert-strandh/second-climacs (eventually, maybe . . .)
Can you expand on what this approach is? Is it just the idea of having all the parsing and semantic analysis be performed in-process, or is it something more precise? Very curious about this.
The main thing is using the same data structures for different programming languages. Sort-of LLVM for front ends.
In IntelliJ, you can use the same code to process Rust and Java syntax trees. This results in some code-reuse, and somewhat better user experience for polyglot codebases, as its relatively easy to implement cross references between different languages.
But front ends differ much more than backends, so, unlike LLVM, IntelliJ isn’t exactly a holly grail of code reuse.
Ah, I see, kind of like TreeSitter but with additional semantic information? I think Langkit kind of matches this description too, but the only end user for that is the Ada language.
Yup. Off the top of my head, IntelliJ provides the following in a reasonably language agnostic fashion:
Note that actual “language semantics” bits are implemented by each language separately, there are common patterns, but little common code there. The exception are Java-like languages (Java, Kotlin and maybe Groovy) which have a “unified ast” framework for implementing polyglot refactors.
Personally, I’m interested in an idea presented in http://userland.org (I’ve been exploring similar space before that, inspired by Bret Victor’s famous “IInventing on principle” talk). Trying to do something in this area, but on hold due to higher priorities (but it never stops to itch me).
This is basically what I want to achieve with nwin. But there’s long hard road before getting there…
Hard disagree there. There is no actual separation between configuring and writing plugins. Writing plugins is just an advanced way of specifying the way software should be configured.
This sounds absurd to me. Your configuration belongs to you and it doesn’t make sense for somebody else to copy it from your dotfiles, they should write their own instead. I would add that there is absolutely no difference between a Lua API and a simpler “set these values” way of configuring software. Both the Lua API and the “simple configuration options” need to be documented in a way that can be understood by the end user and that’s where the actual problem lies. For example, Vim has the simple key-value system the author argues for and it isn’t simple to use. Discoverability is pretty bad and the documentation is often very hard to understand.
Corollary/supporting evidence to your argument:
Edit: though, https://cuelang.org is a potentially interesting development in this space.
As far as I can see, this is a type-checked JSON. Are there other features I might be missing?
IIUC, from this perspective, the typechecking is also intertwined with/acting as a kind of templating. But I believe due to the type checking being always “narrowing down”, it should be non-Turing-complete, and also the syntax looks really approachable. In other words, I believe it’s a somewhat powerful typesystem, but with an impressively approachable syntax and mental model for users. But I’m neither PLT guy, nor deep into CUE itself, haven’t had much time for it yet, and long ago when I tried it had poor error reporting, which made me backlog it. So I may well be misunderstanding things.
I appreciate the callout of neovide in your readme. I’ve been thinking about what it would take to create a similar experience in a full neovim gui using externalized windows. If you don’t mind me asking (I haven’t looked at the code) is that how you built this? Or did you implement the multigrid extension?
It may be possible in neovide to set a mode which causes top level windows to be opened as external windows in a similar way. That way you get the polished neovim experience but with the benefits you’re shooting for in nwin.
Regardless, I always love to see new neovim guis, especially written in rust ;)
I rely on the “ext_win” extension that hasn’t been merged yet: https://github.com/neovim/neovim/pull/13504 (the reason I’m pointing to my neovim fork rather than this PR is that I have lots of experimentatl patches that I’m not sure are really needed).This extension indeed force-enables multigrid.
I’m surprised you’ve been thinking about this though - I remember you were not very interested in this idea when I asked you about it a year ago on reddit (actually I re-read the thread and I seem to have missed the two more favorable replies you gave me after saying you weren’t very interested).
The lack of interest I remembered (and the fact that I can’t get Neovide to work on any of my computers due to weird Vulkan errors) is the reason I started a new project - Nwin is pure SDL2, which is a PITA to make fast but works on all of my machines. Also, I think specifically targetting i3/Sway rather than all window managers across all OS will allow me to take shortcuts architecture-wise and make a deep integration with the window manager much easier.
Starting this project “from scratch” also forced me to lay down the foundations of the architecture and to notice (what I would consider) a lot of shortcomings in
neovim-lib
, to the point where I’m thinking about writing my own client lib to make my code a bit cleaner, saner and safer. Had I relied on Neovide I’d probably have missed all the things I dislike aboutneovim-lib
:).I wish you luck! Like I mentioned, more guis is always good. I’ll be watching the repo to see if theres any shared components or learnings to be had.
Targeting a single OS and window manager is definitely an interesting way to go. Rather than taking the greatest common denominator of support, you’re able to implement new things faster.
Re vulkan issues. This is definitely something I’m targeting in the not too distant future with an OpenGL renderer. Skia supports it as a target, so it should be possible, just working out some issues.
I really like this, I honestly feel exactly the same way. I’ve always liked neovim, and I really like Doom Emacs, but I could never get into configuring it properly, so I always end up back in nvim. And these configuration issues are essentially what makes me still use editors like VSCode for some bigger projects - they are already configured, properly! I don’t have to figure out how to set up LSP, it’s already done for me. That’s something I’ve been trying to recreate with nixvim, using Nix to generate a neovim config, but the whole “configuration as code” thing makes this impractical a lot of times, and I’ve nearly given up on it several times now because of it.
But I’m not sure exposing configuration as code is necessarily a bad thing, because it just lets you do more. For example, I have had for a while a line in my vimrc which converts the selected text into subscript and superscript unicode characters. This would never be doable with just a plain configuration language, but I could just grow it organically without making a whole new plugin (though I’ve looked into it already because I can definitely see the use case). So I’m not sure if we should throw out the scripting configuration, I think it definitely has its place.