Compare commits

...

10 commits

4 changed files with 192 additions and 6 deletions

42
man/fortune-cs.6 Normal file
View file

@ -0,0 +1,42 @@
.Dd $Mdocdate$
.Dt FORTUNE-CS 6
.Os
.Sh NAME
.Nm fortune-cs
.Nd a no-nonsense fortune cookie program
.Sh SYNOPSIS
.Nm fortune-cs
.Op Ar source
.Nm fortune-cs
.Op Fl hlv
.Nm fortune-cs
.Fl m Ar file1 Ar file2
.Sh DESCRIPTION
.Nm fortune-cs
is a sensible, straightforward replacement for
.Xr fortune 6 . Its options are as follows:
.Bl -tag -width Ds
.It Fl h , Fl -help
Shows a brief help text.
.It Fl l , Fl -list
Lists files in the fortune directory
.Po Ev FORTUNE_CS_DIR
.It Fl m , Fl -merge Ar files...
Prints all distinct lines from the provided files to standard output.
.It Fl v , Fl -version
Shows version information.
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It Ev FORTUNE_CS_DIR
Any existing directory. This sets the base directory to pull fortunes from. Default:
.Pa /usr/share/fortune-cs
.Sh FILES
.Bl -tag -width Ds
.It Pa /usr/share/fortune-cs/
The default fortune directory, containing text files with one line per fortune.
.El
.Sh SEE ALSO
.Xr fortune 6
.Sh AUTHORS
.An -nosplit
.An Valerie Wolfe Aq Mt sleeplessval@gmail.com

40
src/Info.cs Normal file
View file

@ -0,0 +1,40 @@
using System;
using System.IO;
public static class Globals {
public const string VERSION = "0.1.0";
public const string DEFAULT_PATH = "/usr/share/fortune-cs/";
}
public static class Usage {
public static void HelpText() {
VersionText();
Console.WriteLine(@"Valerie Wolfe <sleeplessval@gmail.com>
Shows quotes from a set of files.
usage: fortune-cs [flags] [source]
args:
[source] Show a quote from a specific file
flags:
-h, --help Shows this help text
-v, --version Shows version information
-l, --list List files in the fortune directory
-m, --merge [files...] Output all distinct lines from a set of files");
}
public static void ListText(string[] files) {
foreach(var file in files) {
var fileName = Path.GetFileNameWithoutExtension(file);
Console.WriteLine(fileName);
}
}
public static void VersionText() {
Console.WriteLine("fortune-cs v" + Globals.VERSION);
}
}

View file

@ -2,25 +2,75 @@ using System;
using System.IO;
using System.Security.Cryptography;
// handle help flag
if(Utilities.HasFlags(args, "-h", "--help")) {
Usage.HelpText();
return 0;
}
// handle version flag
if(Utilities.HasFlags(args, "-v", "--version")) {
Usage.VersionText();
return 0;
}
// collect nonflag args for merge or file selection
var arguments = Utilities.CollectArgs(args);
// handle merge flag
if(Utilities.HasFlags(args, "-m", "--merge")) {
Utilities.Merge(arguments);
return 0;
}
// get resource path from var or default
string resourcePath = Environment.GetEnvironmentVariable("FORTUNE_CS_DIR");
if(resourcePath == "" || !Directory.Exists(resourcePath))
resourcePath = Globals.DEFAULT_PATH;
// pull file arg if provided
string file = null;
if(arguments.Count == 1) {
file = arguments[0];
// if the file doens't exist, see if it's in `resourcePath`
if(!File.Exists(file)) {
if(!file.EndsWith(".txt"))
file = file + ".txt";
file = resourcePath + file;
if(!File.Exists(file)) {
// don't try to read a file that doesn't exist
Console.WriteLine($"fortune-cs: no file '{file}' found.");
return 2;
}
}
}
// make sure fortune directory exists
var resourcePath = "/usr/share/fortune-cs/";
if(!Directory.Exists(resourcePath)) {
Console.WriteLine("fortune-cs: directory '/usr/share/fortune-cs/' does not exist");
Console.WriteLine($"fortune-cs: directory '${resourcePath}' does not exist");
return 1;
}
// pull file list
var files = Directory.GetFiles(resourcePath, "*.txt");
// choose a file and line
var file = files[RandomNumberGenerator.GetInt32(files.Length)];
// handle list flag
if(Utilities.HasFlags(args, "-l", "--list")) {
Usage.ListText(files);
return 0;
}
// choose file if not provided
if(file == null)
file = files[RandomNumberGenerator.GetInt32(files.Length)];
// read the file and choose a line
var lines = File.ReadAllLines(file);
var line = lines[RandomNumberGenerator.GetInt32(lines.Length)];
// process escape codes
// process line breaks
line = line.Replace("\\n", "\n");
// write
// write the fortune
Console.WriteLine(line);
return 0;

54
src/Util.cs Normal file
View file

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.IO;
public static class Utilities {
/// <summary>
/// returns a `List` of all non-flag arguments
/// </summary>
public static List<string> CollectArgs(string[] args) {
var output = new List<string>();
foreach(string arg in args)
if(!arg.StartsWith("-"))
output.Add(arg);
return output;
}
/// <summary>
/// checks if a given flag is set in `args`
/// </summary>
public static bool HasFlags(string[] args, params string[] flags) {
foreach(string flag in flags)
// using `Array.IndexOf` since including Linq for `array.Contains` increases binary size
if(Array.IndexOf(args, flag) != -1)
return true;
return false;
}
/// <summary>
/// outputs all unique lines from all files in `files` to stdout
/// </summary>
public static void Merge(List<string> files) {
// hashset to prevent duplicates
var members = new HashSet<string>();
// iterate over all paths given
foreach(var file in files) {
// skip nonexistent files gracefully
if(!File.Exists(file))
continue;
// iterate over lines
var lines = File.ReadAllLines(file);
foreach(var line in lines) {
// prevent duplicates
if(members.Contains(line))
continue;
members.Add(line);
// emit to stdout
Console.WriteLine(line);
}
}
}
}