Fix scrolling functionality
[WebThing.git] / Config.cs
index 9ad8095..b8f04cd 100644 (file)
--- a/Config.cs
+++ b/Config.cs
@@ -1,24 +1,66 @@
 using System;
 using System.IO;
+using System.Collections;
 using System.Collections.Generic;
 using System.Text.RegularExpressions;
 
 namespace bytex64.WebThing {
+    public struct SearchHandlerPair {
+        public string Shortcut;
+        public string Plugin;
+
+        public SearchHandlerPair(string s, string p) {
+            Shortcut = s;
+            Plugin = p;
+        }
+    }
+
     public class Config {
-        public static string ConfigurationPrefix = "/etc";
+        public static List<string> ConfigPath;
+        public static string ConfigPathOut = null;
+        public static List<string> PluginPath;
 
         public static Dictionary<string,string> Options;
         public static Dictionary<string,Dictionary<string,string>> PluginOptions;
         public static string[] Arguments;
-        private static HashSet<string> CommandLineOptions;
+        public static List<string> Plugins;
+        public static List<SearchHandlerPair> SearchHandlers;
+        public static string DefaultSearchHandler;
 
-        public static Regex item_re = new Regex(@"^(?:([\w.]+)\.)?(\w+)$");
-        public static Regex file_var_re = new Regex(@"^([\w.]+)\s*=\s*(.*)$");
+        private static HashSet<string> CommandLineOptions;
+        private static Regex item_re = new Regex(@"^(?:([\w.]+)\.)?(\w+)$");
+        private static Regex file_var_re = new Regex(@"^([\w.]+)\s*=\s*(.*)$");
+        private static Regex file_command_re = new Regex(@"^([\w]+)\s*(.*)$");
 
         static Config() {
             Options = new Dictionary<string,string>();
             PluginOptions = new Dictionary<string,Dictionary<string,string>>();
             CommandLineOptions = new HashSet<string>();
+            Plugins = new List<string>();
+            SearchHandlers = new List<SearchHandlerPair>();
+
+            // Set up ConfigPath
+            IDictionary Env = Environment.GetEnvironmentVariables();
+            ConfigPath = new List<string>();
+            ConfigPath.Add("/etc/WebThing");
+            if (Env.Contains("HOME")) {
+                string homepath = Env["HOME"] + "/.config/WebThing";
+                ConfigPath.Add(homepath);
+                if (Directory.Exists(homepath))
+                    ConfigPathOut = homepath;
+            }
+            string LocalAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
+            if (LocalAppData != "") {
+                string homepath = LocalAppData + "/WebThing";
+                ConfigPath.Add(homepath);
+                if (Directory.Exists(homepath))
+                    ConfigPathOut = homepath;
+            }
+
+            // Set up PluginPath
+            PluginPath = new List<string>();
+            PluginPath.Add(Environment.GetEnvironmentVariable("WEBTHING_HOME") + "/plugins");
+            PluginPath.Add(Environment.GetEnvironmentVariable("WEBTHING_HOME") + "/searchplugins");
         }
 
         private static void ParseOption(string key, string val) {
@@ -30,7 +72,14 @@ namespace bytex64.WebThing {
                     PluginOptions[plugin] = new Dictionary<string,string>();
                 PluginOptions[plugin][name] = val;
             } else {                   // Global Option
-                Options[name] = val;
+                switch(key.ToLower()) {
+                case "plugin":
+                    Plugins.Add(val);
+                    break;
+                default:
+                    Options[key] = val;
+                    break;
+                }
             }
         }
 
@@ -103,8 +152,13 @@ namespace bytex64.WebThing {
         }
 
         public static void Load() {
-            LoadFile(ConfigurationPrefix + "/WebThing.conf");
-            LoadFile(Environment.GetEnvironmentVariable("HOME") + "/.config/WebThing/WebThing.conf");
+            foreach (string path in ConfigPath) {
+                if (!Directory.Exists(path)) continue;
+                string[] ConfigFiles = Directory.GetFiles(path, "*.conf");
+                foreach (string file in ConfigFiles) {
+                    LoadFile(file);
+                }
+            }
             if (Options.ContainsKey("config"))
                 LoadFile(Options["config"]);
         }
@@ -112,7 +166,7 @@ namespace bytex64.WebThing {
         public static void LoadFile(string filename) {
             TextReader f;
             try {
-                f = new StreamReader(File.OpenRead(filename));
+                f = new StreamReader(filename);
             } catch (FileNotFoundException) {
                 Console.WriteLine("Could not open configuration file {0}", filename);
                 return;
@@ -120,15 +174,98 @@ namespace bytex64.WebThing {
 
             string line;
             while ((line = f.ReadLine()) != null) {
-                Match m = file_var_re.Match(line.Trim());
+                Match m;
+
+                line = line.Trim();
+                m = file_var_re.Match(line);
                 if (m.Success) {
                     string key = m.Groups[1].Value;
                     if (!CommandLineOptions.Contains(key))
                         ParseOption(key, m.Groups[2].Value);
+                    continue;
+                }
+
+                m = file_command_re.Match(line);
+                if (m.Success) {
+                    string cmd = m.Groups[1].Value.ToLower();
+                    switch(cmd) {
+                    case "plugin":
+                        Plugins.Add(m.Groups[2].Value);
+                        break;
+                    case "searchhandler":
+                        string[] args = Regex.Split(m.Groups[2].Value, @"\s+");
+                        if (args.Length != 2) {
+                            Console.WriteLine("Expecting two arguments for SearchHandler.");
+                            break;
+                        }
+                        SearchHandlers.Add(new SearchHandlerPair(args[0], args[1]));
+                        break;
+                    case "defaultsearchhandler":
+                        DefaultSearchHandler = m.Groups[2].Value;
+                        break;
+                    default:
+                        Console.WriteLine("Unknown Command in {0}: {1}", filename, line);
+                        break;
+                    }
+                    continue;
+                }
+            }
+
+            f.Close();
+        }
+
+        public static void SaveFile(string filename) {
+            TextWriter f;
+            try {
+                f = new StreamWriter(filename);
+            } catch (IOException) {
+                Console.WriteLine("Could not save configuration to {0}", filename);
+                return;
+            }
+
+            foreach (string key in Options.Keys) {
+                if (CommandLineOptions.Contains(key)) continue;
+                f.WriteLine("{0} = {1}", key, Options[key]);
+            }
+
+            foreach (string plugin in PluginOptions.Keys) {
+                foreach (string key in PluginOptions[plugin].Keys) {
+                    string pkey = String.Format("{0}.{1}", plugin, key);
+                    if (CommandLineOptions.Contains(pkey)) continue;
+                    f.WriteLine("{0} = {1}", pkey, PluginOptions[plugin][key]);
                 }
             }
 
             f.Close();
         }
+
+        public static void SaveFile(WebThingPlugin p, string filename) {
+            string plugin_name = p.GetType().FullName;
+            SaveFile(plugin_name, filename);
+        }
+
+        public static void SaveFile(string plugin_name, string filename) {
+            // TODO: Throw exception if plugin does not exist
+            TextWriter f = new StreamWriter(filename);
+
+            foreach (string key in PluginOptions[plugin_name].Keys) {
+                f.WriteLine("{0}.{1} = {2}", plugin_name, key, PluginOptions[plugin_name][key]);
+            }
+
+            f.Close();
+        }
+
+        // Data parsers
+        public static bool ParseBool(string v) {
+            switch(v.ToLower()) {
+            case "true":
+            case "t":
+            case "1":
+            case "on":
+            case "yes":
+                return true;
+            }
+            return false;
+        }
     }
 }