Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
tangledhelix committed May 26, 2024
1 parent be87783 commit 1ba3009
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 180 deletions.
138 changes: 138 additions & 0 deletions TODO.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# https://tkdocs.com/tutorial/text.html
#
# https://stackoverflow.com/a/3781773
# The basic concept is, you assign properties to tags, and you apply tags to
# ranges of text in the widget. You can use the text widget's search command to
# find strings that match your pattern, which will return you enough information
# apply a tag to the range that matched.
#
# https://stackoverflow.com/a/3781773
# This answer seems to have a way to do a search/match with a regex? Also Nigel
# probably has done a lot of work here that can be used as an example of even
# re-used.
#
# Relevant tickets (all from GG1 search menu):
#
# Highlight Character, String or Regex #41 - https://github.com/DistributedProofreaders/guiguts-py/issues/41
# Behavior:
# - opens a dialog
# - accepts a string input
# - has either "exact" or "regex" mode - a toggle
# - works on a selection if present; or else lets you choose "prev selection" or else "select whole file"
# - and then "apply highlights" or "remove highlight"

# Highlight surrounding quotes/brackets #42 - https://github.com/DistributedProofreaders/guiguts-py/issues/42
# Behavior:
# - Wherever the cursor is place, surrounding markers are highlighted
# - it can match left to right brackets i think but quotes just any pair.
# - it doesn't necessarily do only the innermost like for ({foo bar}) it would
# highlight both of the bracket pairs ... have to analyze what it's doing in GG1
# - colors:
# - gray for ' ‘’ (single quote)
# - green for " “ ” (double quote)
# - pink for ( )
# - purple for [ ]
# - blue for { }
# - it doesn't seem to match < >
# - not sure about guillemet
# - check what guiguts1 does.

# Highlight Alignment Column #43 - https://github.com/DistributedProofreaders/guiguts-py/issues/43
# Behavior:
# - identify column at cursor
# - find all characters at the column PRIOR, so to left of the bar cursor position
# - highlight that character
# - so if cursor is at column 3, highlight any character in column 2 on any line
# - it only can highlight lines with a character; lines with no char in that column
# get no highlight there
# - THIS COLUMN DOESN'T MOVE but as the text may move or change, on each change,
# or maybe firing on some timer, it re-highlights so that even if text change,
# the highlight column stays in the same location.
# - this seems to be something that has to be done on each redraw / cursor position move?
# is there a central hook to hang that on? In GG1 it can lag, which makes me think it is
# firing on 250ms timer or something instead of "on each change" ? have to investigate.

# Other things, not ticketed, but related:
# Search -> Highlight single quotes in selection
# Search -> Highlight double quotes in selection

# These are all defined in GG1 in MenuStructure.pm lines 337+

# Order of these by how easy they seem:
# 1. Highlight surrounding quotes/brackets #42
# this is a CheckButton which then has a command tied to it...
# Highlight.pm :: highlight_quotbrac()
# 2. Highlight Alignment Column #43 (must be done on each redraw...)
# Highlight.pm :: it calls a lambda that runs hilite_alignment_{start,stop}()
# this is a CheckButton
# 3. Highlight Character, String or Regex #41 (needs a dialog)
# Highlight.pm :: hilitepopup()
# 4. Search -> Highlight single quotes in selection
# Highlight.pm :: hilitesinglequotes() -> calls hilite()
# 5. Search -> Highlight double quotes in selection
# Highlight.pm :: hilitedoublequotes() -> calls hilite()

# [
# 'command', 'Highlight ~Double Quotes in Selection',
# -accelerator => 'Ctrl+.',
# -command => \&::hilitedoublequotes,
# ],
# [
# 'command', 'Highlight ~Single Quotes in Selection',
# -accelerator => 'Ctrl+,',
# -command => \&::hilitesinglequotes,
# ],
# [
# 'command', '~Highlight Character, String or Regex...',
# -accelerator => "Ctrl+$::altkeyname+h",
# -command => \&::hilitepopup,
# ],
# [
# Checkbutton => 'Highlight S~urrounding Quotes & Brackets',
# -variable => \$::nohighlights,
# -onvalue => 1,
# -offvalue => 0,
# -accelerator => "Ctrl+;",
# -command => \&::highlight_quotbrac
# ],
# [
# Checkbutton => 'Highlight Al~ignment Column',
# -accelerator => 'Ctrl+Shift+a',
# -variable => \$::lglobal{highlightalignment},
# -onvalue => 1,
# -offvalue => 0,
# -command => sub {
# if ( $::lglobal{highlightalignment} ) {
# ::hilite_alignment_start();
# } else {
# ::hilite_alignment_stop();
# }
# $textwindow->focus;
# }
# ],
# [
# 'command', 'Re~move Highlights',
# -accelerator => 'Ctrl+0',
# -command => \&::hiliteremove,
# ],

# Things I need to work out:
#
# - these two are menu items in the Search menu. seems like it's just a "take this action" thing.
# - look at GG1 "highlight single quotes in selection" algorithm
# - look at GG1 "highlight double quotes in selection" algorithm
# - make a function to highlight quotes (either kind) to use for both of the above 2
#
# - Search menu - this is a checkbox / toggle thing. as you move the cursor it CHANGES the surround that's highlighted.
# - so this is another thing that is on every cursor move / redraw? have to re-evaluate it
# - look at GG1 "highlight surrounding quote/bracket" algorithm
# - look at the colors used by the different things and map it in that function
# - make generic function to highlight surrounding (anything) to use for the above
#
# - Search menu - this is a checkbox / toggle thing. as you move cursor if changes with every redraw.
# - make a function to highlight the alignment column
# - look to see if there's an "every change" function that can be used for "on redraw" already
# - implement that if it's not already there. ask nigel first to be sure.
#
# - create dialog box for the char/str/re function
# - work on the implementation(s) behind that
49 changes: 38 additions & 11 deletions src/guiguts/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from guiguts.checkers import CheckerSortType
from guiguts.data import themes
from guiguts.file import File, the_file, NUM_RECENT_FILES
from guiguts.highlight import highlight_quotbrac, toggle_highlight_quotbrac
from guiguts.maintext import maintext
from guiguts.mainwindow import (
MainWindow,
Expand All @@ -36,7 +37,7 @@
from guiguts.page_details import PageDetailsDialog
from guiguts.preferences import preferences, PrefKey
from guiguts.root import root
from guiguts.search import show_search_dialog, find_next, poc_highlighter
from guiguts.search import show_search_dialog, find_next
from guiguts.spell import spell_check
from guiguts.tools.pptxt import pptxt
from guiguts.tools.jeebies import jeebies_check, JeebiesParanoiaLevel
Expand Down Expand Up @@ -320,6 +321,7 @@ def initialize_preferences(self) -> None:
),
)
preferences.set_default(PrefKey.TEAROFF_MENUS, False)
preferences.set_default(PrefKey.HIGHLIGHT_QUOTBRAC, False)

# Check all preferences have a default
for pref_key in PrefKey:
Expand Down Expand Up @@ -432,6 +434,7 @@ def init_edit_menu(self) -> None:
menu_edit.add_separator()
menu_edit.add_button("Pre~ferences...", PreferencesDialog.show_dialog)

# TODO: this should be menu_search not menu_view, in here.
def init_search_menu(self) -> None:
"""Create the View menu."""
menu_view = Menu(menubar(), "~Search")
Expand All @@ -450,16 +453,40 @@ def init_search_menu(self) -> None:
lambda: find_next(backwards=True),
"Cmd+Shift+G" if is_mac() else "Shift+F3",
)
menu_view.add_button(
"Highlight the word curly",
lambda: poc_highlighter(word="curly"),
"",
)
menu_view.add_button(
"Delete Highlights",
lambda: poc_highlighter(disable=True),
"",
)
menu_view.add_checkbox(
"Highlight S~urrounding Quotes & Brackets",
toggle_highlight_quotbrac,
toggle_highlight_quotbrac,
preferences.get(PrefKey.HIGHLIGHT_QUOTBRAC),
)

# TODO nohighlights should persist in preferences dict/file?
# menu_view.add_checkbutton(
# label="Highlight S~urrounding Quotes & Brackets",
# variable=nohighlights,
# onvalue=True,
# offvalue=False,
# accelerator="Cmd-;",
# command=highlight_quotbrac,
# )
# [
# Checkbutton => 'Highlight S~urrounding Quotes & Brackets',
# -variable => \$::nohighlights,
# -onvalue => 1,
# -offvalue => 0,
# -accelerator => "Ctrl+;",
# -command => \&::highlight_quotbrac
# ],
# menu_view.add_button(
# "Highlight the word curly",
# lambda: poc_highlighter(word="curly"),
# "",
# )
# menu_view.add_button(
# "Delete Highlights",
# lambda: poc_highlighter(disable=True),
# "",
# )

def init_tools_menu(self) -> None:
"""Create the Tools menu."""
Expand Down
140 changes: 140 additions & 0 deletions src/guiguts/highlight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""Highlighter functionality"""

import logging
import tkinter as tk
# from tkinter import ttk
from typing import Any, Tuple, Optional

# import regex as re

# from guiguts.checkers import CheckerDialog
from guiguts.maintext import maintext
# from guiguts.maintext import maintext, TclRegexCompileError
from guiguts.preferences import preferences, PersistentBoolean, PrefKey
from guiguts.utilities import (
# sound_bell,
# IndexRowCol,
IndexRange,
# process_accel,
# is_mac,
# sing_plur,
)
# from guiguts.widgets import ToplevelDialog, Combobox, mouse_bind, ToolTip

logger = logging.getLogger(__package__)

# MARK_FOUND_START = "FoundStart"
# MARK_FOUND_END = "FoundEnd"
# MARK_END_RANGE = "SearchRangeEnd"

def poc_highlighter(word="", disable=False) -> None:
"""
Only a proof-of-concept for now. Figuring out how to highlight text.
"""

# a tag name for our highlight thingamajig
tag_name = "dmlhighlightword"

if disable:
maintext().tag_delete(tag_name)
return

# TODO: either augment the search dialog with a button for
# this, or else create a new dialog? See how the GG1 flow works.
search_string = word

# Configure what this tag will look like
# TODO: eventually let user control the colors in a pref or something
maintext().tag_configure(tag_name, background="OliveDrab1", foreground="black")

# TODO: improve on this with differing cases; see
# search.py : SearchDialog.findall_clicked for examples

# hack for now
find_range = IndexRange(maintext().start(), maintext().end())
# find_range = (the_range, "in entire file")

matches = maintext().find_matches(
search_string,
find_range, # what is this??
nocase=False, # figure out how to handle this
regexp=False, # um handle later
wholeword=False, # handle later
)
count = len(matches)
print(f"Found {count} things to highlight")

# Example of how to do highlight
# matches should contain an array of FindMatch
# so match.rowcol.index() should return the start position like 'x.y'
# match.rowcol.count should return the length
# and this code shows how to find from an index to +x chars:
# rowcol_end = maintext().rowcol(match.rowcol.index() + f"+{match.count}c")

# TODO: This doesn't currently behave in the way that GG1 behaves.
# In GG1 if you highlight quotes they stay (unless overwritten.)
# If you highlight a word/match it will highlight but if you insert anything
# in the middle of a word it will split and NOT highlight that word anymore.
# do I need to highlight each individual character to mimic that behavior??
# And if you highlight the alignment column, then it will re-highlight if you
# insert, delete, or overwrite text involving that column. It must be in the
# main loop checking on each redraw.

# GG1 references:
# The popup when you run "Highlight Chars, ..." is in Highlight.pm, sub hilitepopup
# There is a search history here. And a whole dialog.
# The "highlight surrounding brackets" menu item calls Highlight.pm sub highlight_quotbrac
# The "highlight alignment column" menu item calls code in Highlight.pm:
# to start: hilite_alignment_start, to stop: hilite_alignment_stop
# it's all keyed off a global value, a bool `highlightalignment`. menu is a checkbox item.
# (?) can menus in macos act as toggles too? (i think so) - does it work in tkinter?
# and if so does it also work in linux?
# the funcs note they are called every 200ms
# in hilite_alignment_start, a repeating function is started that handles this.
# $::lglobal{align_id} = $::top->repeat( 200, \&hilite_alignment );
# later on this is called with ->cancel to stop the repeating routine
# so it just calls the actual hilight_alignment routine every 200ms

for match in matches:
for n in range(match.count):
if n % 2 == 0:
continue
# maintext().tag_add(tag_name, match.rowcol.index(), match.rowcol.index() + f"+{match.count}c")
__mystart = match.rowcol.index() # + f"+{n}c"
__myend = match.rowcol.index() + f"+{n+1}c"
print(f"Highlighter: from {__mystart} to {__myend}")
maintext().tag_add(tag_name, __mystart, __myend)

# Can I get from the above thing, a FindMatch, to somehow an IndexRange?
# An IndexRange would have
# _range.start.index(), _range.end.index()

# TODO: the below is enough to:
# - set the value
# - save the value in preferences persistently
# - store the value in a place we can easily find it
# NEXT THINGS
# - in the _on and _off routine need to either start, or stop, the 400ms loop
# - on startup if the value is true then also start that loop up
# - and somewhere the handler needs to live (this file?) which does the work every 400mx.
# - steal the code from GG1 to do that.

def toggle_highlight_quotbrac() -> None:
"""Turn on/off highlighting for quotes and brackets"""

pref = PrefKey.HIGHLIGHT_QUOTBRAC

if preferences.get(pref):
preferences.set(pref, False)
print("Turn quote/bracket highlighting off.")

else:
preferences.set(pref, True)
print("Turn quote/bracket highlighting on.")

print(preferences.get(pref))

def highlight_quotbrac():
"""Action routine to highlight quotes/brackets that surround the cursor"""

print("Firing highlight_quotbrac.")
1 change: 1 addition & 0 deletions src/guiguts/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class PrefKey(StrEnum):
PAGESEP_AUTO_TYPE = auto()
THEME_NAME = auto()
TEAROFF_MENUS = auto()
HIGHLIGHT_QUOTBRAC = auto()


class Preferences:
Expand Down
Loading

0 comments on commit 1ba3009

Please sign in to comment.