Instantly share code, notes, and snippets.
Created Apr 9, 2020
find_in_files_new_menu.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import customMenuItem | |
from objc_util import * | |
class findInSourcesMenu(customMenuItem.PYUIMenuItem): | |
__selector__ = 'findInSourcesMenu' | |
__title__ = 'Find' | |
def action(self, selected_text, selection, editorview): | |
import console | |
import os | |
import ui | |
search_term = selected_text | |
if search_term == '': # no text selected | |
# ask it | |
search_term = console.input_alert('text to search in sources', '', '') | |
if search_term == '': # no text entered | |
return # no action | |
tv = ui.TableView() | |
tv.search_term = search_term | |
sources = [] | |
path = os.path.expanduser('~/Documents') | |
se = search_term.lower() | |
# search all .py. Tests show that os.scandir is quicker than os.walk | |
def scantree(path): | |
"""Recursively yield DirEntry objects for given directory.""" | |
for entry in os.scandir(path): | |
if entry.is_dir(follow_symlinks=False): | |
scantree(entry.path) | |
else: | |
fpath = entry.path | |
if os.path.splitext(entry.path)[-1].lower() != ".py": | |
continue | |
with open(fpath, mode='rt', encoding='utf-8', errors='ignore') as fil: | |
content = fil.read().lower() | |
if se in content: | |
sources.append(fpath) | |
scantree(path) | |
def tableview_cell_for_row(tableview, section, row): | |
cell = ui.TableViewCell() | |
data = tableview.data_source.items[row] | |
tx = '/Pythonista3/Documents/' | |
i = data.find(tx) + len(tx) | |
cell.text_label.text = data[i:] | |
return cell | |
class MyTableViewDelegate (object): | |
def tableview_did_select(self,tableview, section, row): | |
from pygments import highlight | |
from pygments.lexers import PythonLexer | |
from pygments.formatters import HtmlFormatter | |
from pygments.styles import get_style_by_name | |
import re | |
import ui | |
from wkwebview import WKWebView | |
fpath = tableview.data_source.items[row] | |
search_term = tableview.search_term | |
with open(fpath, mode='rt', encoding='utf-8', errors='ignore') as fil: | |
code = fil.read() | |
# Syntax-highlight code | |
# from omz code at https://forum.omz-software.com/topic/1950/syntax-highlight-python-code-on-screen-while-running | |
html_formatter = HtmlFormatter(style='colorful') | |
l = PythonLexer() | |
l.add_filter('whitespace', tabs=' ', tabsize=2) | |
highlighted_code = highlight(code, l, html_formatter) | |
styles = html_formatter.get_style_defs() | |
# change html code to highlight searched term with yellow background | |
styles = styles + '\n' + '.search { background-color: #ffff00 } /* search term */' | |
highlighted_code = highlighted_code.replace(search_term, '</span><span class="search">' + search_term + '</span>') | |
# add class to searched term independantly of case | |
src_str = re.compile('('+search_term+')', re.IGNORECASE) | |
# @Olaf: use \1 to refer to matched text grouped by () in the regex | |
highlighted_code = src_str.sub(r'</span><span class="search">\1</span>', highlighted_code) | |
# meta tag UTF-8 is needed to display emojis if present in a script | |
html = '<html><head><meta charset="UTF-8"><style>%s</style></head><body> %s </body></html>' % (styles, highlighted_code) | |
wv = WKWebView() | |
tx = '/Pythonista3/Documents/' | |
i = fpath.find(tx) + len(tx) | |
wv.name = fpath[i:] | |
wv.frame = tableview.frame | |
wv.load_html(html) | |
wv.present() | |
wv.wait_modal() | |
tv.data_source = ui.ListDataSource(items=sources) | |
tv.delegate = MyTableViewDelegate() | |
tv.data_source.tableview_cell_for_row = tableview_cell_for_row | |
bs1 = ui.ButtonItem(title='search',tint_color='black') | |
bs2 = ui.ButtonItem(title=search_term,tint_color='green') | |
bs3 = ui.ButtonItem(title='in my scripts',tint_color='black') | |
tv.right_button_items = [bs3,bs2,bs1] | |
tv.present() | |
g = customMenuItem.MenuNotificationObserver([(findInSourcesMenu(),'Help')]) | |
g.register() | |
g.start() |
I'll not stop the scan background thread even if we select a file to watch because if we come back to watch another file, the list has still increased and should be normally ended. But I'll stop the thread if we close the TableView.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for your, as usual very appreciated, advices, I promise I'll do it, but please, let me some time. My wife asks me to work in the garden😢 😪