Skip to content

Commit

Permalink
improve selection-remembering perf, forget less
Browse files Browse the repository at this point in the history
Added:
1. Selection-based mode now supports any number of remembered selections,
    and undo and redo actions usually do not cause selections to be forgotten.

Changed:
1. Automatic JSON schema validation after editing
    does not happen when the document is in `REGEX` mode.
2. Removed the `max_tracked_json_selections` setting, as it is no longer necessary.

Fixed:
1. Using the Notepad++ find/replace form
    in Notepad++ versions 8.6.3 and 8.6.4
    now appropriately shifts remembered selections
    when in selection-based mode.
  • Loading branch information
molsonkiko committed Feb 24, 2024
1 parent 3b907a5 commit 4dbb720
Show file tree
Hide file tree
Showing 14 changed files with 247 additions and 211 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

1. `minLength` and `maxLength` keywords are now considered when making [random JSON from schema](/docs/README.md#generating-random-json-from-a-schema)
2. JsonTools now automatically navigates to the location of the fatal error when it fails to parse a document, unless the attempted parse was auto-triggered (say, by the [automatic parse after editing](/docs/README.md#automatically-check-for-errors-after-editing))
3. [Selection-based mode](/docs/README.md#working-with-selections) now supports any number of remembered selections, and undo and redo actions usually do not cause selections to be forgotten.

### Changed

1. If the location of an error is between the `CR` and the `LF` of a `CR LF` newline, JsonTools will now always move before the `CR`, rather than placing the caret in between them, which could cause confusion.
2. [Automatic JSON schema validation after editing](/docs/README.md#automatically-check-for-errors-after-editing) does not happen when the document is in `REGEX` mode.
3. Removed the `max_tracked_json_selections` setting, as it is no longer necessary.

### Fixed

1. Using the [Notepad++ find/replace form](https://npp-user-manual.org/docs/searching/#dialog-based-searching) in Notepad++ versions 8.6.3 and 8.6.4 now appropriately shifts remembered selections when in [selection-based mode](/docs/README.md#working-with-selections).

## [7.0.0] - 2024-02-09

Expand Down
2 changes: 1 addition & 1 deletion JsonToolsNppPlugin/Forms/TreeViewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,7 +1260,7 @@ private void DocumentTypeComboBox_SelectedIndexChanged(object sender, EventArgs
DocumentType oldDocumentType = GetDocumentType();
if (oldDocumentType == newDocumentType)
return;
(_, JNode newJson, _, _) =Main.TryParseJson(newDocumentType);
(_, JNode newJson, _, _) = Main.TryParseJson(newDocumentType);
JsonTreePopulate(newJson);
}

Expand Down
12 changes: 5 additions & 7 deletions JsonToolsNppPlugin/JSONTools/RemesPathFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,10 @@ public static JNode Uplus(JNode x)
/// </summary>
public class ArgFunction
{
private Func<List<JNode>, JNode> Function { get; }
/// <summary>
/// the function associated with this ArgFunction
/// </summary>
public Func<List<JNode>, JNode> Call { get; private set; }
private Dtype[] inputTypes;
public string name;
public Dtype type;
Expand Down Expand Up @@ -1007,7 +1010,7 @@ public ArgFunction(Func<List<JNode>, JNode> function,
ArgsTransform argsTransform = null,
bool conditionalExecution = false)
{
Function = function;
Call = function;
this.name = name;
this.type = type;
this.maxArgs = maxArgs;
Expand All @@ -1031,11 +1034,6 @@ public Dtype TypeOptions(int argNum)
: inputTypes[argNum])
| Dtype.UNKNOWN; // UNKNOWN is always a valid argument type.
}

public JNode Call(List<JNode> args)
{
return Function(args);
}

public override string ToString()
{
Expand Down
247 changes: 109 additions & 138 deletions JsonToolsNppPlugin/Main.cs

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions JsonToolsNppPlugin/PluginInfrastructure/Msgs_h.cs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,22 @@ public enum NppMsg : uint
/// </summary>
NPPM_ADDTOOLBARICON_FORDARKMODE = Constants.NPPMSG + 101,

// BOOL NPPM_ALLOCATEINDICATOR(int numberRequested, int* startNumber)
// Allocates an indicator number to a plugin: if a plugin needs to add an indicator,
// it has to use this message to get the indicator number, in order to prevent a conflict with the other plugins.
// wParam[in]: numberRequested is the number of ID you request for the reservation
// lParam[out]: startNumber will be set to the initial command ID if successful
// Return TRUE if successful, FALSE otherwise. startNumber will also be set to 0 if unsuccessful
//
// Example: If a plugin needs 1 indicator ID, the following code can be used :
//
// int idBegin;
// BOOL isAllocatedSuccessful = ::SendMessage(nppData._nppHandle, NPPM_ALLOCATEINDICATOR, 1, &idBegin);
//
// if isAllocatedSuccessful is TRUE, and value of idBegin is 7
// then indicator ID 7 is preserved by Notepad++, and it is safe to be used by the plugin.
NPPM_ALLOCATEINDICATOR = Constants.NPPMSG + 113,

RUNCOMMAND_USER = Constants.WM_USER + 3000,
NPPM_GETFULLCURRENTPATH = RUNCOMMAND_USER + FULL_CURRENT_PATH,
NPPM_GETCURRENTDIRECTORY = RUNCOMMAND_USER + CURRENT_DIRECTORY,
Expand Down
29 changes: 28 additions & 1 deletion JsonToolsNppPlugin/PluginInfrastructure/NotepadPPGateway.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ public interface INotepadPPGateway
/// <param name="formHandle">the Handle attribute of a Windows form</param>
void RemoveModelessDialog(IntPtr formHandle);

/// <summary>
/// Introduced in Notepad++ 8.5.6.<br></br>
/// NPPM_ALLOCATEINDICATOR: allocate one or more unused indicator IDs,
/// which can then be assigned styles and used to style regions of text.<br></br>
/// returns false and sets indicators to null if numberOfIndicators is less than 1, or if the requested number of indicators could not be allocated.<br></br>
/// Otherwise, returns true, and sets indicators to an array of numberOfIndicators indicator IDs.<br></br>
/// See https://www.scintilla.org/ScintillaDoc.html#Indicators for more info on the indicator API.
/// </summary>
/// <param name="numberOfIndicators">number of consecutive indicator IDs to allocate</param>
/// <returns></returns>
bool AllocateIndicators(int numberOfIndicators, out int[] indicators);

}

/// <summary>
Expand Down Expand Up @@ -256,7 +268,22 @@ public void SetStatusBarSection(string message, StatusBarSection section)
{
Win32.SendMessage(PluginBase.nppData._nppHandle, (uint)NppMsg.NPPM_SETSTATUSBAR, (int)section, message);
}
}

public unsafe bool AllocateIndicators(int numberOfIndicators, out int[] indicators)
{
indicators = null;
if (numberOfIndicators < 1)
return false;
indicators = new int[numberOfIndicators];
fixed (int* indicatorsPtr = indicators)
{
IntPtr success = Win32.SendMessage(PluginBase.nppData._nppHandle, (uint)NppMsg.NPPM_ALLOCATEINDICATOR, (IntPtr)numberOfIndicators, (IntPtr)indicatorsPtr);
for (int ii = 1; ii < numberOfIndicators; ii++)
indicators[ii] = indicators[ii - 1] + 1;
return success != IntPtr.Zero;
}
}
}

/// <summary>
/// This class holds helpers for sending messages defined in the Resource_h.cs file. It is at the moment
Expand Down
4 changes: 2 additions & 2 deletions JsonToolsNppPlugin/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@
// Build Number
// Revision
//
[assembly: AssemblyVersion("7.0.0.2")]
[assembly: AssemblyFileVersion("7.0.0.2")]
[assembly: AssemblyVersion("7.0.0.3")]
[assembly: AssemblyFileVersion("7.0.0.3")]
10 changes: 0 additions & 10 deletions JsonToolsNppPlugin/Tests/TestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ public static async Task RunAll()
var failures = new List<string>();
var skipped = new List<string>();
bool hasExplainedSkipLessThanNppV8 = false;
bool hasExplainedSkipLessThanNppV8p5p5 = false;

foreach ((Func<bool> tester, string name, bool onlyIfNpp8Plus, bool onlyIfNpp8p5p5Plus) in tests)
{
Expand All @@ -137,15 +136,6 @@ public static async Task RunAll()
}
skipped.Add(name);
}
else if (onlyIfNpp8p5p5Plus && !Npp.nppVersionAtLeast8p5p5)
{
if (!hasExplainedSkipLessThanNppV8p5p5)
{
hasExplainedSkipLessThanNppV8p5p5 = true;
Npp.AddLine("Skipping UI tests because they are very slow for Notepad++ versions older than v8.5.5");
}
skipped.Add(name);
}
else if (Main.settings.skip_api_request_and_fuzz_tests && name == fuzzTestName)
{
Npp.AddLine("\r\nskipped RemesPath fuzz tests because settings.skip_api_request_and_fuzz_tests was set to true");
Expand Down
5 changes: 1 addition & 4 deletions JsonToolsNppPlugin/Tests/UserInterfaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,6 @@ public static bool Test()
bool previousTabIndentPrettyPrint = Main.settings.tab_indent_pretty_print;
int previousIndentPrettyPrint = Main.settings.indent_pretty_print;
bool previousMinimalWhiteSpaceCompression = Main.settings.minimal_whitespace_compression;
int previousMaxTrackedJsonSelections = Main.settings.max_tracked_json_selections;
bool previousRememberComments = Main.settings.remember_comments;
bool previousHasWarnedSelectionsForgotten = Main.hasWarnedSelectionsForgotten;
bool previousOfferToShowLint = Main.settings.offer_to_show_lint;
Expand All @@ -803,7 +802,6 @@ public static bool Test()
Main.settings.tab_indent_pretty_print = false;
Main.settings.indent_pretty_print = 4;
Main.settings.minimal_whitespace_compression = true;
Main.settings.max_tracked_json_selections = 1000;
Main.settings.remember_comments = false;
Main.settings.offer_to_show_lint = false;
// if this is false, a message-box will pop up at some point.
Expand Down Expand Up @@ -846,7 +844,7 @@ public static bool Test()
catch (Exception ex)
{
failures++;
messages.Add("While running command " + command + " with args [" + string.Join(", ", args) + "], got exception\r\n" + ex);
messages.Add("FAIL: While running command " + command + " with args [" + string.Join(", ", args) + "], got exception\r\n" + ex);
lastFailureIndex = messages.Count;
}
}
Expand All @@ -866,7 +864,6 @@ public static bool Test()
Main.settings.indent_pretty_print = previousIndentPrettyPrint;
Main.settings.tab_indent_pretty_print = previousTabIndentPrettyPrint;
Main.settings.minimal_whitespace_compression = previousMinimalWhiteSpaceCompression;
Main.settings.max_tracked_json_selections = previousMaxTrackedJsonSelections;
Main.settings.remember_comments = previousRememberComments;
Main.hasWarnedSelectionsForgotten = previousHasWarnedSelectionsForgotten;
Main.settings.offer_to_show_lint = previousOfferToShowLint;
Expand Down
4 changes: 2 additions & 2 deletions JsonToolsNppPlugin/Utils/Npp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public class Npp

public static readonly bool nppVersionAtLeast8 = nppVersion[0] >= 8;

/// <summary>may matter for some UI tests</summary>
public static readonly bool nppVersionAtLeast8p5p5 = nppVersionStr.CompareTo("8.5.5") >= 0;
/// <summary>this is when NPPM_ALLOCATEINDICATORS was introduced</summary>
public static readonly bool nppVersionAtLeast8p5p6 = nppVersionStr.CompareTo("8.5.6") >= 0;

/// <summary>
/// append text to current doc, then append newline and move cursor
Expand Down
31 changes: 31 additions & 0 deletions JsonToolsNppPlugin/Utils/SelectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,37 @@ public static (int start, int end) ParseStartEndAsTuple(string startEnd)
return (startEndNums[0], startEndNums[1]);
}

public static List<string> GetRegionsWithIndicator(int indicator1, int indicator2)
{
var selList = new List<string>();
int indEnd = -1;
int indicator = indicator1;
while (indEnd < Npp.editor.GetLength())
{
int indStart = Npp.editor.IndicatorStart(indicator, indEnd);
indEnd = Npp.editor.IndicatorEnd(indicator, indStart);
if (Npp.editor.IndicatorValueAt(indicator, indStart) == 1)
{
selList.Add($"{indStart},{indEnd}");
indicator = indicator == indicator1 ? indicator2 : indicator1;
}
if (indEnd == 0 && indStart == 0)
break;
}
return selList;
}

public static (int start, int end) GetEnclosingRememberedSelection(int pos, int indicator1, int indicator2)
{
if (Npp.editor.IndicatorValueAt(indicator1, pos) == 0)
{
if (Npp.editor.IndicatorValueAt(indicator2, pos) == 0)
return (-1, -1);
return (Npp.editor.IndicatorStart(indicator2, pos), Npp.editor.IndicatorEnd(indicator2, pos));
}
return (Npp.editor.IndicatorStart(indicator1, pos), Npp.editor.IndicatorEnd(indicator1, pos));
}

public static List<(int start, int end)> GetSelectedRanges()
{
var selList = new List<(int start, int end)>();
Expand Down
5 changes: 0 additions & 5 deletions JsonToolsNppPlugin/Utils/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ public class Settings : SettingsBase
Category("Performance"), DefaultValue(4d)]
public double max_file_size_MB_slow_actions { get; set; }

[Description("Maximum number of separate JSON selections to track changes for.\r\n" +
"Files with more JSON selections can be handled, but changes outside of JSON tools will cause all selections to be forgotten"),
Category("Performance"), DefaultValue(1000)]
public int max_tracked_json_selections { get; set; }

[Description("Automatically validate .json, .jsonc, and .jsonl files every 2 seconds, except very large files"),
Category("Performance"), DefaultValue(false)]
public bool auto_validate { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ __Note that your JSON selections (or lack thereof) are only remembered until you
- *NOTE: starting in [v5.7](/CHANGELOG.md#570---2023-09-08), only multi-character selections that begin with a parse-able JSON document will cause the previous selections/lack thereof to be forgotten.*
- For example, if you had the text `foo` selected, any version since 5.7 would ignore that selection because it does not begin with a valid JSON document.
- However, the selection `[ blah` *would override old selections even though it's not valid JSON* because the JSON parser will parse it as an unterminated empty array.
* For JsonTools *earlier than [v7.1](/CHANGELOG.md#710---unreleased-yyyy-mm-dd)*:
- doing a Notepad++ undo/redo action (Ctrl+Z or Ctrl+Y with default keybindings)
- performing any edit to the document when the number of remembered selections is greater than `max_tracked_json_selections`
* For JsonTools *[v7.1](/CHANGELOG.md#710---unreleased-yyyy-mm-dd) or later*, undoing or redoing a plugin action will still cause remembered selections to be forgotten.

You can move the cursor around, insert and delete characters, and the plugin will move or change the JSON selections accordingly.

Expand Down
Loading

0 comments on commit 4dbb720

Please sign in to comment.