diff --git a/ConfigParser.cs b/ConfigParser.cs index aca0b1ff74114438324ad3e4a6f309065002ef9e..2727fb8e70422a1d1c45aebdd115f5de95e7cecc 100644 --- a/ConfigParser.cs +++ b/ConfigParser.cs @@ -29,6 +29,11 @@ namespace Config; abstract class ConfigException: Exception { + public ConfigParser Parser; + internal ConfigException(ConfigParser parser) + { + Parser = parser; + } public override string ToString() { return $"Mistake in config: {ErrorString()}"; @@ -39,7 +44,7 @@ abstract class ConfigDuplicitException: ConfigException { public string Name; public int LineA, LineB; - public ConfigDuplicitException(string name, int lineA, int lineB) + public ConfigDuplicitException(ConfigParser parser, string name, int lineA, int lineB): base(parser) { Name = name; LineA = lineA; @@ -48,8 +53,8 @@ abstract class ConfigDuplicitException: ConfigException } class ConfigDuplicitSectionException: ConfigDuplicitException { - public ConfigDuplicitSectionException(string name, int lineA, int lineB) - :base(name, lineA, lineB){} + public ConfigDuplicitSectionException(ConfigParser parser, string name, int lineA, int lineB) + :base(parser, name, lineA, lineB){} public override string ErrorString() { return $"Duplicit section name {Name} on lines {LineA}, {LineB}"; @@ -57,8 +62,8 @@ class ConfigDuplicitSectionException: ConfigDuplicitException } class ConfigDuplicitKeyException: ConfigDuplicitException { - public ConfigDuplicitKeyException(string name, int lineA, int lineB) - :base(name, lineA, lineB){} + public ConfigDuplicitKeyException(ConfigSection section, string name, int lineA, int lineB) + :base(section.Root, name, lineA, lineB){} public override string ErrorString() { return $"Duplicit key name {Name} on lines {LineA}, {LineB}"; @@ -67,7 +72,7 @@ class ConfigDuplicitKeyException: ConfigDuplicitException class ConfigNoAmenException: ConfigException { public ConfigKeyValue Value; - public ConfigNoAmenException(ConfigKeyValue value) + public ConfigNoAmenException(ConfigKeyValue value):base(value.Section.Root) { Value = value; } @@ -80,7 +85,7 @@ class ConfigMixedTabException: ConfigException { public ConfigKeyValue Value; public int Line; - public ConfigMixedTabException(ConfigKeyValue value, int line) + public ConfigMixedTabException(ConfigKeyValue value, int line):base(value.Section.Root) { Value = value; Line = line; @@ -94,7 +99,7 @@ class ConfigWrongIndentException: ConfigException { public ConfigKeyValue? Value; public int Line; - public ConfigWrongIndentException(ConfigKeyValue? value, int line) + public ConfigWrongIndentException(ConfigSection section, ConfigKeyValue? value, int line):base(section.Root) { Value = value; Line = line; @@ -109,7 +114,7 @@ class ConfigWrongIndentException: ConfigException class ConfigSectionNotDefinedException: ConfigException { public string Name; - public ConfigSectionNotDefinedException(string name) + public ConfigSectionNotDefinedException(ConfigParser parser, string name):base(parser) { Name = name; } @@ -122,7 +127,7 @@ class ConfigNotDefinedException: ConfigException { public ConfigSection Section; public string Name; - public ConfigNotDefinedException(ConfigSection section, string name) + public ConfigNotDefinedException(ConfigSection section, string name):base(section.Root) { Section = section; Name = name; @@ -136,7 +141,7 @@ class ConfigNoValueException: ConfigException { public ConfigValue Value; public string? Reason; - public ConfigNoValueException(ConfigValue value, string? reason=null) + public ConfigNoValueException(ConfigValue value, string? reason=null):base(value.Root) { Value = value; Reason = reason; @@ -149,7 +154,7 @@ class ConfigNoValueException: ConfigException class ConfigUnusedOptionException: ConfigException { public ConfigKeyValue Value; - public ConfigUnusedOptionException(ConfigKeyValue value) + public ConfigUnusedOptionException(ConfigKeyValue value):base(value.Root) { Value = value; } @@ -161,7 +166,7 @@ class ConfigUnusedOptionException: ConfigException class ConfigUnusedSectionException: ConfigException { public ConfigSection Section; - public ConfigUnusedSectionException(ConfigSection section) + public ConfigUnusedSectionException(ConfigSection section):base(section.Root) { Section = section; } @@ -177,7 +182,7 @@ class ConfigParseValueException: ConfigException { public ConfigValue Value; public string? Reason; - public ConfigParseValueException(ConfigValue value, string? reason=null) + public ConfigParseValueException(ConfigValue value, string? reason=null):base(value.Root) { Value = value; Reason = reason; @@ -192,7 +197,7 @@ class ConfigMistake: ConfigException { public ConfigValue Value; public string Text; - public ConfigMistake(ConfigValue value, string text) + public ConfigMistake(ConfigValue value, string text):base(value.Root) { Value = value; Text = text; @@ -205,6 +210,7 @@ class ConfigMistake: ConfigException abstract class ConfigValue { + public ConfigParser Root; public int Line; internal string? Value; public bool HasText() => Value != null; @@ -212,6 +218,11 @@ abstract class ConfigValue public virtual string Place{get => $"{Line}: {FullName}";} public abstract string FullName{get;} // For showing in error + public ConfigValue(ConfigParser _Root) + { + Root = _Root; + } + public string AsString() { if(Value == null) throw new ConfigNoValueException(this); @@ -296,7 +307,7 @@ abstract class ConfigValue } public ConfigParser AsConfig() { - return new ConfigParser(AsString(), Line); + return new ConfigParser(AsString(), Root.FileName, Line); } public static implicit operator string(ConfigValue v) => v.AsString(); } @@ -316,7 +327,7 @@ class ConfigKeyValue: ConfigValue { get => Section.SectionName != null ? $"{Section.SectionName}: {Key}" : Key; } - internal ConfigKeyValue(ConfigSection _Section, string _Key, int _line) + internal ConfigKeyValue(ConfigSection _Section, string _Key, int _line):base(_Section.Root) { Section = _Section; Key = _Key; @@ -331,7 +342,7 @@ class ConfigKeyAsValue: ConfigValue { get => (Section.SectionName != null ? $"{Section.SectionName}: " : "") + $"Key {Value}"; } - internal ConfigKeyAsValue(ConfigKeyValue keyValue) + internal ConfigKeyAsValue(ConfigKeyValue keyValue):base(keyValue.Root) { Line = keyValue.Line; Value = keyValue.Key; @@ -345,7 +356,7 @@ class ConfigSectionNameAsValue: ConfigValue { get => "Section name " + (Section.SectionName != null ? $"\"{Section.SectionName}\"" : "of main section"); } - internal ConfigSectionNameAsValue(ConfigSection _Section) + internal ConfigSectionNameAsValue(ConfigSection _Section):base(_Section.Root) { Section = _Section; Value = Section.SectionName; @@ -386,7 +397,7 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue> internal void Add(ConfigKeyValue v) { if(valueByName.ContainsKey(v.Key)) - throw new ConfigDuplicitKeyException(v.Key, v.Line, valueByName[v.Key].Line); + throw new ConfigDuplicitKeyException(this, v.Key, v.Line, valueByName[v.Key].Line); valueByName[v.Key] = v; values.Add(v); } @@ -446,11 +457,13 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue> } class ConfigParser: IReadOnlyList<ConfigSection> { + public string? FileName {get; init;} public ConfigSection MainSection; List<ConfigSection> sections = new(); Dictionary<string, ConfigSection> sectionByName = new(); - public ConfigParser(string s, int firstLineIndex = 1) + public ConfigParser(string s, string? _FileName = null, int firstLineIndex = 1) { + FileName = _FileName; string[] lines = s.Split("\n"); var currentSection = MainSection = new(this, null, 0); ConfigKeyValue? lastVal = null; @@ -468,7 +481,7 @@ class ConfigParser: IReadOnlyList<ConfigSection> currentSection = new ConfigSection(this, tl[1..^1], firstLineIndex + i); if(sectionByName.ContainsKey(currentSection.SectionName)) { - throw new ConfigDuplicitSectionException(currentSection.SectionName, sectionByName[currentSection.SectionName].Line, firstLineIndex + i); + throw new ConfigDuplicitSectionException(this, currentSection.SectionName, sectionByName[currentSection.SectionName].Line, firstLineIndex + i); } sections.Add(currentSection); sectionByName[currentSection.SectionName] = currentSection; @@ -478,7 +491,7 @@ class ConfigParser: IReadOnlyList<ConfigSection> if(tl[0]==' ' || tl[0]=='\t') { if(lastVal == null) - throw new ConfigWrongIndentException(null, firstLineIndex + i); + throw new ConfigWrongIndentException(currentSection, null, firstLineIndex + i); if(lastVal.tabs == null) { int spacesLen=0; @@ -497,7 +510,7 @@ class ConfigParser: IReadOnlyList<ConfigSection> else { if(!tl.StartsWith(lastVal.tabs)) - throw new ConfigWrongIndentException(lastVal, firstLineIndex + i); + throw new ConfigWrongIndentException(currentSection, lastVal, firstLineIndex + i); lastVal.Value += "\n" + tl[lastVal.tabs.Length..]; } continue; @@ -569,7 +582,7 @@ class ConfigParser: IReadOnlyList<ConfigSection> { if(key == null) return MainSection; if(!sectionByName.TryGetValue(key, out var r)) - throw new ConfigSectionNotDefinedException(key); + throw new ConfigSectionNotDefinedException(this, key); return r.Use(); } public void CheckUnused() diff --git a/Program.cs b/Program.cs index 692bb57de85d63cc1a0769c8bb731c723653daaf..c92a0f5f16382387cedc9979c3117aa6759bda64 100644 --- a/Program.cs +++ b/Program.cs @@ -211,22 +211,25 @@ refresh if(configFile == null) { string configText; + string? fileName; try { - configText = File.ReadAllText(Environment.GetEnvironmentVariable("HOME")+"/.config/i3/i3csstatus.conf"); + fileName = Environment.GetEnvironmentVariable("HOME")+"/.config/i3/i3csstatus.conf"; + configText = File.ReadAllText(fileName); } catch(Exception e) when (e is FileNotFoundException || e is DirectoryNotFoundException) { + fileName = null; configText = DefaultConfigText; } - parseConfigString(configText); + parseConfig(new ConfigParser(configText, fileName)); } else - parseConfigString(File.ReadAllText(configFile.ToString())); + parseConfigString(File.ReadAllText(configFile.ToString()), configFile.ToString()); } - protected void parseConfigString(string configString) + protected void parseConfigString(string configString, string? fileName) { - parseConfig(new ConfigParser(configString)); + parseConfig(new ConfigParser(configString, fileName)); } virtual protected void parseConfig(ConfigParser p) {