TODO APP Design

Just as Solitaire and Minesweeper were games included with Windows intended to teach people how to use the mouse accurately, the VM/OS TODO application is intended to teach the reader how one might use VM/OS APIs for their own projects in the future. Therefore, the emphasis is on being a complete yet simple application.

A secondary goal of the application is to help me, the author, learn more about how to evolve VM/OS going forward. This includes several areas of consideration:

Depending on what I learn, I might write more blog articles in the future.

So, without further ado, let’s get to learning. Let’s start by coming up with a crude spec of the application.

Design Constraints

Debug Console Characteristics

At the moment, VM/OS lacks a graphical user interface, or for that matter, even a textual user interface. Heck, it doesn’t even support a command-line interface yet!

What it does currently support, however, is an operator’s console. For those familiar with the old IBM System/360 and early System/370 mainframes, you might remember these machines having operator consoles which were distinct from normal user terminals. The idea behind these terminals was simple: humans are an extension of the supervisor-level kernel. Your application might need the resources in a data set named FOO.BAR, but that data set might not be currently online. The operating system would take it upon itself to ask a human operator for help via this operator’s console. If the operator cannot locate the volume on which this data set is located, she can deny the request. Or, if the volume is successfully mounted, she can respond with a success code, and the system call can complete.

The same idea applies here: the debug console API is intended for things like supervisory log messages, and where necessary, soliciting critical input from a human operator. Although the actual API is character-oriented, the supervisor-side buffer management is line-oriented. That is, output to the console isn’t guaranteed to flush until you send a new-line or carriage return character; likewise, input from the console isn’t guaranteed to be received until a new-line or carriage-return is received.

IMPORTANT: The debug console I/O API is character-oriented, but behind the scenes, it is actually a variable-length, record-oriented interface. Sending output is quickly handled, so it works well in VM/OS, even in a multitasking environment. Accepting input, however, will block the supervisor until a full record is received, at which point characters will trickle in. Thus, multitasking will stop until a full input record is received.

NOTE: Unlike the mainframe’s console, soliciting input via the operator’s console is currently an emulator-blocking operation in VM/OS. I cannot emphasize this enough! This deficiency might change in the future; but for now, I’m lazy and this will remain a limitation going forward. OR, if you’re up for it, feel free to submit a patch to fix this! I’d certainly welcome it.

This warning is important to keep in mind; however, since the debug console is literally the only form of operator I/O currently supported (as I write this article), we are forced to use it for our TODO app as well. Thus, the design and architecture of the TODO application is strongly influenced by this limitation.

NOTE: As VM/OS gains more user interface options, we will adapt the TODO application accordingly. Stay tuned!

Memory Management

Another limitation to keep in mind is that we don’t really have any standard libraries that we can depend on yet. For that matter, we don’t even have the benefit of a higher level language yet. (Forth will be coming soon enough, but it’s not here yet.)

For this reason, memory management will be almost entirely static, not dynamic. This influences the design of various data structures. It will also have some impact on application performance. Since this application is intended first and foremost to be a tutorial, however, it is explicitly not a feature that this application be fast.

On Startup

The TODO application does not accept command-line arguments. It will function entirely through the use of menus presented to the user via the debug console.

When run, you are presented with a menu; it might look something like:

Welcome to TODO App V0.1

Select an option:

 1. Create a new TODO list.
 2. Load an old TODO list.
 Q. Quit

Cmd (1,2,Q,?) => _

If you select option 1, it will initialize its internal memory so that you have a fresh, 0-length TODO list in memory. The default save file will be set to TODOS.UNSPECIFIED, which you can alter later. It’ll then drop you into the same main menu as if you had loaded an old TODO list.

If you select option 2, it will then ask you for a filename. The filename must refer to a TODO file somewhere in one of the configured sandboxes. That file is loaded, and then you’re dropped into the main menu.

Typing ? will just re-display the menu. This might not be useful at first; however, as you become more proficient with the UI and you start using compound commands, you can use this as a reminder.

The Q (capital Q) command will terminate the program and discard any unsaved changes.

The main menu is probably where you’ll spend most of your time. It lets you manipulate the TODO item list as a whole, including some basic CRUD features (e.g., create a TODO, discard a TODO, show current set of TODOs, and so forth).

Main Menu

Select an option:

 1. Create a new TODO item.
 2. Discard a TODO item.
 3. Discard all items marked complete.
 4. Archive all items marked complete.
 5. Show existing TODO items.
 6. Save TODO items to a file.
 Q. Return to previous menu.

Cmd (1,2,3,4,5,6,Q,?) => _

Create a new TODO Item Dialog Selecting this option will let you create a new TODO item, and append it to the list of TODOs. When done, it’ll let you know the ID number of the TODO created. This ID number is useful, as with it you can later delete it, mark it done, etc.

NOTE: Don’t worry about remembering IDs for every TODO, however; you can always use the Show existing TODO items option to see the ID of any TODO currently in the database. Deleting and archiving TODOs will change the IDs of the remaining unfinished TODOs.

Enter TODO description (max. 64 characters):
Name of TODO item goes here.<-'

TODO #123 created.

Cmd (1,2,3,4,5,6,Q,?) => _

Discard a TODO item Dialog Selecting this option lets you discard a single TODO item. The item does not need to be marked completed.

NOTE: Discarding a TODO n will cause all subsequent TODOs (n+1, n+2, etc.) to be renumbered (n, n+1, etc.).

Enter TODO number to delete: 123<-'
TODO #123 removed.
Cmd (1,2,3,4,5,6,Q,?) => _

It then goes back to main menu.

Discard all completed items. This scans the entire database of TODOs and removes all items which have been marked complete. In doing so, it reports to the screen which items it removed. Then it drops you back into the main menu.

Are you sure (Y/n)? y<-'
...
<list of TODOs elided>
...
Cmd (1,2,3,4,5,6,Q,?) => _

Archive all completed items. After selecting this option, a filename will be requested. Once provided, the database is scanned for all completed TODO records, each of which is recorded in the file specified. After the file is written, it’ll drop you back into the main menu.

The archive file is created fresh if it doesn’t already exist. Otherwise, the file will be appended to. To review the contents of an archive file, run the TODO app and load the archive file as you would any other saved TODO list.

Archiving does not delete the completed tasks; use the Discard all completed items menu option separately for this.

Archive to file: sandbox/todos.done.2025.jan.04<-'

Cmd (1,2,3,4,5,6,Q,?) => _

Show Existing TODO Items dialog This option will place you into a separate menu, which lets you browse the current set of TODOs. This menu is discussed below.

Save TODO items to a file dialog This option will present a submenu:

Save to:

 1. Current file: sandbox/todos.working.2025
 2. New file
 Q. Cancel (Quit back to previous menu)

Cmd (1,2,Q,?) => _

Option 1 lets you save the current TODO database to the currently selected file, if any. If no file yet exists, it will report the filename as TODOS.UNSPECIFIED.

Option 2 lets you save to a completely new file. It’ll ask you for a filename, and will save to that newly specified file. The new file will become the currently open file.

The Cancel option lets you abort the file save operation in case you selected that option by mistake.

Show Existing TODO Items Menu

This menu is used to browse through the set of current TODOs in the database. It will look something like the following, but with more relevant TODO items.

Select an option:

 N. Next page.
 P. Previous page.
 X. Toggle complete flag.
 Q. Return to previous menu.

999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text
999. [ ] TODO text

Cmd (N,P,X,Q,?) => _

This article is pretty lengthy already, so I’m just going to summarize. I think you’re intelligent enough to expand upon these bullets on your own:

Conclusion

We took the time to specify a basic TODO application. Our next steps are to look a little bit deeper. The most obvious next step is to consider the data structure used to represent the TODO database, which you might have guessed by now is just going to be a flat array.

But, much more interesting to me are the menus. The regularity of how each menu is displayed and how its input is handled suggests that it can be heavily data-driven. I’ll save that discussion for next time.