Show HN: Primrose – a text editor that runs in a WebGL texture
primroseeditor.com
primroseeditor.com
I am a digital nomad, and basically travel with a backpack's worth of stuff, developing off my 13"MBA. The thing I miss the most about my old office is having a nice monitor. The thing I miss most about having a home is my 3-monitor desktop setup. Both things I had to give up because they don't fit in my backpack and because I can't easily procure them wherever I travel to.
But if I can pack an Oculus Rift headset into my pack, I dunno, a year from now. I can have all the multi-desktop computing environments I want, and they'd actually be way more awesome than just 3 flat monitors.
Beyond all that, text editors and dev environments have seen little UX improvement given the rate of evolution for everything else digital. This looks like an awesome step to trying some really radical things (I know this is a previously explored topic though, but I love being reminded of it).
OP, this is awesome. I happily leave the future of my dev environments in your hands.
I suspect it'll take longer than that for the resolution to get high enough to be usable for fine-detail tasks like professional coding.
Coding does not require high resolution displays. You can code on a 80 character wide terminal with fonts of 8x8 pixels. I have. I still use bitmap fonts today (terminus). And let me remind you that blind people code as well. Visible text is just an abstraction, other ones are possible.
An Oculus Rift is much less expensive than your typical multi-monitor setup too, FWIW.
A VR headset is a device used to look at the xterm you want to type in.
Like, why do we still use plain text in flat files for source code (for the most part, there are a few exceptions-that-prove-the-rule)? Why are there so many examples of graphical programming systems that have completely failed? Is it because there is something inherent to text that makes it superior for representing algorithms? Or is it because 1-dimensional text maps to our IO systems the best? I suspect there is a healthy dose of the latter, but we haven't ever had a significant "other" IO system to ever test that theory.
In a lot of ways, Primrose isn't even my goal, more like a benchmark from which to start developing other ideas in text representation in VR UIs. I don't know what they will be, but at least I now have a starting point.
Information density. Images and graphs are exceptions to the general rule that text can contain a lot more information on one page than graphics can.
Text transports with full fidelity between print and screen, and between pretty much any system.
Anything beyond text becomes a) harder to communicate (e.g. consider how many people would struggle with even reading out loud maths formulas with symbols they are unfamiliar with; now extend that to trying to talk about representations that have extra spatial information), b) requires extra tooling for far more varied environments than you ever thought people actually code in (e.g. I have an idea; I want to write down code in my phones note-taking app)
Serializing it for IO is trivial. Representing it in a way that allows us to handle the two problems above in a way that makes it seem superior to text in enough cases is a very, very hard problem.
It's definitively intersting, though.
Pretty much any problem easily modeled as data flow has a nice a nice representation in an appropriate (traced, braided) monoidal category, examples would be electrical circuits, chemical reaction networks (simple atmosphere models, so called "Box models" are an example), hardware control software (LabVIEW), general ODE/Statemachine simulation (SIMULINK), "business processes" (forgot the name of the vendor), not to mention the various video/audio/shader programming environments.
Probably the intersection between the people capable of building a "generic" programming language for graphical programming and people who know enough category theory to inform the design is zero, even though software that solves subproblems of this kind is very successful. Ultimately you really want at least a 3d graphical language, because you want to express relations between 2d processes (for example the equation a+b = b+a, should be really understood as such a 3d process). Coincidentally relations between functions is something even programming languages like Haskell fail to address, it has type classes, but no way of specifying the equations that are required to hold.
The only language I'm aware of that does that is Magma, which unsurprisingly is based on Operads (essentially multicolored monoidal category with a fixed set of monoidal functors and natural transformations) and was designed by mathematicians and to a lesser extend Mathematica and Prolog.
I don't see what you mean about Magma. This is what I've found for Magma: http://www.math.harvard.edu/computing/magma/. It looks like Pascal with Python list comprehensions and sets as a first-class type.
Source code in most languages is a one-dimensional construct. Every source file in the project could be concatenated, the newline characters removed, and it would still compile to the same program (assuming the right ordering, barring white-space significant languages, etc.).
Is that because we are linear? Is that because our computers are linear? I don't think we're ever going to get away from written language as the abstraction of source code. Most (all?) people think in words. But how that language is presented might change. Literal lines and connectors between code elements has sucked in 2D because it just gets too dense for 2D space. Is that because linear things "want" to stay linear? Or is it because we have had to deal with 2D interfaces and it's easier to work in N-1 dimensions when using an N-dimensional interface?
And while I think I've seen attempts at this in 3D, then we have the other issue of 3D interfaces being terrible on 2D IO devices. Never have the two been put together.
But I think that's going to change very soon. A lot more people are experimenting with this sort of stuff these days. Good-enough stereo displays are accessible to everyone (slap your phone in the cardboard box you ordered a set of $5 lenses in). Language design is more accessible to everyone. Editor development is, too (I couldn't imagine doing this project 5 years ago, and even 3 years ago it would have been a very poor experience). There is just a culmination of different technologies that make it possible for just about anyone to hack on all of this stuff.
Somehow, there seems to be a lot of discouragement lately to do so, but that's a different story entirely. I'll just leave it at saying, I hate the phrase, "don't reinvent the wheel".
I still think that a graphical language for this is worth exploring, because it already happens to be the way domain experts think, which is presumably why most of the successful commercial software is targeted at them. See for example: http://math.ucr.edu/home/baez/networks/ for an overview of how all those things tie together.
Regarding Magma here is a PDF, which contains a summary of the theoretical foundations:
http://sage.math.washington.edu/people/cannon/magma-the-lang...
Essentially it is a language that can do type checked symbolic reasoning, whereas for example Mathematica is for the most part untyped. Page 11 explains the steps necessary to extend the system (you have to write a C-library, so that is less then ideal). The reason I bring this up is because relations between symbolic expressions (for example equations) are really something that lives in a higher dimensional space, see for example the Associahedron (http://en.wikipedia.org/wiki/Associahedron). In a 2-dimensional language ordinary programs would be graphs and metaprogramming would be surfaces between graphs. As long as you have only a 2 dimensional surface available, that kind representation probably would not work, but I believe as a conceptual idea it is rather helpful.
I agree with you, that the moment convenient augmented reality hits, we will hopefully see different variations of program representations emerge. Especially complicated concurrent systems would probably benefit from it, since they don't have a sequential control flow.
No, I wouldn't want to write Primrose itself in Primrose, and Primrose isn't a very big project. But little experiments with the live-coding have been fun. I'm still working out the use cases in my head. I suspect there might be more use for manipulating and visualizing code in VR--at least in the early days until resolution gets better--than straight, bulk writing code.
Oculus sucks at displaying text - it's low resolution (half of 1080p), it has crazy chromatic abberations, and you have to transform "spherize" your image to correct for the lens distortion, further reducting the resolution.
Oculus is not light - it's pretty annoying to wear it for longer than 20-30 minutes.
If VR catches on at all you can expect it to see the same type of acceleration.
The same is conceivable with a VR solution. That makes it awesome.
As for the problems you mention, all extremely solvable. I'm sure you were alive when people were editing text on lower resolution displays. Lens technology for dealing with a great extent CA exists, it just needs to be tuned for VR settings. I could lie down and use it. Lighter materials could be used in future versions. It could be made disassemblable for easier packing/storage.
I have faith in our current generation of technologists to make these things and more happen before my development career sunsets :)
My friends think I'm insane by keeping so many tabs open. Maybe I am. Maybe you are, too. Yet with as disorganized as it might seem to others, it works well for my particular usage patterns. (It also helps that I segregate news, work, misc. activities into different profiles, too.) The thing is that sometimes when you open something that you want to get back to at some indeterminate point in the future, you can do one of two things: Bookmark it and forget about it, possibly permanently; or keep it open and stumble upon it as you go through your tabs to categorize them and clean them out. Although these days, I mostly just dump everything into a dated but uncategorized list to go through in the future. Session Manager handles the rest in the event I do something stupid.
I imagine I'll catch some flak for sharing this, but it works well for me. My work-related browser sessions are usually better organized and important stuff gets saved more or less immediately. My "fun" generic browsing instances--not so much.
Not that I'm aware of, but there might be a support group. ;)
Joking aside, it's curious how much flak you can take from suggesting that you make extensive use of a feature that's built into the browser... everyone I know thinks I'm a bit odd when they see my Firefox sessions.
> For me windows are tasks/areas of research. A task can last minutes, hours, days or even weeks.
I really like this perspective, because it's deeply reflective of my usage patterns. For example, when I was learning Golang, I had a session opened exclusively for that, with all the respective documentation, some blogs, tutorials, and various odds and ends. Over time it evolved, certainly, but those tabs remained open for the duration that I needed them. It doesn't matter if it's a day, two days, or two months.
I have one Firefox profile configured to use Session Manager with various saved sessions based on whatever I'm working on. So, whenever I need a major context switch, I save the current session, then switch to the one I need. It allows me to pick up where I left off--even if there's 300+ tabs in that particular list. Though, I'm pretty bad about clearing some of those tabs out--oftentimes it's because I want to revisit whatever I was researching, even if it takes several months!
It sounds like you and I do about the same thing in that regard! Although, I've yet to learn the bookmarking technique. ;) Presently, for my generic browsing, I just dump everything into a dated folder. Everything else of interest that I don't want to inadvertently lose gets shunted into my unsorted bookmarks without a date under the pretense that I'll eventually categorize it (which I usually do). I think I'll have to try the categorization for tasks that are complete rather than simply bookmarking tabs individually and massacring the rest.
The ability to shift select tabs and bookmark, move to a new window or close is amazing.
Exactly this (apologies for the 2-day delay!). This is exactly why I keep so many tabs open, because I can filter them and use them as a living browsing session. It also provides me with some amusement when I look through tabs opened weeks (sometimes months?) prior, because it gives me a snapshot into what I was thinking of/looking for during that window of history.
I'm really glad to find others who share my usage patterns. I don't feel so weird. :D
Aside: Just a week or two ago, I archived a bunch of tabs from a generic browsing session and I think the total came close to 980. Eeeek!
The tabs are also "soft-loaded" meaning that you have to click on them to load the content, so you can find the offending tab and kill it to prevent crash from happening again.
> The tabs are also "soft-loaded" meaning that you have to click on them to load the content
I couldn't be happier since Mozilla switched to this mechanism. It means reloading a massive browsing instance isn't quite as resource intensive. Last I checked Chrome/Chromium, it STILL doesn't do this, which is infuriating and part of the reason I dumped using Chromium as my primary general browser.
There's nothing worse than when as few as 100 tabs can eat up ~2-3GiB RAM right after you start the browser...
[1] https://addons.mozilla.org/en-US/firefox/addon/session-manag...
I guess that will teach me to start sneaking into my wife's computer bag and borrowing her Macbook to test these things.
You cannot be serious about this. This is like writing a thesis and just never closing office and never saving. A year?
Imagine playing around in a Voxel.js Minecraft world, walking up to an NPC, and lifting the hood to reveal its live-editable source code.
Looking forward to see hacks using this.
GET https://primroseeditor.com:8082/javascripts/ga.js net::ERR_BLOCKED_BY_CLIENT
And in Firefox it's not even loading the home page, with an error of "too many open files".ga.js is "classic" Google Analytics, generally considered a privacy concern worth blocking.
Blocked by client means blocked by you.
After New Years, I got the bug in me to work on this and just knuckled down on it. Though, Brian appears to be happy with where he is, now.
In my very first proof-of-concept, I used hidden DOM elements to do the layout and styling of the text, and then queried the element properties to figure out the draw operations I needed to do. It was very slow and really unreliable, though, and I had a lot of cross-browser issues. Ultimately, redoing everything from scratch was actually easier than trying to hack around DOM.
I've been seriously considering implementing a soft keyboard for mobile devices as well. It's just so hard to get the ones in the wild to interact with text in any common way, and on iOS it's nearly impossible to get everything resized correctly to use the most of the screen real estate.
If anyone is interested in working on something like this, there's a very small community germinating in http://www.reddit.com/r/HMDprogramming/
A few notes, using FF35 on OSX 10.10:
1) Can't use without first going full-screen.
2) Red dot follows the mouse, but with a large offset.
3) Cursor doesn't focus where mouse click occurs. Doesn't focus where red dot is either.
4) No visual indicator when a window has focus. So keyboard navigation often results in accidentally typing a/w/s/d in a code window.
5) Would be nice to use click/drag to pan up/down/left/right.
#1 is interesting, I've actually had the opposite problems: not being able to get things to work in fullscreen on OS X. My wife has a Macbook, so I will try to test there (if she will let me).
#2 and #3 are probably the same issue, expressed in two different ways because the red dot is placed completely independently from the caret drawn in the texture. Do you think you'd be able to figure out if its OS or display related? I.e. do you have a retina display? I should be collecting analytics on screen and pixel ratio metrics, sigh.
#4 was a punt, I just wanted to get the job out the door. I did want to dim the editor when it wasn't selected, and provide a key combo to deselect, but I ran out of time on my self-inflicted deadline. It is definitely in the pipeline, however.
#5: did you notice that SHIFT+mouse movement panned the view? Or are you not satisfied with that system? I admit, I'm not wild about it myself, but it seemed like the least evil of all of the options, considering the interactions that I also had to do with the editor.
Any windowing system or GUI is already mostly a graphics application.
That was actually a bit of a surprise (though I admit it shouldn't have been) with Primrose. If I pick dimensions for the editor that fit the window's aspect ratio, and don't rotate the view at all, then the editor pane can fill the browser window and it looks very natural.
I am not positive, as I don't have the spec laying in front of me and it's been a long time since I looked, but I'm pretty sure the HTML5 Canvas API is not hardware accelerated at this time. That is how I do the actual rendering of the text, using Text API.
There is another project called fontpath[1] that can read TTF and OTF font files, and another project from the same developer called gl-sprite-text[2] that can render them as bitmaps to textures. I've been considering converting my rendering over to using it. The process would at least be good practice in decoupling the code a bit more, as I think the tokenizer and keyboard system would be useful in other projects as well.
The keyboard code pages aren't yet complete for everyone in the world right now, but I think they go a long way towards making it possible to once and for all make good keyboard interactions in JS. And by completely implementing my own end-around of the browser's own handling, sticking to more of the older primitives, I am actually able to make for more cross browser compatible. I don't know if anyone noticed, but this runs in IE perfectly fine, and I didn't really do anything special to make it so. And if you just run the Canvas on its own, without the WebGL part, it actually runs on some relatively old browsers without any trouble.
How do native apps do this, while also using hardware acceleration? Also, native apps can access sub-pixels for antialiasing, which I don't think is possible in a WebGL context.
I've seen OpenGL GUIs before, but I wonder what limits them compared to native apps, particularly when it comes to text and sub-pixel antialiasing.
Side note: I tried to load this on Chrome for Android and it went very badly. I got redirected through two of those bright red "UNSAFE YOU SHALL NOT PASS" https pages and then finally got to a page that didn't do much at all. No idea why, worked fine in Chrome on OS X.
I also somehow broke the touch screen controls at the last minute. But I was really keen to get this project out by the end of this month. So I cut features to get in on my self-imposed deadline. I just shut it off to avoid procrastinating release, focusing on too many UI issues or trying to avoid crashing people's browsers when I haven't the slightest clue if there is anything I can do about it.
Most of my career has been working in consulting, mostly for the type of consultoware companies that make all the boring, MS-tech, CRUD projects. I've been freelancing for the last three years, but even that isn't ideal. I've always wanted to have my own projects, building the type of products I've always wanted.
Over the years, I've had a lot of personal trouble with procrastination of completing projects. 10 years of starting and stopping the same ideas, becoming dissatisfied with my work, and eventually growing bored of it and letting it rot on a forgotten hard drive somewhere. I've always known it was an avoidance tactic. By focusing only on the core technical issues, I'd never have to address the tertiary tech and management issues common to releasing any project. So that was another motivation behind this project: just get something together and get it done, out, and in front of people.
I couldn't be happier with the results. Yes, it's missing features. Yes, the server is kind of janky, being that I'm not a sysadmin and only even learned how to turn SSL on a few months ago (though I think it's actually my host's fault for not configuring some of my certificates properly). But I think it's pretty good for a month's worth of work.
It's written in Go, but I'm planning to have it running in the browser by compiling Go to JS and using OpenGL bindings with two backends: WebGL and OpenGL.
In terms of usability, it's nothing more than a complicated tech demo atm; I need to figure out its future direction.
Yeah, I have written everything so far in plain JavaScript. I've been considering something else, but all of the available options seem a tad... monolithic.
If I'm going to not-javascript, then I think the answer is to go to something that is completely type safe and static, instead. I'd really like to be able to write-once-and-run-desktop-and-browser. I used to do C++, and now there is Emscripten, but I'd really rather not get back into C++ again. Go looked interesting, and there seems to already be a fair amount of work towards transpiling to JS. Rust looks particularly interesting, especially with the lack of implicit garbage collector, but from the little I've read, it seems Emscripten doesn't work that well with it.
I agree completely, about type safe, static types, and not wanting to get back to the mess of C++ (header files, makefiles, ifdefs, complexity, etc.).
Which is why I think Go fits the bill so well.
> Go looked interesting, and there seems to already be a fair amount of work towards transpiling to JS.
There is indeed. I've already done quite a lot with it, but with smaller side projects for now. That's where I gained the confidence and I will work towards applying it to my main projects now.
I can link you to https://github.com/shurcooL/play/commit/e53557dd9c070ce0ec52.... You can look at the latest code, it's all in a single main.go file, and it runs great in the browser.
Feel free to ping me with any questions you may run into (like what are best packages to use, or anything else) and I'll happily help out!
There is a small bug that I haven't fixed yet that requires you to look away from the editor to make the drop down lists on the instructions page work.
As for other languages, I have a tool at https://primroseeditor.com/keyboard_test.html that can put together the code pages that I use for this. It supports dead keys for typing umlauts, but it can be a little fiddly to use. I've been using the Windows on screen keyboard to make them, so I don't know how well it maps to reality.
Unless you mean using alt codes to your Unicode characters directly, no, don't have that feature yet. To the list!
Between the OS and the browser, there aren't many friendly keyboard shortcuts left.
forever -w start yourFile.js
That'll keep it up and going as a daemon and reboot it when files change :)
Also, setting up a CDN in front of your static files is actually much easier than it sounds at first. You can just setup a Cloudfront distribution that uses your domain as its source; that should take off a lot of the load.