Skip to content

Commit

Permalink
Tidy up the class library
Browse files Browse the repository at this point in the history
  * only a single demo used `SelectionManager` and it's not very portable

  * better document the pitfalls of calling methods intended for .NET Framework
    in the context of a native compiled app

  * don't expose array extensions that can be replaced by C# 8.0 range operations

  * don't expose all the stuff from JSON Tools in the primary namespace
  • Loading branch information
rdipardo committed Feb 6, 2025
1 parent 981dff4 commit 123530a
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 41 deletions.
6 changes: 6 additions & 0 deletions docfx/extra/Npp.DotNet.Plugin.Extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
uid: Npp.DotNet.Plugin.Extensions
summary: *content
---

Miscellaneous utility classes to assist .NET Framework developers, contributed by [Mark Johnston Olson](https://github.com/molsonkiko).
9 changes: 5 additions & 4 deletions examples/gui/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Text;
using System.Text.RegularExpressions;
using Npp.DotNet.Plugin;
using Npp.DotNet.Plugin.Extensions;
using Npp.DotNet.Plugin.Winforms;
using static Npp.DotNet.Plugin.Win32;
using static Npp.DotNet.Plugin.Winforms.WinUser;
Expand Down Expand Up @@ -399,10 +400,10 @@ static internal void doInsertHtmlCloseTag(char newChar)

int bufCapacity = 512;
var pos = NppUtils.Editor.GetCurrentPos();
int currentPos = pos;
int beginPos = currentPos - (bufCapacity - 1);
int startPos = (beginPos > 0) ? beginPos : 0;
int size = currentPos - startPos;
long currentPos = pos;
long beginPos = currentPos - (bufCapacity - 1);
long startPos = (beginPos > 0) ? beginPos : 0;
int size = unchecked(Convert.ToInt32(currentPos - startPos));

if (size < 3)
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,38 @@
using System.Linq;
using System.Text.RegularExpressions;

namespace Npp.DotNet.Plugin
namespace Npp.DotNet.Plugin.Gui.Demo
{
public class SelectionManager
{
private static readonly Regex START_END_REGEX = new Regex(@"^\d+,\d+$", RegexOptions.Compiled);

public static bool IsStartEnd(string x) => START_END_REGEX.IsMatch(x);

public static (int start, int end) ParseStartEndAsTuple(string startEnd)
public static (long start, long end) ParseStartEndAsTuple(string startEnd)
{
int[] startEndNums = ParseStartEnd(startEnd);
long[] startEndNums = ParseStartEnd(startEnd);
return (startEndNums[0], startEndNums[1]);
}

public static List<(int start, int end)> GetSelectedRanges()
public static List<(long start, long end)> GetSelectedRanges()
{
var selList = new List<(int start, int end)>();
var selList = new List<(long start, long end)>();
int selCount = NppUtils.Editor.GetSelections();
for (int ii = 0; ii < selCount; ii++)
selList.Add((NppUtils.Editor.GetSelectionNStart(ii), NppUtils.Editor.GetSelectionNEnd(ii)));
return selList;
}

public static bool NoTextSelected(IList<(int start, int end)> selections)
public static bool NoTextSelected(IList<(long start, long end)> selections)
{
(int start, int end) = selections[0];
(long start, long end) = selections[0];
return selections.Count < 2 && start == end;
}

public static bool NoTextSelected(IList<string> selections)
{
int[] startEnd = ParseStartEnd(selections[0]);
long[] startEnd = ParseStartEnd(selections[0]);
return selections.Count < 2 && startEnd[0] == startEnd[1];
}

Expand All @@ -49,19 +49,19 @@ public static bool NoTextSelected(IList<string> selections)
/// </summary>
/// <param name="startEnd"></param>
/// <returns></returns>
public static int[] ParseStartEnd(string startEnd)
public static long[] ParseStartEnd(string startEnd)
{
return startEnd.Split(',').Select(s => int.Parse(s)).ToArray();
return startEnd.Split(',').Where(s => long.TryParse(s, out long _)).Select(v => long.Parse(v)).ToArray();
}

public static List<(int start, int end)> SetSelectionsFromStartEnds(IEnumerable<string> startEnds)
public static List<(long start, long end)> SetSelectionsFromStartEnds(IEnumerable<string> startEnds)
{
int ii = 0;
NppUtils.Editor.ClearSelections();
var result = new List<(int start, int end)>();
var result = new List<(long start, long end)>();
foreach (string startEnd in startEnds)
{
(int start, int end) = ParseStartEndAsTuple(startEnd);
(long start, long end) = ParseStartEndAsTuple(startEnd);
if (start > end)
(start, end) = (end, start);
result.Add((start, end));
Expand Down Expand Up @@ -97,7 +97,7 @@ public static int StartEndCompareByStart(string s1, string s2)
return StartFromStartEnd(s1).CompareTo(StartFromStartEnd(s2));
}

public static int StartEndCompareByStart((int start, int end) se1, (int start, int end) se2)
public static int StartEndCompareByStart((long start, long end) se1, (long start, long end) se2)
{
return se1.start.CompareTo(se2.start);
}
Expand All @@ -109,7 +109,7 @@ public static int StartEndCompareByStart((int start, int end) se1, (int start, i
/// * StartEndListToString([(1, 2), (5, 7)], "], [") returns "1,2], [5,7"<br></br>
/// * StartEndListToString([(1, 2), (9, 20), (30,45)], " ") returns "1,2 9,20 30,45"
/// </summary>
public static string StartEndListToString(IEnumerable<(int start, int end)> selections, string sep = " ")
public static string StartEndListToString(IEnumerable<(long start, long end)> selections, string sep = " ")
{
return string.Join(sep, selections.OrderBy(x => x.start).Select(x => $"{x.start},{x.end}"));
}
Expand Down
28 changes: 25 additions & 3 deletions examples/minimal/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

using Figgle;
using System.Runtime.InteropServices;
using static System.Diagnostics.FileVersionInfo;
using static Npp.DotNet.Plugin.Win32;

namespace Npp.DotNet.Plugin.Demo
Expand Down Expand Up @@ -116,8 +117,8 @@ public override NativeBool OnMessageProc(uint msg, UIntPtr wParam, IntPtr lParam
static void HelloNpp()
{
NppUtils.Notepad.FileNew();
NppUtils.Editor.SetText(HelloTo);
NppUtils.AddLine(HelloFrom);
NppUtils.Editor.SetText(HelloTo.Replace("\r\n", NppUtils.Editor.LineDelimiter));
NppUtils.AddLine(HelloFrom.Replace("\r\n", NppUtils.Editor.LineDelimiter));
}

/// <summary>
Expand All @@ -130,7 +131,7 @@ static void DisplayInfo()
_ =
MsgBoxDialog(
PluginData.NppData.NppHandle,
$"{MenuTitles._4}: {NppUtils.AssemblyVersionString}\0",
$"{MenuTitles._4}: {AssemblyVersionString}\0",
$"{MenuTitles._5} {PluginName}",
mbMask
);
Expand All @@ -152,6 +153,27 @@ private static bool NativeLangIsRTL()
private static readonly Main Instance;
private static readonly PluginOptions Config;
private static readonly PluginMenuTitles MenuTitles;

private static string AssemblyVersionString
{
get
{
string version = "1.0.0.0";
try
{
string assemblyName = typeof(Main).Namespace!;
version =
GetVersionInfo(
Path.Combine(
NppUtils.Notepad.GetPluginsHomePath(), assemblyName, $"{assemblyName}.dll")
)
.FileVersion!;
}
catch { }
return version;
}
}

public static readonly string PluginName = ".NET Demo Plugin\0";
public static string PluginFolderName => PluginName.Trim(new char[] { '\0', '.' });
}
Expand Down
20 changes: 8 additions & 12 deletions lib/Npp.DotNet.Plugin/Kbg.NppPluginNET.Contrib/ArrayExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
using System.Linq;
using System.Text;

namespace Npp.DotNet.Plugin
namespace Npp.DotNet.Plugin.Extensions
{
public static class ArrayExtensions
{
// C# has a range operator since version 8.0
// https://learn.microsoft.com/dotnet/csharp/language-reference/operators/member-access-operators#range-operator-
#if !NETCOREAPP3_0_OR_GREATER
/// <summary>
/// Allows the use of Python-style slices, where start, stop, and stride must be declared as individual paramters.<br></br>
/// Thus e.g. arr.Slice(2, null, -1) is just like arr[slice(2, None, -1)] in Python.<br></br>
Expand Down Expand Up @@ -103,6 +106,7 @@ public static IEnumerable<T> LazySlice<T>(this IList<T> source, int? start, int?
}
}
}
#endif

/// <summary>
/// If num is negative, use Python-style negative indices (e.g., -1 is the last element, -len is the first elememnt)
Expand All @@ -126,6 +130,7 @@ public static int ClampWithinLen(int len, int num, bool is_start_idx)
return num;
}

#if !NETCOREAPP3_0_OR_GREATER
///<summary>
/// Allows the use of Python-style slices, passed as strings (e.g., ":", "1::-2").<br></br>
/// Because LazySlice is an extension method, all arrays in this namespace can use this method.<br></br>
Expand Down Expand Up @@ -287,6 +292,7 @@ public static string Slice(this string source, int?[] slicer)
{
return new string(source.ToCharArray().LazySlice(slicer).ToArray());
}
#endif

/// <summary>
/// randomize the order of the elements in arr
Expand Down Expand Up @@ -326,17 +332,7 @@ public static T Pop<T>(this List<T> list)
/// <returns></returns>
public static string ArrayToString<T>(this IList<T> list)
{
var sb = new StringBuilder();
sb.Append('[');
for (int ii = 0; ii < list.Count; ii++)
{
T x = list[ii];
sb.Append(x?.ToString());
if (ii < list.Count - 1)
sb.Append(", ");
}
sb.Append(']');
return sb.ToString();
return $"[{string.Join(", ", list)}]";
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion lib/Npp.DotNet.Plugin/Kbg.NppPluginNET.Contrib/NanInf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
namespace Npp.DotNet.Plugin
namespace Npp.DotNet.Plugin.Extensions
{
public class NanInf
{
Expand Down
61 changes: 55 additions & 6 deletions lib/Npp.DotNet.Plugin/Kbg.NppPluginNET.Contrib/NppUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,46 @@ public class NppUtils

public static string ConfigDirectory => Notepad.GetConfigDirectory();

#pragma warning disable CS1587
/// <summary>
/// Gets the version of the currently executing assembly as a formatted string.
/// </summary>
#if NET7_0_OR_GREATER
/// <remarks>
/// <para><em><b>Warning</b></em></para>
/// <para>
/// If this method is called in a native compiled app, the return value is the file version of
/// the <c>Npp.DotNet.Plugin.dll</c> assembly, <em>not</em> the version of the app as expected.
/// </para>
/// <para>
/// To properly fetch the file version of a native app, pass the fully qualified file name
/// to <see cref="System.Diagnostics.FileVersionInfo.GetVersionInfo"/> and use the
/// <see cref="System.Diagnostics.FileVersionInfo.FileVersion"/> property.
/// </para>
/// <example>
/// For example, assuming <c>Main</c> is the main class of a native app:
/// <code>
/// using System.IO;
/// using static System.Diagnostics.FileVersionInfo;
/// // ...
/// version = "";
/// try
/// {
/// string assemblyName = typeof(Main).Namespace!;
/// version =
/// GetVersionInfo(
/// Path.Combine(
/// NppUtils.Notepad.GetPluginsHomePath(), assemblyName, $"{assemblyName}.dll")
/// )
/// .FileVersion!;
/// }
/// catch {}
/// </code>
/// </example>
/// </remarks>
#endif
#pragma warning restore CS1587

public static string AssemblyVersionString
{
get
Expand All @@ -66,8 +106,7 @@ public static string AssemblyVersionString
/// <param name="inp"></param>
public static void AddLine(string inp)
{
Editor.AppendText(Encoding.UTF8.GetByteCount(inp), inp);
Editor.AppendText(Environment.NewLine.Length, Environment.NewLine);
Editor.AppendText($"{inp}{Editor.LineDelimiter}");
}

public enum PathType
Expand Down Expand Up @@ -136,21 +175,22 @@ public static void CreateConfigSubDirectoryIfNotExists()
/// <param name="start"></param>
/// <param name="end"></param>
/// <returns></returns>
public static string GetSlice(int start, int end)
public static string GetSlice(long start, long end)
{
int len = end - start;
long len = end - start;
IntPtr rangePtr = Editor.GetRangePointer(start, len);
string ansi = Marshal.PtrToStringAnsi(rangePtr, len);
string ansi = Marshal.PtrToStringAnsi(rangePtr, unchecked(Convert.ToInt32(len)));
// TODO: figure out a way to do this that involves less memcopy for non-ASCII
if (ansi.Any(c => c >= 128))
return Encoding.UTF8.GetString(Encoding.Default.GetBytes(ansi));
return Encoding.UTF8.GetString(Editor.CodePage.GetBytes(ansi));
return ansi;
}

private static readonly string[] newlines = new string[] { "\r\n", "\r", "\n" };

/// <summary>0: CRLF, 1: CR, 2: LF<br></br>
/// Anything less than 0 or greater than 2: LF</summary>
[Obsolete("Use the Npp.DotNet.Plugin.IScintillaGateway.LineDelimiter property instead ")]
public static string GetEndOfLineString(int eolType)
{
if (eolType < 0 || eolType >= 3)
Expand All @@ -164,7 +204,16 @@ private static string NppVersionString(bool include32bitVs64bit)
string nppVerStr = $"{major}.{minor}.{revision}";
return include32bitVs64bit ? $"{nppVerStr} {IntPtr.Size * 8}bit" : nppVerStr;
}
}
}

namespace Npp.DotNet.Plugin.Extensions
{
/// <summary>
/// Utilities ported from the <a href="https://github.com/molsonkiko/JsonToolsNppPlugin">JSON Tools</a> plugin.
/// </summary>
public static class JsonUtils
{
/// <summary>
/// appends the JSON representation of char c to a StringBuilder.<br></br>
/// for most characters, this just means appending the character itself, but for example '\n' would become "\\n", '\t' would become "\\t",<br></br>
Expand Down

0 comments on commit 123530a

Please sign in to comment.