4coder Update: still reorganizing and cleaning up

Allen Webster Jan. 17, 2017, 1:24 a.m.
So it's been over two years since I started 4coder, and I don't think I properly slowed down and cleaned anything up at all during the 2016 portion. I can't even remember what 2015 4coder was like, but I figure I probably was even less disciplined back then. So for that reason the project I took up a while ago of carefully considering the organization of the code and the major systems is still going on. Since cleanup doesn't lend itself to new features I have also split my 4coder time between little features I can implement through the custom API and the cleanup work.

As I discussed in an upcoming 'Handmade After Dark' episode, I have a new more strict schedule and special office space. With that comes sessions of 4coder work that can go as long as eight hours without having to interrupt the flow of my thoughts. If I have learned one thing from the experience, it is that I am definitely not the sort of person who can work as well a couple hours every day as I can all at once in one day.

I am excited to roll out the new function listing feature and several other new features and improvements by the end of the month for all backers.

Stay tuned everyone, and thanks for reading!

4coder's New Project Files

Allen Webster Dec. 29, 2016, 4:33 a.m.
This is a post to briefly describe the new 4coder project file feature in alpha 4.0.14.

The feature is meant to support the common situation where just having one build rule that is always in a "build.bat" or "build.sh" for the entire project is not always enough. Obviously anyone with access to the customisation layer has always been able to extend this, but the project file system creates some built in project configuration possibility. It also solves several other smaller issues, but we'll get to that in a minute.

The way it works is you create a "project.4coder" file in the root directory of the project. With 4coder running you can launch a project by navigating to the directory containing the project file and running 'load project'. Loading the project also opens all the code in the directory. Unlike the 'open all code' version, this version reads an extensions setting out of the project file, so you can set any set of extensions to open with the project.

Once the project is open the f keys are all assigned a command to execute and an output buffer where the command results will be sent. This can include various build script configurations, other types of scripts, or any terminal commands available on the platform at all.

Another advantage of this new system is that it always runs the command from the project root directory, even if you have navigated the 4coder hot directory into a subdirectory or outside of the project. This helps you to guarantee where your scripts can be found and know what directory they will run in.

Here is an example project.4coder file that is similar to default 4coder behaviour using F1 as the build key:


fkey_command_win[1] = {"build.bat", "*compilation*", true};

fkey_command_linux[1] = {"build.sh", "*compilation*", true};

The first line sets the extensions to the standard C/C++ extensions. Since commands will differ from platform to platform each platform gets it's own command array. The index [1] says that the command should be bound to F1. The command itself is formatted as: {COMMAND-STRING, OUTPUT-BUFFER, use-small-footer-panel}. The first two options have already been described, the last, if set to true, lets you specify that you want the command executed in a small panel at the bottom of the window instead of taking over an entire panel.

And that is the entire project system so far!

Let me know if you have any thoughts on other features you would like to see that go along with projects.

Later everyone!

New 4coder Information Site

Allen Webster Nov. 29, 2016, 8:19 p.m.
Through November I have been building up an information site for 4coder and today I posted it at 4coder.net. I still need to fill in lots of the information which I will continue to do over the next few days. A lot of people have asked for different information pages including a features list, a road map, and tutorials, all of which will be going on the site. I will also be posting the 4coder API documentation there from now on. If there is any category of information you would like to have on 4coder that is missing let me know!

For the next month of work on 4coder I will continue building out the information on the site and I will work on inner 4coder system clean up and finally building the basic testing apparatus I've been hinting at from time to time for a while now. I plan to post a couple of new builds in December for bug fixes and tweaks to the indentation system.

That is it for my end of November update, later people!

4coder October Update

Allen Webster Oct. 28, 2016, 10:20 p.m.
Hi everyone!

It has been a big month for 4coder. Just today I released alpha 4.0.12. I finally switched over to the gap buffer, and eliminated the transitional framework that I first constructed eleven months ago. Getting rid of that extra complexity bought me a great deal of room in my "complexity budget", and I spent it on new features in the buffer system.

The immediate upgrades are the systems for arbitrary wrap positions, and virtualized white space at the beginning of lines, which have allowed me to create a code smart line wrapping system, or "code wrapping". Just enabling code wrapping can make you a little faster by eliminating a lot of left-to-right scrolling you may have been doing in the past. It also makes it so that you never spend a single keystroke manipulating lead white space. I look forward to iterating on this idea and related ideas for a while to see how much we can all get out of it. There may also be some higher order benefits but I won't go into a lot of detail today.

A more subtle upgrade is a new type of "buffer coordinate" called the "apparent character". The apparent character was necessary for virtual white space, because there is now a separation from the text that is actually in the file and the text that is "apparent". This upgrade is filed under "more subtle" because the benefit of it right now is slight. It merely supports code wrapping. But later this will be crucial for adding Unicode support.

As for the month of November, I think it will be best if I take it easy on the new features. Switching to gap buffer bought me some room in the complexity budget, but at this point I think I've overspent. The last week of getting 4.0.12 out was an exercise in not panicking as I realized how many new details I have added to the system. So it seems to me that the wise next step for the project is to take a few versions to let all the dust settle and try to make some more wiggle room in the complexity budget again.

I have also been getting a high number of requests that aren't even for features in the application. Many people are looking for 4coder tutorials for getting started with 4coder. Some people are looking for a "current feature list" so they know if there is a good migration path from their current editor. Some people are looking for a road map, so they can see how I am prioritizing my next steps and make suggestions where they think my plans have a blind spot. So my prime directive for November will be to produce a lot of informational material about 4coder while I do the slow process of "cleaning up" in the application's code base.

Thanks so much everyone! Later!

The 4cpp Lexer: Version 1.1

Allen Webster Sept. 21, 2016, 8:57 p.m.
Dear everyone,

Two weeks ago I shared version 1.0 of the 4cpp lexer with my backers on Patreon, and I promised after a two week period, everyone who came here to this fabulous handmade.network would have free access to the library. But since then I have made a few improvements to the system. The new improvements make the system even easier to use, more efficient, and expose the entire relex system, which now supports the same input chunking that the main lexer supports. Therefore today I'm not going to release the library that I promised to release two weeks ago. Instead I am going to release 4cpp v1.1 !

Right this very instant you can go to 4coder's main page, and get the source under the "Download" tile.

To make your life even better I've put the download link right here!

Enjoy everyone!

The 4cpp Lexer: Version 1.0

Allen Webster Sept. 7, 2016, 2:33 p.m.
A long long time ago, at least a year ago, I decided I would contribute the code parsing system in 4coder as free and open software for our community. I released a little example of what I thought it might be like way back then on Patreon, but since then there's been nothing. I've been waiting because I just wanted to make sure that when I actually "released" something it would be really well thought through.

As of this morning I think a release lexer is ready and I have prepared the package!

The lexer supports all sorts of fancy complex features, like arbitrarily chunked source data, output rate limiting, and user controlled allocation. All with an API that leaves the user in control 100% of the time. As well as a convenience level API for making quick tools that just want to pass in a file and get out the tokens with 0 micromanagement.

Today I will make an early release of the library to all of my backers on Patreon since their support has made this side project possible. Two weeks from today I will release the library to everyone. In the mean time I have posted the 4cpp lexer documentation here* so that everyone can feel a little teased.

Later everyone!

*The library has been officially released now, so instead of downloading the documentation, you can get the library source right here.

The Return of School

Allen Webster Sept. 6, 2016, 8:09 p.m.
Today is my first day of classes in my sixth semester of school at the University of Michigan. I would like to assure everyone updates will still be coming to 4coder and I will continue to stay on top of bug reports and feature requests, but I will be moving more slowly. Last year during my second semester of school I managed to implement: build in editor, keyboard internationalization (although that is a forever ongoing project with Windows), word completion, the first version of direct buffer manipulation API, the query replace and replace range functions, and a Linux port (thanks insofaras!). Hopefully this school year will be similarly productive for 4coder.

Right now I am working on bringing together all of the work I did through the month of August to make 4.0.11 really great. That includes a better file tracker that eliminates a lot of passive per frame CPU usage, a new faster lexer, and access to a file's tokens in the customization API.

Stay tuned this week for an announcement about a special surprise for everyone that I promised a long time ago.

Later everyone!

4coder GUI (should be) returning soon

Allen Webster July 8, 2016, 5:01 p.m.
If you follow the posts on the 4coder Patreon right now, then you know that I stopped posting the 4coder GUI blog posts because I stopped working on the GUI for a little while. What I have been working on was mostly less glamorous. I've been fixing bugs eliminating confusing APIs, both internally and the API exposed for customizations. I've been reimplementing everything I can through the custom API. Most recently what I have done was to use the custom API to construct a new build and goto error work flow. There are twelve internal commands that I can still shift to the custom side. Once that is done, it will be time for the GUI work to resume.

4coder's GUI: Challenges with Scrolling

Allen Webster May 27, 2016, 2:13 p.m.
In last week's post I discussed the rough plan for making 4coder GUI customizable. That plan is somewhat theoretical, and the implementation only began a few days ago. But for the most part knowing that the system will be immediate mode basically informs the rest of the design. There may be a few things that would be done differently if I knew I was dealing with hooks up front, I may do a little more to help the user manage their state, rather than just assuming they'll be able to do whatever they want. Even still, I don't think it would be too difficult to make those tweaks. One way or the other the user will declare a GUI every frame based on whatever rule they want, and the behaviors I want to support are the same either way. So all together I think it is the "immediate mode" part that informs everything else.

Starting from there, the thing that has been the biggest difficulty is the scrolling system. "Insofaras", 4coder Linux extraordinaire, sees my commit's and can probably attest to the number of times I have "fixed scrolling bugs" in 4coder. So what makes scrolling hard? Well there are a number of things. For one thing the requirements of the 4coder scrolling rules are a bit more complex than your standard view moving rules. On top of that the main drawback of the immediate mode API are being more tied to a particular order of events and difficulty with things that involve global layout information, like how tall the layout is. Third I probably made it worse on myself than I needed by being a bit sloppy about scrolling initially.

The Scrolling Rule
The 4coder scrolling rule is just a bit more complex than what a "standard scrolling rule" has to look like. To be clear I don't mean the math for actually computing the rendering offset, or the method of smooth scrolling towards a target location. The hard part is actually setting up a rule for correctly setting the target location. In 4coder I want the cursor to always be in view. In some editors, what actually happens is the cursor can go out of view, then when you do anything, the view jumps back to the cursor, and you lose the position you thought you had. The downside to keeping the cursor in view is that if you look around for something then want to go back to where you were, you need an explicit command for "return to previous location" or something like that. I think that is better though, it involves no surprises.

Now here comes the nasty part. To keep the cursor in the view there are two things you have to do. The obvious thing is that "if the cursor moves out of the view, move the view to the cursor". This is the rule things like games are usually based on, where a character is always in view because the view is locked to them. That goes out the window as soon as you also want to be able to do things like use the mouse wheel to move the view around. If I just follow the first rule, as soon as I scroll too far from the cursor the view will get locked and stop moving until I move the cursor down. So the rule you sort of want is "if the cursor moves update the view as necessary, if the view moves update the cursor as necessary". Depending on how it is set up there is also the question "what if both move?". If both move in 4coder, I just arbitrarily break the tie and say the cursor wins, the view moves to it.

The problem get's even worse than this. Not only can the cursor or the view change. The actual context of scrolling can change too. If I am looking at one file, and the I switch to another, I don't want to immediately scroll from some arbitrary position. So you also need a rule for what happens on a context change, and ideally you want to avoid any scrolling from happening when a context change happens.

One way to solve this and be 100% correct is just say that you never set one of these three things without setting the others. That is, you could write some code like this:
set_cursor(View *view, int pos){
    move_cursor(view, pos);

set_scroll(View *view, float pos){
    move_scroll(view, pos);

set_context(View *view, int pos, float scroll_pos){
    move_cursor(view, pos);
    move_scroll(view, scroll_pos);

Obviously if you do this you're spending the price of fixing multiple variables every time something moves, so if some command set's the cursor several times just because the author decided to be a bit sloppy, you're also setting the scrolling several times. That is probably not a big deal.

In the case of 4coder though, it felt to me like there was a second problem. I had already written a lot of code that just directly set the cursor, set scrolling positions, etc. and I thought going in and rewriting all of those commands would be a bad idea. I retrospect probably could have tried this and it would have been okay, but that's not what I did.

What I actually came up with is that there is a section of code where the scroll position and cursor are allowed to be set. Before that section starts I hold the previous values, and not until the end of the frame do I look and see which ones changed, and based on that apply the fixing rule. This is where the "both changed" possibility comes up. I think if that was the whole story, that system would work just fine... but...

Immediate Mode vs Scrolling
The next issue is more general to any scrolling system in an immediate mode API. Specifically, any API where you allow the user to respond to changes in the scrolling position. If you just said that the GUI system manages the scrolling and the user has no method of responding to scrolling events, then the this is probably not such an issue. For my system though, I wanted the user to get notified whenever scrolling was done by the user, so that they could look at the event and respond. This turned out to be a useful idea, because it allowed the same scrolling system to tie to the cursor as I was discussing before, and tie to the file highlighted for arrow navigation in the file list, which sound similar, but being able to handle them on a case by case basis was very handy.

The API for this that I first had in the GUI system looked something like:

if (gui_get_scroll_vars(&gui, scroll_context_id, &view->scroll_vars)){

This means that the response to the scroll event happens with one frame of lag. The basic idea here is every time the GUI is executed, if the last execution recorded a scroll event, the user sees it here.

This introduces a new detail. The GUI has to keep a record of whether a scroll event happened and what the state of the scroll position should be because it has to report that back on the next frame when gui_get_scroll_vars is called. This introduces a whole new basic problem, which is that now your immediate mode API is actually holding onto a little bit of state that it thinks is authoritative, namely where the scrolling position should be.

Again, by itself this would be fine, but it turns out this does not play so well with the back and forth between the cursor and scroll position. In this system the cursor responds to the motion in the view with one frame of lag. Now if the cursor is moved we announce that the scrolling position should change, and in the next frame that will look like a scrolling even. Then the cursor will be fixed back into the scrolling region, if you updated the cursor again this frame any time before the if (gui_get_scroll_vars(...)) that cursor position is lost.

This nasty dependence on the order of events has been the source of many scrolling and cursor positioning bugs in 4coder. One part of the confusion is that the user has this local copy of the scroll variables and if you ever update that without declaring the change, or you ever change the scroll variables in the middle of the frame due to, say a wheel, and don't have a way to tell the user about the change until next frame, suddenly you have two sets of scroll variables that both think they're authoritative and do not agree with one another. Getting into a mess like that is when you know the architectural decisions you've made need to be rethought.

BUT before I get to the rethinking process, there is one other issue with scrolling in an immediate mode API that deserves a mention. That is, you very often want to know what the size of the viewable region is and what the size of the content that is being viewed is, so that you can limit the edges of the scrolling and do the lerping from the slider's position to the scroll position. But so far, I've assumed everything will operate with one frame of lag, which means sometimes, even if you get everything right with scrolling and cursor position, you could still get bitten by the fact that your scroll limits are off and so you end up thinking the max scroll position is 0 and clamping to that, even though you actually had a perfectly valid scroll position. Fixing that is a matter of undoing the frame of lag, but this is very difficult for a number of reasons, and I will get into that some other time.

The Moral: Know Where the Authoritative State Lives
Getting back to the nasty order of events and dealing with the cursor to view back and forth and negotiating the user's desire to easily update the scrolling variables while the API needs to somehow report scrolling events that only it can detect, and with a frame of lag.

It turns out this quagmire actually boiled down to one mistake. I did not really carefully think about who was going to have the authoritative state for the scrolling variables. In the original system the API thinks it is authoritative and the user is always trying to correct it before it does something wrong, but at other times the user has to query the scroll variables to correct the user copy. This is the real curse of a retained mode API. The API tries to hold the authoritative version but the user needs more control and so the user also tries to have an authoritative version. To fix this I either had to go full retained or full immediate on the scrolling system. I had to either completely seal of the scroll variables, so that the user could only ever read them, and give the user no control over scroll rules; or I had to say, the API never holds something that it believes to be an authoritative set of scroll variables ever.

I went the second route, because I was already depending on being able to do a lot of case specific rules, and it will mean more flexibility in the GUI system over all.

This actually turns out to be a no-brainer once I tried it. Anything in the GUI system that wants to manipulate the scroll variables, now takes scroll variables as a parameter, and then returns new scroll variables if it thinks a change should happen. Then the user looks at that change and can use it, or not as they please and stores their own copy until the next GUI call that needs scroll variables. This way, from the API's point of view, it does not ever hold an authoritative copy, it is just holding a local set of scroll variables and it's job is to report what it would do to those variables if it was in charge. It never really stored them though.

So what happens to gui_get_scroll_vars? We still want a way to know that a scroll event happened, but we don't want to continue getting scroll variables from the GUI system. It turns out the user can just write this as a helper themselves now! Since any GUI side call that changes the scrolling will tell the user what the new scroll variables are right there, the user can then have their own flag for "the scrolling is dirty, activate next frame" if they want. They could also eliminate the frame of lag in their response to GUI events. (Note there is still a layout frame of lag, which as I said, I will look at more later).

That's it for this week everyone, as usual thanks for following!

4coder's GUI: Problem Statement

Allen Webster May 13, 2016, 6:13 p.m.
The primary goal for the 4.0.x family of 4coder versions is to figure out the actual GUI system that 4coder will use and to give absolute control over the GUI to the custom layer. I want to see users be able to delete the code that adds the scroll bar to the file, or write up a tool bar for functions they would rather not tie to a key-combos, or to create drop down menus for their custom word completing system, or to trivially modify open file and new file to work exactly the way they want. It was the big topic on my mind for about six straight weeks.

Recently, I having been trying to figure out the best way to describe everything I have learned in a blog post, but it just does not boil down to a succinct string of text. So starting this week I will begin writing a blog post every week until I have described every last detail. I hope you are prepared for a long journey to catching up with 4coder GUI, because it's time to begin.

"To solve the problem, you must know the problem." - Certainly someone has said this, perhaps a meditating monk or a curmudgeonly programmer. And I am inclined to agree whoever said it, so let us start with the problem statement!

4coder's biggest asset at the moment is that it is extendable through native code compiled from C++. So the GUI also needs to be fully customizable in the same custom layer. When I say *fully customizable* I do not mean in that way that most programs now have one or more plugin systems available that kind of let you interfere with the built in behavior. I mean that even the default behavior itself is just code written in the custom layer. There are a number of benefits to this policy. First, the more default behavior that is implemented on the custom side, the more powerful the custom API will be for everyone else. Second, if the default behavior is close but not quite right for someone, they can easily tweak it however they want without writing an entirely new customization or hacking it in some other undesirable way. Finally, this means that the default behavior becomes well tested example usage code that I would have to write either way. On top of all that, it should also be very simple for the user to write the GUI controlling code. If customizing the GUI is even a little complex, then probably very little of the rest of the system will even be put to use.

The GUI in 4coder has to be driven by both the keyboard and the mouse. For instance, the arrow navigation of the file list was one of the most highly requested features. On the other hand plenty of other people have expressed concern when a new build happens to break something their mouse use to be able to do, and there are still requests for the mouse-wheel-click to paste thing for Linux. So the GUI system must support customization for both of these devices.

When a user is doing something like search or replace in 4coder a little text bar pops in at the top. I am rather fond of not wasting that screen space all the time, so being able to show and hide the bar dynamically is important. When the bar shows up though, there is usually no need for that to effect the placement of the file on screen. To support this that bar "overlaps" the file.

To support requests for things like drop down menus, or auto complete menus, or pop up lists, the system also needs to be able to arbitrarily place a new layout box anywhere in a panel. This may sound like it should just be an extension of the overlapping text bars, but it turns out that if we dig in we will find some tricky distinctions between them, and not until we dig even further will it be clear what the best way to handle these two is.

Almost every single GUI in 4coder requires the ability to scroll. While this is not perhaps a particularly difficult feature to have on it's own. It turns out that in combination with other requirements on this system, the scrolling system becomes non-trivial. In fact to be entirely honest with you, my readers, even now the scrolling system is the most brittle part of the 4coder GUI system, which suggests there may be something better to do with it that I have not found yet.

Each view should have it's own distinct GUI system. The reason for this requirement is that, as I see it, the other option is to say that there is only one GUI system, and the old idea of panels and views just exists within that. I do not see a lot of benefit to putting that much on the user. In my mind a code editor will pretty much always be something divided into panels for viewing different things at the top level. To avoid all the extra complexity that would go into having the custom layer manage the panels and views themselves, I decided there would be one instance of the GUI system within each view, and that the panel/view system would remain a core property of 4coder.

That is it! Put all those requirements together and that is the entire 4coder GUI problem. Next week I will start pointing out all the tension points I have discovered between these requirements and I will explain what it took to solve each one.

Thanks for following everyone!


4coder's GUI: Preparing for Customizability

Allen Webster May 20, 2016, 4:53 p.m.
Last week I discussed all the goals of the 4coder GUI system I have been developing. Now I will look into detail on how I plan to achieve the first big goal: giving the entire GUI to the custom layer and making it as easy as possible.

Any talk about ease of use and GUI will wind up being a talk about how great immediate mode is, and I have already talked about this on a previous blog post. In the 4coder GUI the API design is immediate mode. But because of all the other constraints on the 4coder GUI system, some aspects of it do not look like a typical immediate mode system. I will discuss those points more in future blog posts.

What I want to talk about today is the difference between a library and an engine. 4coder's customization API is not a library, it is an engine. The main difference being that the user of an engine writes code that does not have one controlling stack frame, the user is always expected to return back to the engine. This fact alone does not actually change the principles of API design very much. In an engine it is very easy to convince yourself that everything has to be retained mode. Because it seems controlling code will have the authoritative state and the user is doomed to just asking about that state and issuing commands to change to the state. But this doesn't need to be true, the problem is just how to allow the user's code to have some stable state so that they can have the authoritative state.

There are a few obvious ways to do this. The user can rely on global memory, or you can establish a user data system that allows the user to get some heap memory. After taking that step, they can store any state they want and then all you have to do is be sure to provide an entry point to the user's code where they declare the GUI according to whatever state and rules they want, and make sure this entry point is called frequently enough for the GUI to stay correct. In the case of 4coder it is not hard to guarantee the GUI will refresh frequently enough because the 100% of the GUI declaration code is already contained in one place that can easily be replaced with a call into the custom layer.

So that is one option, and as I said, I feel like this is the "obvious" option.

But there is still an issue with this, which is that the controlling state can now be changed while the GUI control code is not executing. For instance, in 4coder a command might be called, which wants to change from viewing a buffer to a file list. Making such systems work is usually more difficult. A disciplined user can set aside memory that is "only" for the GUI control code, but the temptation to reach in and pull some neat trick is usually non-zero in such a system. Plus always getting all the state stored you actually need can be difficult by itself.

To solve this some of this, I could say that the dispatch to commands is controlled by the GUI controlling code as well, and in fact I plan to do this and go even further with giving control of the command system to the user. But, there are also multiple views who will all need to keep track of their own GUI control code, and as I said last week in my list, I am not willing to merge them all into one control structure. So the issue is pretty much unsolved.

A similar issue made it really hard to implement commands like search, goto-line, and replace in 4coder for a while. These are commands that would want more interaction than simply being called and they involved showing something back to the user. I originally wrote them by having the command be called repeatedly with new input until the command reported that it completed, and it was up to the user to make sure every piece of state that needed to be repeated was stored in a non-local memory. These systems were bug prone, and actually I never released a version with working replace commands when I was trying to make those commands with this system.

There I ran a little experiment, which I still believe was one of the greatest success's of the experimental side of 4coder work so far. I decided all commands should be run in a "coroutine". A coroutine is like a thread that never runs in parallel. You have to explicitly say "I am done for now come back to me later" from inside the coroutine, and the calling code has to later say "okay you should continue now". A lot of people try to use them in conjunction with their fancy multi-threading systems, but from my point of view the entire advantage of the coroutine is as a flow control mechanism for when both sides of an API need long term local storage. Attached to each "yield" and "resume" coroutines and their callers can pass information back and forth.

So the 4coder customization API got the call: "app->get_user_input". This call yields the currently executing command and says to the caller "I am still going, I need more information from the user". When 4coder get's more input from the user it passes it back to the command's coroutine. Now the command can store all of it's state in a local stack frame, where the only way it can be changed by someone else is if you gave them a pointer to the local memory, or if they have a really wild invalid pointer bug.

This change made the complex control flow of the interactive commands a lot more natural. But the command must still exit and relinquish this little island of control that was established.

Based on the success of that experiment I plan to try the same thing for the view control code itself. Each view will run in a coroutine, and it will yield by asking for more messages from the application side. The big difference being that these coroutine's are expected to never terminate, so that the user has a permanent base of local storage. To make the change complete, all other entry points into the custom layer will be removed, so that the user knows exactly where flow control will continue every time their code is invoked by the engine.

So that is it, the entire plan for the future of 4coder customization. I should mention that this coroutine business is the only part of the system I have not implemented yet, so I am only arguing that I think it will be neat, I do not yet have the results of this experiment. However, that has been the plan that everything else, which I will discuss in future weeks, is building towards.

Until then, thanks for following everyone!

New 4coder Version: alpha 4.0.3

Allen Webster May 10, 2016, 6:49 p.m.
Hey folks,

Today I am announcing the first 4coder build to come out of the "Summer of 4coder". This new build is the first to feature the GUI system I have discussed in older blog posts, and now that it is out I will take a little more time to describe some of what I discovered, what I have come up with so far, and what I would like to do even better.

In the mean time if you are supporting the project be sure to go check out the new build!

April Shenanigans and the Summer of 4coder

Allen Webster April 29, 2016, 6:04 p.m.
One whole month has passed but there has not been a single 4coder update. I was hoping all month that today there would be an update with new GUI stuff ready to go, but it's just not going to happen. The new theme editor is getting there pretty quickly, and there are some other improvements I would like to have in the next version. Specifically I want to address the high idle CPU usage by going to a system that is more event driven.

Now for the good news. With school year over though the way is cleared for an entire summer of 4coder. I have high hopes for huge updates this summer. I plan to open the customization layer up even more. These new upgrades will hopefully facilitate projects like 4coder vim keys (by ChronalDragon) and providing a customizable GUI for various debugger projects that have cropped up. But my biggest goal of the summer is to start cracking the code intelligence that I was imagining when I first started 4coder. I am making no promises but I think there is a lot to look forward to for the next few months.

As always, thanks for following, and thanks to my backers for their patience through this slower month.
See you around everyone!

Moving to the Handmade Network!

Allen Webster April 24, 2016, 3:08 p.m.
So thanks to the works of the Handmade Dev guys, 4coder is going to have a new home right here on handmade.network!

I mean first of all, the projects are all exciting and I just want to be nearby when awesome stuff happens, but also... look at this site I mean for literally no work at all the 4coder blog suddenly looks about a hundred times better than it did back when I was trying to design it myself. Also did you notice how fast everything is? It is off the hook people.

If you want to check out the old blog, if it is still up you can find it here. My plan is to eventually ditch that blog entirely and move all the old posts here. So from now on you can just follow my absurd blog posting here.

Thanks a ton to the handmade dev guys.

Later everyone!

SIL Open Font License

C Allen Webster April 23, 2016, 1:39 a.m.
The following parts of the Software are separately licensed as follows:

- The Liberation font family is licensed under the SIL Open Font License (version 2 onwards).
The full text of this license is available in the accompanying 3rdparty/sil.txt file

- The Hack font family is licensed under the a modified SIL license
The full text of this license is available in the accompanying 3rdparty/hacksil.txt file

- The Inconsolata font family is licensed under the SIL Open Font License
Copyright (c) 2011, Raph Levien ([email protected]), Copyright (c) 2012, Cyreal (cyreal.org)
The full text of this license is available in the accompanying 3rdpart/sil.txt

- The Cutive font family is licensed under the SIL Open Font License
Copyright (c) 2012 by vernon adams ([email protected])
The full text of this license is available in the accompanying 3rdpart/sil.txt

The 4coder License

C Allen Webster April 23, 2016, 1:39 a.m.
4coder-alpha License

The Software ("4coder", "4ed.exe") is Copyright 2015 by Four Tech LLC, all
rights are reserved. Anyone who has purchased a copy of the Software,
("The User"), is granted a personal, non-assignable, non-transferable,
license to use the Software for personal or commercial uses.

The User may not redistribute, sub-license, or resell the Software. The User is
permitted to make an unlimited number of copies of the Software which are subject
the the aforementioned restrictions.

The Software is provided "as is" without warranty of any kind, either express or
implied, including without limitation any implied warranties of condition,
uninterrupted use, merchantability, fitness for a particular purpose, or