From e2ffde3a5e529d94f018930dc5ba5e0b077e793c Mon Sep 17 00:00:00 2001 From: molsonkiko <46202915+molsonkiko@users.noreply.github.com> Date: Tue, 28 Feb 2023 13:15:24 -0800 Subject: [PATCH] plugin now compatible with Npp older than 8.4.1 FIXED 1. Fixed bug in [Main](/JsonToolsNppPlugin/Main.cs#L360) (based on failure to read [SCI_GETTEXT documentation](https://www.scintilla.org/ScintillaDoc.html#SCI_GETTEXT)) that caused this plugin to be incompatible with versions of Notepad++ older than 8.4.1. ADDED 1. DSON emitter and UDL takes this plugin to the moon! --- CHANGELOG.md | 8 +- DSON UDL.xml | 64 +++++++++ JsonToolsNppPlugin/JSONTools/Dson.cs | 130 ++++++++++++++++++ .../JSONTools/RandomJsonFromSchema.cs | 6 +- JsonToolsNppPlugin/JsonToolsNppPlugin.csproj | 2 + JsonToolsNppPlugin/Main.cs | 25 +++- .../PluginInfrastructure/NotepadPPGateway.cs | 14 ++ JsonToolsNppPlugin/Properties/AssemblyInfo.cs | 4 +- JsonToolsNppPlugin/Tests/DsonTests.cs | 60 ++++++++ JsonToolsNppPlugin/Tests/TestRunner.cs | 6 + JsonToolsNppPlugin/Utils/FormStyle.cs | 3 + docs/DSON example.PNG | Bin 0 -> 33896 bytes docs/README.md | 10 +- testfiles/small/subsmall/to the moon.dson | 1 + 14 files changed, 325 insertions(+), 8 deletions(-) create mode 100644 DSON UDL.xml create mode 100644 JsonToolsNppPlugin/JSONTools/Dson.cs create mode 100644 JsonToolsNppPlugin/Tests/DsonTests.cs create mode 100644 docs/DSON example.PNG create mode 100644 testfiles/small/subsmall/to the moon.dson diff --git a/CHANGELOG.md b/CHANGELOG.md index 99cddbe..4b7121d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed 1. Hopefully eliminated crash bug that sometimes seems to happen because a file that had a tree viewer associated with it was renamed. This bug is really unpredictable, so it may not be gone. -2. Changed [RemesPath `s_sub` function](/docs/RemesPath.md#vectorized-functions) so that it either does regex-replace or simple string-replace, depending on the type of the second parameter. +2. Fixed bug in [Main](/JsonToolsNppPlugin/Main.cs#L360) (based on failure to read [SCI_GETTEXT documentation](https://www.scintilla.org/ScintillaDoc.html#SCI_GETTEXT)) that caused this plugin to be incompatible with versions of Notepad++ older than 8.4.1. + +### Changed +1. Changed [RemesPath `s_sub` function](/docs/RemesPath.md#vectorized-functions) so that it either does regex-replace or simple string-replace, depending on the type of the second parameter. + +#### Added +1. [DSON emitter and UDL](/docs/README.md#dson) takes this plugin to the moon! ## [4.10.0] - 2023-02-15 diff --git a/DSON UDL.xml b/DSON UDL.xml new file mode 100644 index 0000000..84ab86c --- /dev/null +++ b/DSON UDL.xml @@ -0,0 +1,64 @@ + + + + + + + + 00 01 02 03 04 + + - + + + + + + VERY very + , ? . ! + + + + + + + + + + + so and also many + such is wow + yes no + empty + + + + + 00" 01\ 02" 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/JsonToolsNppPlugin/JSONTools/Dson.cs b/JsonToolsNppPlugin/JSONTools/Dson.cs new file mode 100644 index 0000000..e063caa --- /dev/null +++ b/JsonToolsNppPlugin/JSONTools/Dson.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +namespace JSON_Tools.JSON_Tools +{ + class DsonDumpException : Exception + { + public new string Message; + + public DsonDumpException(string message) + { + Message = message; + } + } + + /// + /// wow such data very readable

+ /// such docs at https://dogeon.xyz/ plz read + ///
+ class Dson + { + public static string KeyValuePairDelims = ",.!?"; + + public static string[] ArrayPairDelims = new string[] { "and", "also" }; + + private static string FormatInteger(long val) + { + if (val == long.MinValue) + // converting to octal turns signed numbers into unsigned numbers + // this can be reversed for every negative number except long.MinValue + return "1000000000000000000000"; + if (val < 0) + return "-" + Convert.ToString(-val, 8); + return Convert.ToString(val, 8); + } + + /// + /// plz stringify json as DSON

+ /// wow so amaze + ///
+ public static string Dump(JNode json) + { + StringBuilder sb; + switch (json.type) + { + case Dtype.ARR: + sb = new StringBuilder(); + sb.Append("so "); + JArray arr = (JArray)json; + bool useAndDelim = true; + for (int ii = 0; ii < arr.Length; ii++) + { + sb.Append(Dump(arr[ii])); + sb.Append(useAndDelim ? " and " : " also "); + useAndDelim = !useAndDelim; + } + if (arr.Length > 0) + { + // trim off the last delimiter if the array had items + int lengthToRemove = useAndDelim ? 5 : 4; + sb.Remove(sb.Length - lengthToRemove - 1, lengthToRemove); + } + sb.Append("many"); + return sb.ToString(); + case Dtype.OBJ: + // {"a": 13.51e25, "b": true} becomes + // such "a" is 15.63very31, "b" is yes wow + sb = new StringBuilder(); + sb.Append("such "); + int delimIdx = 0; + JObject obj = (JObject)json; + foreach (string key in obj.children.Keys) + { + JNode value = obj[key]; + sb.Append($"\"{key}\" is "); + sb.Append(Dump(value)); + sb.Append(KeyValuePairDelims[delimIdx % 4] + " "); + delimIdx++; + } + if (obj.Length > 0) + sb.Remove(sb.Length - 2, 1); // remove the last delimter if there were items + sb.Append("wow"); + return sb.ToString(); + case Dtype.BOOL: + return (bool)json.value ? "yes" : "no"; + case Dtype.NULL: + return "empty"; + case Dtype.INT: + return FormatInteger((long)json.value); + case Dtype.FLOAT: + // floating point numbers are formatted + // such that fractional part, exponent, and integer part are all octal + string valstr = ((double)json.value).ToString(); + if (valstr.EndsWith("y") || valstr.EndsWith("N")) + // Infinity and NaN are not in the DSON specification + throw new DsonDumpException($"{valstr} is fake number, can't understand. So silly, wow"); + StringBuilder partSb = new StringBuilder(); + sb = new StringBuilder(); + long part; + foreach (char c in valstr) + { + if ('0' <= c && c <= '9' || c == '+' || c == '-') + { + partSb.Append(c); + } + else + { + part = Convert.ToInt64(partSb.ToString()); + partSb = new StringBuilder(); + sb.Append(FormatInteger(part)); + if (c == '.') + sb.Append("."); + else if (c == 'e') + sb.Append("very"); + else if (c == 'E') + sb.Append("VERY"); + } + } + part = Convert.ToInt64(partSb.ToString()); + sb.Append(FormatInteger(part)); + return sb.ToString(); + case Dtype.STR: + return json.ToString(); + default: throw new NotSupportedException(); + } + } + } +} diff --git a/JsonToolsNppPlugin/JSONTools/RandomJsonFromSchema.cs b/JsonToolsNppPlugin/JSONTools/RandomJsonFromSchema.cs index 6f14d75..835b242 100644 --- a/JsonToolsNppPlugin/JSONTools/RandomJsonFromSchema.cs +++ b/JsonToolsNppPlugin/JSONTools/RandomJsonFromSchema.cs @@ -76,7 +76,7 @@ private static JNode RandomString(JNode schema, int minArrayLength, int maxArray { for (int ii = 0; ii < length; ii++) { - char randChar = EXTENDED_ASCII[random.Next(256)]; + char randChar = EXTENDED_ASCII[random.Next(1, 256)]; // not allowing \x00 because that will terminate string early in C sb.Append(randChar); } } @@ -227,6 +227,10 @@ private static JNode RandomAnything(JNode schema, int minArrayLength, int maxArr } } + /// + /// choose a random schema from an anyOf list of schemas, and make random JSON based on that schema + /// + /// private static JNode RandomAnyOf(JNode anyOf, int minArrayLength, int maxArrayLength, bool extended_ascii_strings) { JArray anyOfArr = (JArray)anyOf; diff --git a/JsonToolsNppPlugin/JsonToolsNppPlugin.csproj b/JsonToolsNppPlugin/JsonToolsNppPlugin.csproj index d900c03..1eb1ff0 100644 --- a/JsonToolsNppPlugin/JsonToolsNppPlugin.csproj +++ b/JsonToolsNppPlugin/JsonToolsNppPlugin.csproj @@ -97,6 +97,7 @@ TreeViewer.cs + @@ -193,6 +194,7 @@ + diff --git a/JsonToolsNppPlugin/Main.cs b/JsonToolsNppPlugin/Main.cs index 629913a..2bd508e 100644 --- a/JsonToolsNppPlugin/Main.cs +++ b/JsonToolsNppPlugin/Main.cs @@ -14,6 +14,7 @@ using JSON_Tools.Utils; using JSON_Tools.Forms; using JSON_Tools.Tests; +using System.Runtime.InteropServices.WindowsRuntime; namespace Kbg.NppPluginNET { @@ -49,7 +50,6 @@ class Main static internal int jsonTreeId = -1; static internal int grepperFormId = -1; static internal int AboutFormId = -1; - //static internal int nodeSelectedLabelId = -1; #endregion #region " Startup/CleanUp " @@ -87,7 +87,8 @@ static internal void CommandMenuInit() PluginBase.SetCommand(14, "---", null); PluginBase.SetCommand(15, "JSON to &YAML", DumpYaml); PluginBase.SetCommand(16, "Run &tests", async () => await TestRunner.RunAll()); - PluginBase.SetCommand(17, "A&bout", ShowAboutForm); AboutFormId = 16; + PluginBase.SetCommand(17, "A&bout", ShowAboutForm); AboutFormId = 17; + PluginBase.SetCommand(18, "&Wow such doge", Dogeify); //// read schemas_to_fname_patterns.json in config directory (if it exists) //string config_dir = Npp.notepad.GetConfigDirectory(); @@ -356,7 +357,7 @@ public static JNode TryParseJson(bool is_json_lines = false) { int len = Npp.editor.GetLength(); string fname = Npp.notepad.GetCurrentFilePath(); - string text = Npp.editor.GetText(len); + string text = Npp.editor.GetText(len + 1); JNode json = new JNode(); try { @@ -781,6 +782,24 @@ static void ShowAboutForm() aboutForm.Focus(); } + static void Dogeify() + { + JNode json = TryParseJson(); + if (json == null) return; + try + { + string dson = Dson.Dump(json); + Npp.notepad.FileNew(); + Npp.editor.SetText(dson); + } + catch (Exception ex) + { + MessageBox.Show($"Could not convert JSON to DSON. Got exception:\r\n{ex}", + "such error very sad", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + //static void MapSchemasToFnamePatterns() //{ // string config_dir = Npp.notepad.GetConfigDirectory(); diff --git a/JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs b/JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs index 1f086eb..6f391a1 100644 --- a/JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs +++ b/JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs @@ -25,6 +25,7 @@ public interface INotepadPPGateway Color GetDefaultForegroundColor(); Color GetDefaultBackgroundColor(); string GetConfigDirectory(); + int[] GetNppVersion(); } /// @@ -174,6 +175,19 @@ public string GetConfigDirectory() Win32.SendMessage(PluginBase.nppData._nppHandle, (uint)NppMsg.NPPM_GETPLUGINSCONFIGDIR, Win32.MAX_PATH, sbIniFilePath); return sbIniFilePath.ToString(); } + + /// + /// 2-int array. First entry: major version. Second entry: minor version + /// + /// + public int[] GetNppVersion() + { + // the low word (i.e., version & 0xffff + int version = Win32.SendMessage(PluginBase.nppData._nppHandle, (uint)NppMsg.NPPM_GETNPPVERSION, 0, 0).ToInt32(); + int minor = version & 0xffff; + int major = version >> 16; + return new int[] { major, minor }; + } } /// diff --git a/JsonToolsNppPlugin/Properties/AssemblyInfo.cs b/JsonToolsNppPlugin/Properties/AssemblyInfo.cs index f2eef53..4acecb9 100644 --- a/JsonToolsNppPlugin/Properties/AssemblyInfo.cs +++ b/JsonToolsNppPlugin/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("4.10.0.2")] -[assembly: AssemblyFileVersion("4.10.0.2")] +[assembly: AssemblyVersion("4.10.0.3")] +[assembly: AssemblyFileVersion("4.10.0.3")] diff --git a/JsonToolsNppPlugin/Tests/DsonTests.cs b/JsonToolsNppPlugin/Tests/DsonTests.cs new file mode 100644 index 0000000..769d2c8 --- /dev/null +++ b/JsonToolsNppPlugin/Tests/DsonTests.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; +using JSON_Tools.JSON_Tools; +using JSON_Tools.Utils; + +namespace JSON_Tools.Tests +{ + public class DsonTester + { + public static void TestDump() + { + (string inp, string correctOut)[] testcases = new (string inp, string correctOut)[] + { + ("[]", "so many"), + ("{}", "such wow"), + ("[1]", "so 1 many"), + ("{\"a\": 13}", "such \"a\" is 15 wow"), + ("null", "empty"), + ("[1.5, [2e31], -3.5E40]", "so 1.5 and so 2VERY37 many also -3.5VERY50 many"), + ("{\"aჿ\":[true,false,{\"c\": 3},\"оa\",[1, -2]], \"b\\\"\": \"z\", \"c\": {\"d\": 1.13}, \"d\": 50, \"e\": 0.76, \"f\": null}", + "such \"aჿ\" is so yes and no also such \"c\" is 3 wow and \"оa\" also so 1 and -2 many many, \"b\\\"\" is \"z\". " + + "\"c\" is such \"d\" is 1.15 wow! \"d\" is 62? \"e\" is 0.114, \"f\" is empty wow"), + ("[-9223372036854775808, 9223372036854775807]", "so 1000000000000000000000 and 777777777777777777777 many"), + }; + int tests_failed = 0; + int ii = 0; + JsonParser parser = new JsonParser(); + foreach ((string input, string correctOut) in testcases) + { + JNode json = JsonParserTester.TryParse(input, parser); + if (json == null) continue; + ii++; + string dson; + try + { + dson = Dson.Dump(json); + } + catch (Exception ex) + { + tests_failed++; + string msg = $"Tried to parse json\r\n{json}\r\nas dson\r\n{correctOut}\r\nbut got error:\r\n{ex}\r\n"; + Npp.editor.AppendText(Encoding.UTF8.GetByteCount(msg), msg); + continue; + } + if (dson != correctOut) + { + tests_failed++; + string msg = $"Expected json\r\n{json}\r\nto be emitted\r\nas dson\r\n{correctOut}\r\nbut instead got \r\n{dson}\r\n"; + Npp.editor.AppendText(Encoding.UTF8.GetByteCount(msg), msg); + } + } + Npp.AddLine($"Failed {tests_failed} tests."); + Npp.AddLine($"Passed {ii - tests_failed} tests."); + } + } +} diff --git a/JsonToolsNppPlugin/Tests/TestRunner.cs b/JsonToolsNppPlugin/Tests/TestRunner.cs index e2400db..08d9de7 100644 --- a/JsonToolsNppPlugin/Tests/TestRunner.cs +++ b/JsonToolsNppPlugin/Tests/TestRunner.cs @@ -131,6 +131,12 @@ Testing ArgFunctions "); RandomJsonTests.TestRandomJson(); + Npp.AddLine(@"========================= +Testing conversion of JSON to DSON (see https://dogeon.xyz/) +========================= +"); + DsonTester.TestDump(); + Npp.AddLine(@"========================= Performance tests for JsonParser ========================= diff --git a/JsonToolsNppPlugin/Utils/FormStyle.cs b/JsonToolsNppPlugin/Utils/FormStyle.cs index f2de107..2d1754f 100644 --- a/JsonToolsNppPlugin/Utils/FormStyle.cs +++ b/JsonToolsNppPlugin/Utils/FormStyle.cs @@ -25,6 +25,9 @@ public static class FormStyle public static void ApplyStyle(Form form, bool use_npp_style) { if (form.IsDisposed) return; + int[] version = Npp.notepad.GetNppVersion(); + if (version[0] < 8) + use_npp_style = false; // trying to follow editor style looks weird for Notepad++ 7.3.3 //foreach (PropertyInfo info in form.GetType().GetProperties()) //{ // if (info.PropertyType.IsSubclassOf(form_type)) diff --git a/docs/DSON example.PNG b/docs/DSON example.PNG new file mode 100644 index 0000000000000000000000000000000000000000..c561435a296dd521411008b80dbd9157e2b8094d GIT binary patch literal 33896 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 literal 0 HcmV?d00001 diff --git a/docs/README.md b/docs/README.md index 82582d4..5f88c12 100644 --- a/docs/README.md +++ b/docs/README.md @@ -446,4 +446,12 @@ This JSON schema generator only produces schemas with the following keywords: ### Keywords for arrays * [items](https://json-schema.org/draft/2020-12/json-schema-core.html#name-items) -![JSON schema generator](/docs/json%20viewer%20schema%20generator.PNG) \ No newline at end of file +![JSON schema generator](/docs/json%20viewer%20schema%20generator.PNG) + +## DSON ## + +JSON is not sufficiently [Doge-friendly](https://dogeon.xyz/index.html). This plugin aims to help correct that. + +Currently the plugin only has a DSON emitter. Later I will add a DSON parser. + +![DSON example](/docs/DSON%20example.PNG) \ No newline at end of file diff --git a/testfiles/small/subsmall/to the moon.dson b/testfiles/small/subsmall/to the moon.dson new file mode 100644 index 0000000..f0643d9 --- /dev/null +++ b/testfiles/small/subsmall/to the moon.dson @@ -0,0 +1 @@ +so such "aჿ" is so yes and no also such "c" is 3 wow and "оa" also so 1 and -2 many many, "b\"" is "z". "c" is such "d" is 1.15 wow! "d" is 62? "e" is 0.114, "f" is empty wow and so 1.5 and so 2very37 many also -3.5VERY50 many many