Skip to content

Commit

Permalink
Merge pull request #1241 from stevencohn/1236-highlight-hashtags
Browse files Browse the repository at this point in the history
1236 highlight hashtags
  • Loading branch information
stevencohn authored Dec 28, 2023
2 parents 9280268 + 8b8fa33 commit aa61c61
Show file tree
Hide file tree
Showing 34 changed files with 874 additions and 141 deletions.
131 changes: 102 additions & 29 deletions OneMore/Commands/Favorites/FavoritesProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace River.OneMoreAddIn
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Xml.Linq;
using Resx = Properties.Resources;
Expand Down Expand Up @@ -197,36 +198,110 @@ public List<Favorite> SortFavorites()
}


/// <summary>
/// Confirm that each favorite exists and is reachable with the by ID. For those that
/// are not reachable, confirm if the Location/Screentip/path is reachable and, if so,
/// patch the favorite with an updated ID.
/// </summary>
/// <param name="favorites">List of favorites to validate</param>
/// <returns></returns>
public async Task ValidateFavorites(List<Favorite> favorites)
{
one ??= new OneNote();

notebooks = new Dictionary<string, XElement>();
var updated = false;

foreach (var f in favorites)
{
f.Status = string.IsNullOrWhiteSpace(f.NotebookID) || string.IsNullOrWhiteSpace(f.ObjectID)
? await ConfirmByName(f.Location)
: await ConfirmByID(f.NotebookID, f.ObjectID);
if (!string.IsNullOrWhiteSpace(f.NotebookID) &&
!string.IsNullOrWhiteSpace(f.ObjectID))
{
await ConfirmByID(f);
}

// ConfirmByID would only return either Known or Unknown
if (f.Status == FavoriteStatus.Unknown)
{
// infer from location and update ID
updated = await ConfirmByLocation(f) || updated;
}
}

if (updated)
{
logger.WriteLine("saving updated favorites!");
var root = FavoritesProvider.MakeMenuRoot();
foreach (var favorite in favorites)
{
root.Add(favorite.Root);
}

using var provider = new FavoritesProvider(ribbon);
provider.SaveFavorites(root);
}
else
{
logger.WriteLine("favorites check OK");
}
}


private async Task<FavoriteStatus> ConfirmByName(string path)
private async Task ConfirmByID(Favorite favorite)
{
XElement notebook = null;
if (notebooks.ContainsKey(favorite.NotebookID))
{
notebook = notebooks[favorite.NotebookID];
}
else
{
try
{
notebook = await one.GetNotebook(favorite.NotebookID, OneNote.Scope.Pages);
notebooks.Add(favorite.NotebookID, notebook);
}
catch (COMException exc) when ((uint)exc.ErrorCode == ErrorCodes.hrObjectMissing)
{
logger.WriteLine($"broken link to favorite notebook {favorite.Location}");
}
catch (Exception exc)
{
logger.WriteLine($"could not fetch favorite notebook {favorite.Location}", exc);
}
}

if (notebook != null &&
notebook.Descendants().Any(e => e.Attribute("ID")?.Value == favorite.ObjectID))
{
favorite.Status = FavoriteStatus.Known;
}
else
{
logger.WriteLine($"broken link to favorite notebook {favorite.Location}");
favorite.Status = FavoriteStatus.Unknown;
}
}


private async Task<bool> ConfirmByLocation(Favorite favorite)
{
books ??= await one.GetNotebooks();

var parts = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var parts = favorite.Location.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var notebook = notebooks.Values.FirstOrDefault(n => n.Attribute("name")?.Value == parts[0]);
if (notebook == null)
{
// first part should be name of notebook
var nx = books.GetNamespaceOfPrefix(OneNote.Prefix);
var book = books.Elements(nx + "Notebook")
.FirstOrDefault(n => n.Attribute("name")?.Value == parts[0]);

if (book == null)
{
return FavoriteStatus.Suspect;
logger.WriteLine($"broken link to favorite notebook {favorite.Location}");
favorite.Status = FavoriteStatus.Suspect;
return false;
}

var id = book.Attribute("ID").Value;
Expand All @@ -248,37 +323,35 @@ private async Task<FavoriteStatus> ConfirmByName(string path)
node = node.Elements().FirstOrDefault(n => n.Attribute("name").Value == parts[i]);
if (node == null)
{
return FavoriteStatus.Suspect;
logger.WriteLine($"broken link to favorite parts[{i}] {favorite.Location}");
favorite.Status = FavoriteStatus.Suspect;
return false;
}
}

return FavoriteStatus.Known;
}
favorite.Status = FavoriteStatus.Known;

var notebookID = notebook.Attribute("ID").Value;
var nodeID = node.Attribute("ID").Value;

private async Task<FavoriteStatus> ConfirmByID(string notebookID, string objectID)
{
XElement notebook = null;
if (notebooks.ContainsKey(notebookID))
{
notebook = notebooks[notebookID];
}
else
if (favorite.NotebookID != notebookID ||
favorite.ObjectID != nodeID)
{
try
{
notebook = await one.GetNotebook(notebookID, OneNote.Scope.Pages);
notebooks.Add(notebookID, notebook);
}
catch (Exception exc)
{
logger.WriteLine($"unrecognized notebook {notebookID}", exc);
}
logger.WriteLine($"patching favorite IDs {favorite.Location}");

favorite.NotebookID = notebookID;
favorite.ObjectID = nodeID;

favorite.Root.SetAttributeValue("notebookID", notebookID);
favorite.Root.SetAttributeValue("objectID", nodeID);
favorite.Root.SetAttributeValue("tag", one.GetHyperlink(nodeID, string.Empty));

logger.WriteLine(favorite.Root);

return true;
}

return notebook != null && notebook.Descendants().Any(e => e.Attribute("ID")?.Value == objectID)
? FavoriteStatus.Known
: FavoriteStatus.Unknown;
return false;
}


Expand Down
21 changes: 17 additions & 4 deletions OneMore/Commands/Search/SearchAndReplaceCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public override async Task Execute(params object[] args)
string withText;
bool matchCase;
bool useRegex;
XElement withElement;

using var one = new OneNote(out var page, out _);
var text = page.GetSelectedText();
Expand All @@ -44,17 +45,29 @@ public override async Task Execute(params object[] args)

whatText = dialog.WhatText;
withText = dialog.WithText;
withElement = dialog.RawXml;
matchCase = dialog.MatchCase;
useRegex = dialog.UseRegex;
}

// let user insert a newline char
withText = withText.Replace("\\n", "\n");

var editor = new SearchAndReplaceEditor(whatText, withText,
enableRegex: useRegex,
caseSensitive: matchCase
);
SearchAndReplaceEditor editor;
if (withElement == null)
{
editor = new SearchAndReplaceEditor(whatText, withText,
enableRegex: useRegex,
caseSensitive: matchCase
);
}
else
{
editor = new SearchAndReplaceEditor(whatText, withElement,
enableRegex: useRegex,
caseSensitive: matchCase
);
}

var count = editor.SearchAndReplace(page);

Expand Down
22 changes: 19 additions & 3 deletions OneMore/Commands/Search/SearchAndReplaceDialog.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 52 additions & 2 deletions OneMore/Commands/Search/SearchAndReplaceDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace River.OneMoreAddIn.Commands
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml.Linq;
using Resx = Properties.Resources;

Expand All @@ -31,6 +32,7 @@ public SearchAndReplaceDialog()
"withLabel",
"matchBox",
"regBox",
"rawBox",
"okButton=word_OK",
"cancelButton=word_Cancel"
});
Expand All @@ -46,6 +48,14 @@ public SearchAndReplaceDialog()
private void LoadSettings()
{
var provider = new SettingsProvider();

var experimental = provider.GetCollection("GeneralSheet").Get<bool>("experimental");
if (!experimental)
{
rawBox.Visible = false;
Height -= rawBox.Height;
}

var settings = provider.GetCollection("SearchReplace");
if (settings != null)
{
Expand All @@ -61,9 +71,15 @@ private void LoadSettings()
var withs = settings.Get<XElement>("withs");
if (withs != null)
{
foreach (var withText in withs.Elements())
foreach (var withText in withs.Elements().Select(e => e.Value))
{
withBox.Items.Add(withText.Value);
var text = withText;
if (text.StartsWith("&lt;") && text.EndsWith("&gt;"))
{
text = HttpUtility.HtmlDecode(text);
}

withBox.Items.Add(text);
}
}
}
Expand All @@ -72,6 +88,8 @@ private void LoadSettings()

public bool MatchCase => matchBox.Checked;

public XElement RawXml { get; private set; }

public string WithText => withBox.Text;

public bool UseRegex => regBox.Checked;
Expand All @@ -97,6 +115,12 @@ private void ToggleRegex(object sender, EventArgs e)
}


private void ToggleRawXml(object sender, EventArgs e)
{
CheckXmlFormat(sender, e);
}


private void CheckPattern(object sender, EventArgs e)
{
var text = whatBox.Text.Trim();
Expand Down Expand Up @@ -149,6 +173,32 @@ private void CheckPattern(object sender, EventArgs e)
}


private void CheckXmlFormat(object sender, EventArgs e)
{
if (rawBox.Checked)
{
var xml = withBox.Text.Trim();
try
{
RawXml = XElement.Parse(xml);
}
catch
{
withStatusLabel.Text = "XML format is not correct";
return;
}
}
else
{
RawXml = null;
}

// ensure whatStatus is restored correctly
CheckPattern(sender, e);
}



private void SelectedWhat(object sender, EventArgs e)
{
if (whatBox.SelectedIndex >= 0 && whatBox.SelectedIndex < whats.Elements().Count())
Expand Down
Loading

0 comments on commit aa61c61

Please sign in to comment.