Compare commits
10 commits
Author | SHA1 | Date | |
---|---|---|---|
a98944708c | |||
028972d707 | |||
1b38e781ad | |||
d491b047d5 | |||
6c2d327c4b | |||
54cceabdce | |||
7d42eaf2b8 | |||
348f59b44d | |||
dec2f6ff19 | |||
3902f5e3b7 |
4 changed files with 192 additions and 6 deletions
42
man/fortune-cs.6
Normal file
42
man/fortune-cs.6
Normal 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
40
src/Info.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
54
src/Util.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in a new issue