3
\$\begingroup\$

Started picking up D recently. I wrote an application to create journal entries (text files) based on user input.

//this program will write to files. It should be able to read them.
//implement a command interface?
import std.stdio;
import std.string;
import std.datetime;
import fileio = std.file;
import std.conv;

enum Commands {exit = "EXIT", create = "CREATE"};

string menuText(){
    return "\nType a command:\n\t- create\n\t- exit\n>";
}

void checkJournalEntriesFolder(){
    string path = "journalEntries/";
    if(fileio.exists(path) == 0){
        writeln("Creating a journalEntries folder for you.");
        fileio.mkdir(path); 
    }
}

string getFileName(){
    return "entry_" ~ std.conv.to!string(stdTimeToUnixTime(Clock.currStdTime())) ~ ".txt";
}

int main(string[] argv)
{
    writeln("\nWelcome to myJournal.");
    checkJournalEntriesFolder();
    string mode = "COMMAND";
    char[] buf;
    Commands command;
    while (mode != "EXIT"){
        while (mode == "COMMAND"){
            string journalContent;
            write(menuText);
            stdin.readln(buf);
            switch(toUpper(buf[0..$-1])) // cut off the /n at the end of the buffer.
            {
                case command.exit:
                    {
                        mode = "EXIT";
                        writeln("Oh, I'll exit.");  
                        break;
                    }
                case command.create:
                    {
                        writeln("create journal entry selected");
                        mode = "CREATE";
                        //create file
                        writeln("You are now typing in your journal.");
                        writeln("To exit this file, type #EOF");
                        writeln("----------------------------");
                        break;
                    }
                default:
                    {
                        writeln("\nunrecognized command");                  
                    }
            }

            while (mode == "CREATE") {
                stdin.readln(buf);
                if(buf[0..$-1] == "#EOF"){
                    writeln("----------------------------");            
                    mode = "COMMAND";
                    checkJournalEntriesFolder(); // double check, in case the user deleted it.
                    string filename = "journalEntries/" ~ getFileName;
                    fileio.write(filename, journalContent[0..$-1]); //Dont include the blank line.
                    writeln("File Saved.");
                } else {
                    journalContent ~= buf;  
                }
            }
        }
    }
    return 0;
}

Possible Improvements:

  1. Maybe be able to move throughout the document once it is open (right now if you hit enter, you cannot move to the previous line).
  2. Make command / insert mode more like vi.
  3. Edit existing files.

I am very new to D, so I expect this code will be tore up. I've done some C++, but it has been a while.

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

I'm not entirely sure what you are asking for, but if this were my program I would do a few things differently.

SQLite

I would place the journal entries in a sqlite database rather than raw files and directories.

D provides an interface to sqlite. Sqlite provides great abstraction over raw files. Keeping your files consistent, and not corrupting them is difficult. sqlite already does the right thing, and more!

Command Pattern instead of switch

I would provide a nicer abstraction for commands instead of a switch statement. This Python code works as a template.

By implementing a switch statement, each new command increases the cyclomatic-complexity of the main() function. Thus your testing requirements increase exponentially. By breaking out each command to implement an ICommand interface, your testing requirement increases linearly. The visitor pattern might also provide a nice mechanism to process each command.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.