using System;
using System.IO;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace De.Thekid.INotify
{
/// See also inotifywait(1) - Linux man page
public class ArgumentParser
{
/// Helper method for parser
protected string Value(string[] args, int i, string name)
{
if (i > args.Length)
{
throw new ArgumentException("Argument " + name + " requires a value");
}
return args[i];
}
/// Tokenizes "printf" format string into an array of strings
protected string[] TokenizeFormat(string arg)
{
var result = new List();
var tokens = arg.Split(new char[]{ '%' });
foreach (var token in tokens)
{
if (token.Length == 0) continue;
if ("efwT".IndexOf(token[0]) != -1)
{
result.Add(token[0].ToString());
if (token.Length > 1)
{
result.Add(token.Substring(1));
}
}
else
{
result.Add(token);
}
}
return result.ToArray();
}
private void ParseArgument(string option, string[] args, ref int i, Arguments result)
{
if ("--recursive" == option || "-r" == option)
{
result.Recursive = true;
}
else if ("--monitor" == option || "-m" == option)
{
result.Monitor = true;
}
else if ("--quiet" == option || "-q" == option)
{
result.Quiet = true;
}
else if ("--event" == option || "-e" == option)
{
result.Events = new List(Value(args, ++i, "event").Split(','));
}
else if ("--format" == option)
{
result.Format = TokenizeFormat(Value(args, ++i, "format"));
}
else if ("--exclude" == option)
{
result.Exclude = new Regex(Value(args, ++i, "exclude"));
}
else if ("--excludei" == option)
{
result.Exclude = new Regex(Value(args, ++i, "exclude"), RegexOptions.IgnoreCase);
}
else if (option.StartsWith("--event="))
{
result.Events = new List(option.Split(new Char[]{'='}, 2)[1].Split(','));
}
else if (option.StartsWith("--format="))
{
result.Format = TokenizeFormat(option.Split(new Char[]{'='}, 2)[1]);
}
else if (option.StartsWith("--exclude="))
{
result.Exclude = new Regex(option.Split(new Char[]{'='}, 2)[1]);
}
else if (option.StartsWith("--excludei="))
{
result.Exclude = new Regex(option.Split(new Char[]{'='}, 2)[1], RegexOptions.IgnoreCase);
}
else if (Directory.Exists(option))
{
result.Paths.Add(System.IO.Path.GetFullPath(option));
}
}
/// Creates a new argument parser and parses the arguments
public Arguments Parse(string[] args)
{
var result = new Arguments();
for (var i = 0; i < args.Length; i++)
{
if (!args[i].StartsWith("--") && args[i].StartsWith("-") && args[i].Length > 2)
{
string options = args[i];
for (var j = 1; j < options.Length; j++)
{
ParseArgument("-" + options.Substring(j, 1), args, ref i, result);
}
}
else
{
ParseArgument(args[i], args, ref i, result);
}
}
return result;
}
/// Usage
public void PrintUsage(string name, TextWriter writer)
{
writer.WriteLine("Usage: " + name + " [options] path [...]");
writer.WriteLine();
writer.WriteLine("Options:");
writer.WriteLine("-r/--recursive: Recursively watch all files and subdirectories inside path");
writer.WriteLine("-m/--monitor: Keep running until killed (e.g. via Ctrl+C)");
writer.WriteLine("-q/--quiet: Do not output information about actions");
writer.WriteLine("-e/--event list: Which events (create, modify, delete, move) to watch, comma-separated. Default: all");
writer.WriteLine("--format format: Format string for output.");
writer.WriteLine("--exclude: Do not process any events whose filename matches the specified regex");
writer.WriteLine("--excludei: Ditto, case-insensitive");
writer.WriteLine();
writer.WriteLine("Formats:");
writer.WriteLine("%e : Event name");
writer.WriteLine("%f : File name");
writer.WriteLine("%w : Path name");
writer.WriteLine("%T : Current date and time");
}
}
}