Skip to content

Commit b773ff8

Browse files
committed
added some untested samples from N++ community or pythonscript sourceforge discussion forum
1 parent 8227d24 commit b773ff8

File tree

4 files changed

+1135
-0
lines changed

4 files changed

+1135
-0
lines changed
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
#From https://notepad-plus-plus.org/community/topic/14501/has-a-plugin-like-sublime-plugin-brackethighlighter/7
2+
3+
try:
4+
5+
BH__dict
6+
7+
except NameError:
8+
9+
BH__dict = dict()
10+
11+
BH__dict['indic_for_box_at_caret'] = 10 # pick a free indicator number
12+
13+
def indicatorOptionsSet(indicator_number, indicator_style, rgb_color_tup, alpha, outline_alpha, draw_under_text, which_editor=editor):
14+
which_editor.indicSetStyle(indicator_number, indicator_style) # e.g. INDICATORSTYLE.ROUNDBOX
15+
which_editor.indicSetFore(indicator_number, rgb_color_tup)
16+
which_editor.indicSetAlpha(indicator_number, alpha) # integer
17+
which_editor.indicSetOutlineAlpha(indicator_number, outline_alpha) # integer
18+
which_editor.indicSetUnder(indicator_number, draw_under_text) # boolean
19+
20+
for editorX in (editor1, editor2):
21+
indicatorOptionsSet(BH__dict['indic_for_box_at_caret'], INDICATORSTYLE.STRAIGHTBOX, (238,121,159), 0, 255, True, editorX) # white box rimmed in "pale violet red 2"
22+
23+
BH__dict['last_modificationType_for_hack'] = None
24+
25+
def BH__containing_box_indices_into_string(str_containing_caret, caret_index_into_str):
26+
27+
class Stack:
28+
def __init__(self): self.clear()
29+
def isEmpty(self): return self.size() == 0
30+
def push(self, item): self.items.append(item)
31+
def pop(self): return None if self.size() == 0 else self.items.pop()
32+
def peek(self): return None if self.size() == 0 else self.items[self.size() - 1]
33+
def size(self): return len(self.items)
34+
def clear(self): self.items = []
35+
36+
retval = (None, None) # default to no valid box
37+
38+
get_opening_char_via_closing_char_dict = {
39+
')' : '(',
40+
']' : '[',
41+
'}' : '{',
42+
}
43+
get_closing_char_via_opening_char_dict = dict((v, k) for (k, v) in get_opening_char_via_closing_char_dict.items())
44+
45+
closing_chars = get_opening_char_via_closing_char_dict.keys()
46+
opening_chars = get_opening_char_via_closing_char_dict.values()
47+
48+
box_ending_index = -1
49+
box_starting_index = -1
50+
51+
stack = Stack()
52+
53+
for j in range(caret_index_into_str, len(str_containing_caret)):
54+
c = str_containing_caret[j]
55+
if c in closing_chars:
56+
if stack.isEmpty():
57+
box_ending_index = j
58+
break
59+
else:
60+
if stack.peek() == get_opening_char_via_closing_char_dict[c]:
61+
stack.pop()
62+
else:
63+
break # unbalanced
64+
elif c in opening_chars:
65+
stack.push(c)
66+
67+
if box_ending_index != -1:
68+
stack.clear()
69+
box_starting_index = -1
70+
for j in range(caret_index_into_str - 1, -1, -1):
71+
c = str_containing_caret[j]
72+
if c in opening_chars:
73+
if stack.isEmpty():
74+
box_starting_index = j
75+
break
76+
else:
77+
if stack.peek() == get_closing_char_via_opening_char_dict[c]:
78+
stack.pop()
79+
else:
80+
break # unbalanced
81+
elif c in closing_chars:
82+
stack.push(c)
83+
84+
if box_ending_index != -1:
85+
if box_starting_index != -1:
86+
if str_containing_caret[box_ending_index] == get_closing_char_via_opening_char_dict[str_containing_caret[box_starting_index]]:
87+
retval = (box_starting_index, box_ending_index + 1)
88+
89+
return retval
90+
91+
def BH__callback_sci_MODIFIED(args):
92+
global BH__dict
93+
BH__dict['last_modificationType_for_hack'] = args['modificationType']
94+
95+
def BH__fileIsCloned(file_name_to_test):
96+
retval = False
97+
clone_detect_dict = {}
98+
file_tup_list = notepad.getFiles()
99+
for tup in file_tup_list:
100+
(filename, _, _, _) = tup
101+
if filename not in clone_detect_dict:
102+
clone_detect_dict[filename] = 0
103+
else:
104+
clone_detect_dict[filename] += 1
105+
if filename == file_name_to_test: break
106+
if file_name_to_test in clone_detect_dict:
107+
if clone_detect_dict[file_name_to_test] >= 1: retval = True
108+
return retval
109+
110+
def BH__fileIsClonedAndIsActiveInBothViews(file_name_to_test):
111+
retval = False
112+
if editor1 and editor2:
113+
# both views are in use
114+
if BH__fileIsCloned(file_name_to_test):
115+
curr_doc_index_main_view = notepad.getCurrentDocIndex(0)
116+
curr_doc_index_2nd_view = notepad.getCurrentDocIndex(1)
117+
main_view_active_doc_bool = False
118+
secondary_view_active_doc_bool = False
119+
file_tup_list = notepad.getFiles()
120+
for tup in file_tup_list:
121+
(filename, _, index_in_view, view_number) = tup
122+
if filename == file_name_to_test:
123+
if view_number == 0:
124+
if index_in_view == curr_doc_index_main_view:
125+
main_view_active_doc_bool = True
126+
elif view_number == 1:
127+
if index_in_view == curr_doc_index_2nd_view:
128+
secondary_view_active_doc_bool = True
129+
if main_view_active_doc_bool and secondary_view_active_doc_bool:
130+
retval = True
131+
break
132+
return retval
133+
134+
def BH__getViewableEditorAndRangeTupleListList(work_across_both_views):
135+
retval = []
136+
# retval looks like these examples:
137+
# [ ( editor, [ (0, 1000), (2020, 3000) ] ) ]
138+
# [ ( editor1, [ (0, 1000), (2020, 3000) ] ), ( editor2, [ (4000, 5000), (6020, 7000) ] ) ]
139+
def consolidate_range_tuple_list(range_tup_list):
140+
sorted_range_tup_list = sorted(range_tup_list) # sort criteria is first element of tuple in list
141+
saved_2element_list = list(sorted_range_tup_list[0])
142+
for (start, end) in sorted_range_tup_list:
143+
if start <= saved_2element_list[1]:
144+
saved_2element_list[1] = max(saved_2element_list[1], end)
145+
else:
146+
yield tuple(saved_2element_list)
147+
saved_2element_list[0] = start
148+
saved_2element_list[1] = end
149+
yield tuple(saved_2element_list)
150+
def get_onscreen_pos_tup_list(which_editor): # which_editor is editor1 or editor2 (or maybe even just plain editor)
151+
# loosely based upon the N++ source for SmartHighlighter::highlightViewWithWord()
152+
retval_tup_list = list()
153+
temp_tup_list = []
154+
MAXLINEHIGHLIGHT = 400
155+
firstLine = which_editor.getFirstVisibleLine()
156+
currentLine = firstLine
157+
nbLineOnScreen = which_editor.linesOnScreen()
158+
nrLines = min(nbLineOnScreen, MAXLINEHIGHLIGHT) + 1
159+
lastLine = firstLine + nrLines
160+
prevDocLineChecked = -1
161+
break_out = False
162+
while currentLine < lastLine:
163+
docLine = which_editor.docLineFromVisible(currentLine)
164+
if docLine != prevDocLineChecked:
165+
prevDocLineChecked = docLine
166+
startPos = which_editor.positionFromLine(docLine)
167+
endPos = which_editor.positionFromLine(docLine + 1)
168+
if endPos == -1:
169+
endPos = which_editor.getTextLength() - 1
170+
break_out = True
171+
if endPos > startPos: temp_tup_list.append((startPos, endPos))
172+
if break_out: break
173+
currentLine += 1
174+
if len(temp_tup_list) > 0:
175+
retval_tup_list = list(consolidate_range_tuple_list(temp_tup_list))
176+
return retval_tup_list
177+
both_views_open = True if editor1 and editor2 else False
178+
curr_file_active_in_both_views = BH__fileIsClonedAndIsActiveInBothViews(notepad.getCurrentFilename()) if both_views_open else False
179+
if both_views_open:
180+
ed1_range_tup_list = get_onscreen_pos_tup_list(editor1)
181+
ed2_range_tup_list = get_onscreen_pos_tup_list(editor2)
182+
if curr_file_active_in_both_views:
183+
range_tup_list = list(consolidate_range_tuple_list(ed1_range_tup_list + ed2_range_tup_list))
184+
retval.append((editor, range_tup_list))
185+
elif both_views_open and work_across_both_views:
186+
retval.append((editor1, ed1_range_tup_list))
187+
retval.append((editor2, ed2_range_tup_list))
188+
else:
189+
range_tup_list = get_onscreen_pos_tup_list(editor)
190+
retval.append((editor, range_tup_list))
191+
return retval
192+
193+
def BH__callback_sci_UPDATEUI(args):
194+
195+
# hack, see https://notepad-plus-plus.org/community/topic/12360/vi-simulator-how-to-highlight-a-word/27, look for "16400" in code:
196+
if args['updated'] == UPDATE.CONTENT and BH__dict['last_modificationType_for_hack'] == (MODIFICATIONFLAGS.CHANGEINDICATOR | MODIFICATIONFLAGS.USER): return
197+
198+
for (editorX, pos_range_tuple_list) in BH__getViewableEditorAndRangeTupleListList(True):
199+
200+
# clear out any existing highlighting in areas the user can currently see
201+
for (start_pos, end_pos) in pos_range_tuple_list:
202+
editorX.setIndicatorCurrent(BH__dict['indic_for_box_at_caret'])
203+
editorX.indicatorClearRange(start_pos, end_pos - start_pos)
204+
205+
for (start_pos, end_pos) in pos_range_tuple_list:
206+
207+
if start_pos <= editorX.getCurrentPos() <= end_pos:
208+
209+
(box_start_offset, box_end_offset) = BH__containing_box_indices_into_string(
210+
editorX.getTextRange(start_pos, end_pos),
211+
editorX.getCurrentPos() - start_pos
212+
)
213+
214+
if box_start_offset != None:
215+
size_of_box_in_chars = box_end_offset - box_start_offset
216+
if size_of_box_in_chars <= 2:
217+
pass # rather pointless to box in if the opening and closing delims are right next to each other
218+
else:
219+
editorX.setIndicatorCurrent(BH__dict['indic_for_box_at_caret'])
220+
editorX.indicatorFillRange(start_pos + box_start_offset, size_of_box_in_chars)
221+
222+
editor.callbackSync(BH__callback_sci_UPDATEUI, [SCINTILLANOTIFICATION.UPDATEUI]) # install callback
223+
editor.callbackSync(BH__callback_sci_MODIFIED, [SCINTILLANOTIFICATION.MODIFIED]) # may not need to be "Sync", but for now we'll make it that way
224+
225+
else:
226+
227+
228+
editor.setSelectionMode(editor.getSelectionMode()) # force manual UPDATEUI to happen
229+

0 commit comments

Comments
 (0)