ΨευδΩρίγενης

coding

See part 1 and part 2.

This one is a bit of an interlude.

As I explained last time, I had sorted out the basic functionality for terminal output. This means that if I wanted to say, write some text in red someplace else in the program, I just have to call:

TextFormat.colorWrite("text to write", "Red");

I also did a couple of others, including one to do a complete line (the one above doesn't skip to a new line, which allows for multiple colors in a line), and one for centering. This last was also nice and simple: all it had to do was figure out how long the text to be written was, figure out how wide the window was, and from that it's easy enough to calculate how much whitespace is needed on the left to make things line up. (This of course supports color as well.) I was then able to add an optional width, meaning it'll center text within an imaginary bounding box (which is useful for “windows” within the console).

Where I got bogged down was in actual editing. It's trivial to just have the user start typing and show it, but as soon as even basic functionality, like word wrap, comes into the occasion, things become much more complicated.

I won't bore you with the details, but I was getting stuck with trying to keep track of where everything is and display it properly. I think I have a method now that will work, but I haven't been able to put it into practice just yet.

In the meantime, I decided to put some work into the interface, which also meant figuring out what kinds of functionality I actually wanted to include. I also haven't had much time to devote to this project this week, thanks to various other things demanding my attention. But I've managed to get a basic idea for a layout, and have some helper functions to draw the full window border and sub-panels.

The sub panel code was an interesting challenge, but I definitely learned some things. It works as a function that I call, giving it a starting X and Y, how wide it should be (either in absolute columns or a percentage of the window), as well as some further attributes like a title, border style and color, etc. Soon I'll add code for background colors too, but that needs some changes elsewhere (such as in my colored text methods).

The first sub-panel I'm putting together is a calendar, which will show when previous entries have been made and allow the user to jump to them for viewing or editing. I won't be able to do much of this until I have the actual editing code in, of course, but I can at least do some basics. The last thing I've implemented so far was getting it put the first week of the current month into a grid. This is harder than it sounds.

Case Study

Remember, the computer doesn't know anything about anything. It can only do what I've told it to do, and can only use new information that I've told it to figure out.

All it can bring to the party is a date. So that's my starting point.

In C#, there's what's known as a DateTime object. This is its own category of variable, and it can hold various parts of a date and time (from years to milliseconds). So my method works like this.

First: get today's year, month, and day, since the first thing to be displayed is the current month (and scrolling through months later will need a starting point). It then isolates the month, and gets its name (so I can use that as the heading). Then there's a built-in method that returns a number from 0-6 based on what day of the week a given date is (with 0 being Sunday and 6 being Saturday).

This proved to be perfect. From there, I just built a 7-element array, with each element representing a day of the month for a week. Like in most languages, arrays in C# are zero-indexed, which means that the first element is at place 0 rather than 1. Since I also have a 0-6 number associated with the day of the week, I can put the first of the month in its proper place just by assigning it:

arrayOfDays[dayOfWeek] = 1;

The bit in brackets tells the computer which specific element should equal 1.

From there, it's a simple matter of getting the number of days in the previous month (and there's another built-in method for that). That one goes in arrayOfDays[dayOfWeek - 1], then keeps adding smaller numbers until we get to 0. Then it starts at wherever the 1 is and adds in 2-whatever. There's some additional logic to check for edge cases (like I can't tell it to use dayOfWeek - 1 when dayOfWeek is 0, since there is no element at -1).

So now I have an array with 7 numbers, but it needs to be output. That too is easy enough: just go through each element of the array, converting it to a string (since it's stored as an integer) and adding a couple spaces so that it'll print properly:

string weekText = "";
foreach (int day in arrayOfDays) {

     weekText = String.Concat(weekText + "  " + day.toString());

}

From there, it's a simple matter of putting the cursor in the correct place, then using my centered text function with a width of 2 columns less than the width of the box (so that it doesn't overwrite the box's borders). Done!

This was definitely the hard part, since I had to deal with finding the beginning of the month. From there I can just build groups of 7 days until I get to the end, then start over at 1 to fill out the row.

But even then, I'm not quite done. I have two more main to-dos for this piece:

  1. Update my centered writing function to allow printing more than one color. This is something I wanted to do anyway, and for the calendar it'll let me dim the dates that aren't in the current month, which is a nice aesthetic touch.

  2. Have some logic that will keep track of certain dates as including an entry. I don't have file reading stuff in yet, but I can use some test code to make sure that the pieces will be in place so that when I do, and can load a list of dates when journal entries were done, the calendar will be ready to handle them.

This part shouldn't actually be too hard. C# allows a function to take an unknown number of variables. Although as I think about it, since I'll need to be able to pick random/arbitrary numbers to output this way (i.e. it won't always be the first and third numbers in the row, for example), it'll probably be better to have a separate function within my calendar drawing framework rather than trying to force the more general one into the role.

Phew. I'm sure that was far too much information, but it's certainly helpful for me to put my thinking down into some kind of order so that I don't go in 100 tangents at once.

#coding #journalApp

Journaling About Coding a Journal | Part 2

Part 1 is here.

One of the first things that struck me about how C# works is the fact that it wants everything to be in a class. I vaguely recall classes being a thing in C++, but it was something I never really messed around with.

The nice thing is that the way it handles namespaces and file inclusion makes a whole lot more sense.

First: no include directives! For core libraries, you can include a Using directive to shorten the typing, but like with C++, everything is still accessible by defining the scope at the time you're using it. This includes third-party libraries too (the complier uses a manifest file to know where everything is instead).

Namespace also feels a little more flexible to me, although I'm not sure it's actually that different from C++. What I really like, though, is that you can organize files without having to include them. As long as everything uses the same namespace, it's all accessible right off the bat.

The requirement to use classes for everything also really helps with organization; it forced me to divide things up anyway, so I may as well categorize the various functions I'm putting together.

Now in Technicolor

One of the things I decided early on was that I wasn't going to use any third-party libraries. I'd take a look at how other people had done things, but I wanted to do everything from scratch. I'll learn a lot more that way, and it's more fun to figure out a puzzle than simply apply a tool.

The first thing I wanted to do was style text output. Terminal apps are nothing but text (although I've seen some ways to change that...), so I want to get the most of it.

There's a built in ConsoleColor attribute (actually an enum), but that only works with Windows. Since I'm developing on Linux (and want it to be cross-platform anyway), I had to find something else. Meanwhile, most *nix-based consoles (plus MacOS') support a much greater color depth than Windows.

For the *Nix consoles, I was able to do some tinkering and found that they'll recognize ANSI escape codes. These are a specific sequence of characters where, if you output them to the console, they'll change the color and what-not. I originally had an issue with Konsole, KDE's default console, not recognizing them. I later discovered that this was actually a matter of the escape characters having to be capitalized. It really was that simple, and was something I discovered completely by accident.

So for my original implementation, I figured I'd just detect the OS, and then my color output function would actually style the text based on that. This was simple enough, and worked fine, even if I couldn't help but feel it was a little clunky, or at least inefficient.

I was looking up something else when, lo and behold, I found the escape character that the Windows terminal recognizes. The documentation is a little opaque, in that it spreads the information over a couple of pages, but it turned out to be the upper-case version of what I had been using for *Nix all along. No more duplicate code!

...Or so I thought. The problem is that Microsoft has a pathological aversion to following standards. In order to get the Windows console to use an escape sequence with colors, you have to use the SetConsoleMode function, which is part of the standard C library, but not C#. I could implement this directly in C# by loading a Windows DLL on runtime and then executing the code that way. There are also some third-party libraries that hook in at runtime to give this functionality. But in either case, I'd have to have OS-detecting code (since there's no need for the DLL on anything else). At that point I'm much better off just using the built-in color coding for Windows and escape sequences everywhere else.

The code is simple enough. I have a public class called Globals, which associates a number with some simple color names (and the number depends on the platform, i.e. Windows or something else). Then my color writing function has an if/else block to use the correct language for the OS. Honestly, from what I've seen my approach is smaller in terms of lines of code than any other implementation I've seen, all of which seem hell bent on over-complicating the whole thing.

I also have a couple of additional helper functions, to do things like bold and underlining (even if Windows doesn't support those at all), as well as center text on screen.

Finally, I've got some basic file saving logic, but I'm not getting too deep into this until I get the editor part working. After all, I won't know quite what a given “entry” is going to look like until much further down the road.

Next time, the beginnings of an editor, which causes a great deal of headache.

#coding #journalApp

I got my first ever computer in 1990, an IBM-PC clone that my dad and grandfather bought me for my birthday that year. One or both of them recognized, with no small amount of foresight, that these things were the future, and that it was important for me to get in on them early. My maternal grandfather, meanwhile, was an electrical engineer working for various telcos, so I got no small amount of exposure there as well.

It was actually him that first introduced me to programming, showing me some basics of BASIC (heh). I never really got past this, though, since I was rubbish at system-oriented thinking. (This would make a lot of sense when I was diagnosed with ADHD in my 30s). My next real foray was burgeoning web design in the late 1990s, including ActionScript, which was the primary language behind Flash. This was my first introduction to C-style syntax, and I continued chipping away (including a summer C++ class during law school). But I continued to struggle with being unable to see past the piece that was immediately in front of me.

Once I had the revelation that was prescription stimulants, I decided to give it another shot, and it is amazing how much more sense this stuff makes.

Meanwhile, I've started using Linux almost exclusively over the last 6 months or so, after being half-and-half for the previous year. (I now use Windows exclusively for gaming.) I found myself really enjoying the modern generation of console apps, basically programs that work in a terminal window (think a DOS prompt if you're on Windows). Around the same time I decided to start journaling again, and so set out to look for a good console-based journal.

I did find jrnl, which serves, but which is a little too minimalist for me. On the other end of the spectrum is org mode for emacs, which didn't quite work the way I wanted it to.

So, these things came together, and I decided to write one.

Finding a Language

This section may occupy a weird space of being too technical for non-programmers, and too naive for the coders. It's a skill.

Of course, I needed a language to use. I wanted to use something lower-level than python, in the hopes that I could grow into the greater control. Plus there's a performance hit to it compared to something else, which would matter down the line (but obviously not for a text-based journal). On the other hand, I decided that C++ was a little too steep of a learning curve right now, although it's something I'd like to revisit in the future.

I also looked at Rust, which is a relatively new language maintained by the Mozilla Foundation. There are a lot of things that I find intriguing: the way it handles asynchronous I/O (basically the way you set up one part of the code to wait for something while other parts keep going) seems to make a lot of sense to me, and I like that it's really conscious of memory usage and referencing.

On the other hand, its relative youth was also a hindrance. It was only released in 2010; by comparison, C++ was first released in 1985. The documentation isn't the greatest, and as of right now there aren't any particularly good ways to do GUIs. There are a couple projects involving creating bindings for existing frameworks like GTK, but it all felt very piecemeal. (I found the same thing with Go.)

Meanwhile, I had been working on a website redesign for my martial arts school. My cohort in this process is a full-time developer, and so we're using Angular. This has a core written in C#, and I was reminded that this was a thing. I'd previously only seen it as the language the underlies the Unity game engine, but I hadn't used it very much.

What really raised my interest, though, was the discovery that Microsoft had ported the core libraries for C#, the .Net Core, to other platforms. C# could already work as a cross-platform language, but this would make it a lot easier.

In terms of my IDE (the actual program in which I'm writing the code), I had already been using Visual Studio Code to do web-based project I'm working on, and really like it. It's extensible enough, cross-platform (so I can work on my Windows machine too without changing environment), helpful without taking too much control out of the way, and visually enjoyable. I do also use good ol' emacs on my laptop on occasion.

This was my starting point. Next time will be the overall design I'm going for, and my early progress (and wall-hitting).

#coding #journalApp