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 0000000..c561435
Binary files /dev/null and b/docs/DSON example.PNG differ
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