Skip to content

Instantly share code, notes, and snippets.

@koktoh
Last active August 2, 2020 04:15
Show Gist options
  • Save koktoh/74d7fb4b20d1254129bc31692369cacd to your computer and use it in GitHub Desktop.
Save koktoh/74d7fb4b20d1254129bc31692369cacd to your computer and use it in GitHub Desktop.
void Main()
{
var keycordPath = @""; // common\keycode.h
var qkPath = @""; // quantum\quantum_keycodes.h
var kc = keycordPath.ToFileInfo().OpenText().ReadToEnd();
var qk = qkPath.ToFileInfo().OpenText().ReadToEnd();
var parser = new KeycodeDefinitionParser();
var tmkKeycodes = parser.Parse(kc).ToList();
var qmkKeycodes = parser.Parse(tmkKeycodes, qk).ToList();
var keycodes = tmkKeycodes.Concat(qmkKeycodes).ToList();
var formated = keycodes
.OrderBy(x => x.DefinitionValue)
.Select(x => $@" ""{x.Definition}"": {x.DefinitionValue}")
.Join($",{Environment.NewLine}");
var json = new[] { "{", formated, "}", Environment.NewLine }.JoinNewLine();
json.Dump();
}
// Define other methods and classes here
public interface IKeycodeDefinition
{
string Definition { get; set; }
int DefinitionValue { get; set; }
}
public class KeycodeDefinition : IKeycodeDefinition
{
private readonly Regex _hexRex;
public string Definition { get; set; }
public string DefinitionValueRaw { get; set; }
public bool HasDefinitionValueRaw => this.DefinitionValueRaw.HasMeaningfulValue();
public bool isDefinitionValueHex => this._hexRex.IsMatch(this.DefinitionValueRaw);
public int DefinitionValue { get; set; }
public KeycodeDefinition() : this(string.Empty) { }
public KeycodeDefinition(string definition) : this(definition, string.Empty) { }
public KeycodeDefinition(string definition, string definitionValueRaw)
{
this._hexRex = new Regex(@"^0x[0-9A-Fa-f]+$");
this.Definition = definition;
this.DefinitionValueRaw = definitionValueRaw;
}
}
public class KeycodeDefinitionParser
{
private const string KC_ENUM = "kc_enum";
private const string ENUM_ITEMS = "enum_items";
private const string EX_KEYCODE = "ex_kc";
private readonly Regex _kcEnumDefRex;
private readonly Regex _kcEnumItemsRex;
private readonly Regex _exKcRex;
public KeycodeDefinitionParser()
{
this._kcEnumDefRex = new Regex($@"(\r|\n)*\s*(?<{KC_ENUM}>enum (.*(\r|\n))+?\}};)");
this._kcEnumItemsRex = new Regex($@".*\{{\s*(\r|\n)(?<{ENUM_ITEMS}>(.*(\r|\n))+?)\}};");
this._exKcRex = new Regex($@"\s*\#define\s(?<{EX_KEYCODE}>(([^\(\)]+?)\s([^\(\)]+?)))(\s*/.*?)?(\r|\n)");
}
public IEnumerable<IKeycodeDefinition> Parse(string raw)
{
return this.Parse(Enumerable.Empty<IKeycodeDefinition>(), raw);
}
public IEnumerable<IKeycodeDefinition> Parse(IEnumerable<IKeycodeDefinition> baseKeycodes, string raw)
{
var enumDefs = this.GetKeycodeEnumDefinitions(raw);
var keycodes = this.GetKeycodeDefinitions(enumDefs).ToList();
baseKeycodes = baseKeycodes.Concat(keycodes);
var exKeycodes = this.GetExKeycodes(baseKeycodes, raw).ToList();
return keycodes.Concat(exKeycodes);
}
private IEnumerable<IEnumerable<KeycodeDefinition>> GetKeycodeEnumDefinitions(string raw)
{
return this._kcEnumDefRex.Matches(raw)
.Cast<Match>()
.Select(x => x.Groups[KC_ENUM].Value)
.Select(x => this._kcEnumItemsRex.Match(x).Groups[ENUM_ITEMS].Value)
.Select(x => x.SplitNewLine().Select(y => y.Trim()).Where(y => !y.StartsWith("/") && !y.StartsWith("#") && y.HasMeaningfulValue()))
.Select(x => x.Select(y => y.SplitCommma().First()))
.Select(x => x.Select(y => y.Split("=").Select(z => z.Trim())))
.Select(x => x.Select(y =>
{
var item = y.First();
var value = string.Empty;
if (y.Count() > 1)
{
value = y.ElementAt(1);
}
return new KeycodeDefinition(item, value);
}));
}
private IEnumerable<IKeycodeDefinition> GetKeycodeDefinitions(IEnumerable<IEnumerable<KeycodeDefinition>> source)
{
var list = new List<KeycodeDefinition>();
foreach (var enumDef in source)
{
var preDef = new KeycodeDefinition();
for (int i = 0; i < enumDef.Count(); i++)
{
var def = enumDef.ElementAt(i);
if (def.isDefinitionValueHex)
{
def.DefinitionValue = def.DefinitionValueRaw.HexToInt32();
}
else if (def.HasDefinitionValueRaw)
{
var srcDef = list.First(x => x.Definition.Equals(def.DefinitionValueRaw));
def.DefinitionValue = srcDef.DefinitionValue;
}
else
{
def.DefinitionValue = preDef.DefinitionValue + 1;
}
if (!preDef.Definition.Equals(def.Definition) || preDef.DefinitionValue < def.DefinitionValue)
{
preDef = def;
}
list.Add(def);
}
}
return list;
}
private IEnumerable<IKeycodeDefinition> GetExKeycodes(IEnumerable<IKeycodeDefinition> baseKeycodes, string raw)
{
return this._exKcRex.Matches(raw)
.Cast<Match>()
.Select(x => x.Groups[EX_KEYCODE].Value)
.Select(x => x.Split(' ').Select(y => y.Trim()).ToArray())
.Where(x => x.Length > 1)
.Select(x => new KeycodeDefinition(x[0], x[1]))
.Where(x => x.isDefinitionValueHex || baseKeycodes.Select(y => y.Definition).Contains(x.DefinitionValueRaw))
.Select(x =>
{
var def = x;
if (x.isDefinitionValueHex)
{
def.DefinitionValue = x.DefinitionValueRaw.HexToInt32();
}
else
{
var keycode = baseKeycodes.First(y => y.Definition.Equals(x.DefinitionValueRaw));
def.DefinitionValue = keycode.DefinitionValue;
}
return def;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment