2021-01-17 21:30:27 +00:00
import os . path
import subprocess
import sys
2021-02-24 17:59:02 +00:00
import mmap , re
import warnings
2021-01-17 21:30:27 +00:00
import PySimpleGUI as sg
"""
2021-02-24 17:59:02 +00:00
PySimpleGUI Demo Program Browser
Originaly written for PySimpleGUI Demo Programs , but expanded to
be a general purpose tool . Enable Advanced Mode in settings for more fun
2021-01-17 21:30:27 +00:00
2021-02-24 17:59:02 +00:00
Use to filter and search your source code tree .
Then run or edit your files
Filter the list of :
2021-01-17 21:30:27 +00:00
* Search using filename
2021-02-24 17:59:02 +00:00
* Searching within the programs ' source code (like grep)
2021-01-17 21:30:27 +00:00
The basic file operations are
* Edit a file in your editor
* Run a file
* Filter file list
* Search in files
2021-02-24 17:59:02 +00:00
* Run a regular expression search on all files
* Display the matching line in a file
2021-01-17 21:30:27 +00:00
Additional operations
* Edit this file in editor
2021-02-24 17:59:02 +00:00
Keeps a " history " of the previously chosen folders to easy switching between projects
2021-01-17 21:30:27 +00:00
Copyright 2021 PySimpleGUI . org
"""
2021-02-24 17:59:02 +00:00
def running_linux ( ) :
return sys . platform . startswith ( ' linux ' )
2021-01-17 21:30:27 +00:00
2021-02-24 17:59:02 +00:00
def running_windows ( ) :
return sys . platform . startswith ( ' win ' )
2021-01-17 21:30:27 +00:00
2021-02-24 17:59:02 +00:00
def get_file_list_dict ( ) :
2021-01-17 21:30:27 +00:00
"""
2021-02-24 17:59:02 +00:00
Returns dictionary of files
Key is short filename
Value is the full filename and path
2021-01-17 21:30:27 +00:00
2021-02-24 17:59:02 +00:00
: return : Dictionary of demo files
: rtype : Dict [ str : str ]
2021-01-17 21:30:27 +00:00
"""
2021-01-28 19:37:14 +00:00
demo_path = get_demo_path ( )
2021-02-24 17:59:02 +00:00
demo_files_dict = { }
for dirname , dirnames , filenames in os . walk ( demo_path ) :
for filename in filenames :
if filename . endswith ( ' .py ' ) or filename . endswith ( ' .pyw ' ) :
fname_full = os . path . join ( dirname , filename )
if filename not in demo_files_dict . keys ( ) :
demo_files_dict [ filename ] = fname_full
else :
# Allow up to 100 dupicated names. After that, give up
for i in range ( 1 , 100 ) :
new_filename = f ' { filename } _ { i } '
if new_filename not in demo_files_dict :
demo_files_dict [ new_filename ] = fname_full
break
return demo_files_dict
def get_file_list ( ) :
"""
Returns list of filenames of files to display
No path is shown , only the short filename
2021-01-17 21:30:27 +00:00
2021-02-24 17:59:02 +00:00
: return : List of filenames
: rtype : List [ str ]
"""
return sorted ( list ( get_file_list_dict ( ) . keys ( ) ) )
2021-01-17 21:30:27 +00:00
2021-01-28 19:37:14 +00:00
def get_demo_path ( ) :
2021-02-24 17:59:02 +00:00
"""
Get the top - level folder path
: return : Path to list of files using the user settings for this file . Returns folder of this file if not found
: rtype : str
"""
2021-01-28 19:37:14 +00:00
demo_path = sg . user_settings_get_entry ( ' -demos folder- ' , os . path . dirname ( __file__ ) )
return demo_path
2021-02-24 17:59:02 +00:00
2021-01-28 19:37:14 +00:00
def get_editor ( ) :
2021-02-24 17:59:02 +00:00
"""
Get the path to the editor based on user settings or on PySimpleGUI ' s global settings
: return : Path to the editor
: rtype : str
"""
2021-01-28 19:37:14 +00:00
try : # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
2021-01-30 23:24:45 +00:00
global_editor = sg . pysimplegui_user_settings . get ( ' -editor program- ' )
2021-01-28 19:37:14 +00:00
except :
global_editor = ' '
return sg . user_settings_get_entry ( ' -editor program- ' , global_editor )
2021-02-24 17:59:02 +00:00
def get_explorer ( ) :
"""
Get the path to the file explorer program
: return : Path to the file explorer EXE
: rtype : str
"""
# TODO - need to add a default for Macs
default_explorer = ' explorer ' if running_windows ( ) else ' nemo '
return sg . user_settings_get_entry ( ' -explorer program- ' , default_explorer )
def advanced_mode ( ) :
"""
Returns True is advanced GUI should be shown
: return : True if user indicated wants the advanced GUI to be shown ( set in the settings window )
: rtype : bool
"""
return sg . user_settings_get_entry ( ' -advanced mode- ' , False )
2021-01-28 19:37:14 +00:00
def get_theme ( ) :
2021-02-21 13:51:41 +00:00
"""
Get the theme to use for the program
Value is in this program ' s user settings. If none set, then use PySimpleGUI ' s global default theme
: return : The theme
: rtype : str
"""
# First get the current global theme for PySimpleGUI to use if none has been set for this program
try :
global_theme = sg . theme_global ( )
except :
global_theme = sg . theme ( )
# Get theme from user settings for this program. Use global theme if no entry found
2021-01-28 19:37:14 +00:00
return sg . user_settings_get_entry ( ' -theme- ' , global_theme )
2021-02-21 13:51:41 +00:00
2021-02-24 17:59:02 +00:00
# We handle our code properly. But in case the user types in a flag, the flags are now in the middle of a regex. Ignore this warning.
warnings . filterwarnings ( " ignore " , category = DeprecationWarning )
def find_in_file ( string , demo_files_dict , regex = False , verbose = False , window = None ) :
2021-01-17 21:30:27 +00:00
"""
Search through the demo files for a string .
The case of the string and the file contents are ignored
: param string : String to search for
: return : List of files containing the string
: rtype : List [ str ]
"""
2021-02-24 17:59:02 +00:00
# So you face a prediciment here. You wish to read files, both small and large; however the bigger the file/bigger the list, the longer to read the file.
# This probably isn't what you want, right?
# Well, we can't use a direct command line to run grep and parse. But it is an option. The user may not have it.
# We could check if grep exists and if not use our method; but it isn't the best way.
# So using background knowldge, we know that grep is *very* fast.
#
# Why?
# Grep reads a *ton* of files into memory then searches through the memory to find the string or regex/pattern corresponding to the file.
# How can we load a file into memory on python as fast as grep whilst keeping it universal?
# memory mapping (mmap).
# We can't load a lot of files into memory as we may face issues with watchdog on other operating systems. So we load one file at a time and search though there.
# This will allow the fastest searching and loading of a file without sacrificing read times.
# 2.8 seconds on the highend for both small and large files in memory.
# We also don't have to iterate over lines this way.
2021-01-17 21:30:27 +00:00
file_list = [ ]
2021-02-24 17:59:02 +00:00
new_demo_files_dict = { }
num_files = 0
for file in demo_files_dict :
2021-01-17 21:30:27 +00:00
try :
2021-02-24 17:59:02 +00:00
full_filename = demo_files_dict [ file ]
with open ( full_filename , ' rb ' , 0 ) as f , mmap . mmap ( f . fileno ( ) , 0 , access = mmap . ACCESS_READ ) as s :
if ( regex ) :
window [ ' -FIND NUMBER- ' ] . update ( f ' { num_files } files ' )
window . refresh ( )
matches = re . finditer ( bytes ( " ^.*( " + string + " ).*$ " , ' utf-8 ' ) , s , re . MULTILINE )
if matches :
for match in matches :
if match is not None :
if file not in file_list :
file_list . append ( file )
num_files + = 1
if verbose :
sg . cprint ( f " { file } : " , c = ' white on green ' )
sg . cprint ( f " { match . group ( 0 ) . decode ( ' utf-8 ' ) } \n " )
else :
window [ ' -FIND NUMBER- ' ] . update ( f ' { num_files } files ' )
window . refresh ( )
matches = re . search ( br ' (?i)^ ' + bytes ( " .*( " + re . escape ( string . lower ( ) ) + " ).*$ " , ' utf-8 ' ) , s , re . M )
if matches :
2021-01-17 21:30:27 +00:00
file_list . append ( file )
2021-02-24 17:59:02 +00:00
num_files + = 1
if verbose :
sg . cprint ( f " { file } : " , c = ' white on green ' )
sg . cprint ( f " { matches . group ( 0 ) . decode ( ' utf-8 ' ) } \n " )
# DICT
if file not in new_demo_files_dict . keys ( ) :
new_demo_files_dict [ file ] = full_filename
else :
new_demo_files_dict [ f ' { file } _1 ' ] = full_filename
del matches
except ValueError :
2021-01-17 21:30:27 +00:00
pass
2021-02-24 17:59:02 +00:00
except Exception as e :
print ( f ' { file } ' , e , file = sys . stderr )
if not regex :
find_in_file . old_file_list = new_demo_files_dict
file_list = list ( set ( file_list ) )
return file_list
2021-01-17 21:30:27 +00:00
def settings_window ( ) :
"""
Show the settings window .
This is where the folder paths and program paths are set .
Returns True if settings were changed
: return : True if settings were changed
: rtype : ( bool )
"""
2021-01-28 19:37:14 +00:00
editor_program = get_editor ( )
2021-02-24 17:59:02 +00:00
explorer_program = get_explorer ( )
2021-01-28 19:37:14 +00:00
2021-02-24 17:59:02 +00:00
layout = [ [ sg . T ( ' Program Settings ' , font = ' DEFAULT 18 ' ) ] ,
[ sg . T ( ' Path to Tree ' , size = ( 20 , 1 ) ) ,
sg . Combo ( sorted ( sg . user_settings_get_entry ( ' -folder names- ' , [ ] ) ) , default_value = sg . user_settings_get_entry ( ' -demos folder- ' , get_demo_path ( ) ) , size = ( 50 , 1 ) , key = ' -FOLDERNAME- ' ) ,
sg . FolderBrowse ( ' Folder Browse ' , target = ' -FOLDERNAME- ' ) , sg . B ( ' Clear History ' ) ] ,
2021-01-17 21:30:27 +00:00
[ sg . T ( r " For PyCharm, Add this to your PyCharm main program ' s folder \ bin \ pycharm.bat " ) ] ,
2021-02-24 17:59:02 +00:00
[ sg . T ( ' Editor Program ' , size = ( 20 , 1 ) ) , sg . In ( sg . user_settings_get_entry ( ' -editor program- ' , editor_program ) , k = ' -EDITOR PROGRAM- ' ) , sg . FileBrowse ( ) ] ,
[ sg . T ( ' File Explorer Program ' , size = ( 20 , 1 ) ) , sg . In ( explorer_program , k = ' -EXPLORER PROGRAM- ' ) , sg . FileBrowse ( ) ] ,
[ sg . Combo ( [ ' ' ] + sg . theme_list ( ) , sg . user_settings_get_entry ( ' -theme- ' , None ) , readonly = True , k = ' -THEME- ' ) ] ,
[ sg . CB ( ' Use Advanced Interface ' , default = advanced_mode ( ) , k = ' -ADVANCED MODE- ' ) ] ,
2021-01-18 20:08:34 +00:00
[ sg . B ( ' Ok ' , bind_return_key = True ) , sg . B ( ' Cancel ' ) ] ,
2021-01-17 21:30:27 +00:00
]
window = sg . Window ( ' Settings ' , layout )
2021-02-24 17:59:02 +00:00
settings_changed = False
while True :
event , values = window . read ( )
if event in ( ' Cancel ' , sg . WIN_CLOSED ) :
break
if event == ' Ok ' :
sg . user_settings_set_entry ( ' -demos folder- ' , values [ ' -FOLDERNAME- ' ] )
new_editor = editor_program if not values [ ' -EDITOR PROGRAM- ' ] else values [ ' -EDITOR PROGRAM- ' ]
sg . user_settings_set_entry ( ' -editor program- ' , new_editor )
new_theme = get_theme ( ) if values [ ' -THEME- ' ] == ' ' else values [ ' -THEME- ' ]
sg . user_settings_set_entry ( ' -theme- ' , new_theme )
sg . user_settings_set_entry ( ' -folder names- ' , list ( set ( sg . user_settings_get_entry ( ' -folder names- ' , [ ] ) + [ values [ ' -FOLDERNAME- ' ] , ] ) ) )
sg . user_settings_set_entry ( ' -explorer program- ' , values [ ' -EXPLORER PROGRAM- ' ] )
sg . user_settings_set_entry ( ' -advanced mode- ' , values [ ' -ADVANCED MODE- ' ] )
settings_changed = True
break
elif event == ' Clear History ' :
sg . user_settings_set_entry ( ' -folder names- ' , [ ] )
sg . user_settings_set_entry ( ' -last filename- ' , ' ' )
window [ ' -FOLDERNAME- ' ] . update ( values = [ ] , value = ' ' )
window . close ( )
return settings_changed
ML_KEY = ' -ML- ' # Multline's key
2021-01-17 21:30:27 +00:00
# --------------------------------- Create the window ---------------------------------
def make_window ( ) :
"""
Creates the main window
: return : The main window object
: rtype : ( Window )
"""
2021-01-28 19:37:14 +00:00
theme = get_theme ( )
2021-01-17 21:30:27 +00:00
if not theme :
theme = sg . OFFICIAL_PYSIMPLEGUI_THEME
sg . theme ( theme )
# First the window layout...2 columns
find_tooltip = " Find in file \n Enter a string in box to search for string inside of the files. \n File list will update with list of files string found inside. "
filter_tooltip = " Filter files \n Enter a string in box to narrow down the list of files. \n File list will update with list of files with string in filename. "
2021-02-24 17:59:02 +00:00
find_re_tooltip = " Find in file using Regular Expression \n Enter a string in box to search for string inside of the files. \n Search is performed after clicking the FindRE button. "
2021-01-17 21:30:27 +00:00
2021-02-24 17:59:02 +00:00
left_col = sg . Col ( [
[ sg . Listbox ( values = get_file_list ( ) , select_mode = sg . SELECT_MODE_EXTENDED , size = ( 50 , 20 ) , key = ' -DEMO LIST- ' ) ] ,
2021-01-24 18:08:24 +00:00
[ sg . Text ( ' Filter: ' , tooltip = filter_tooltip ) , sg . Input ( size = ( 25 , 1 ) , enable_events = True , key = ' -FILTER- ' , tooltip = filter_tooltip ) ,
2021-02-24 17:59:02 +00:00
sg . T ( size = ( 15 , 1 ) , k = ' -FILTER NUMBER- ' ) ] ,
[ sg . Button ( ' Run ' ) , sg . B ( ' Edit ' ) , sg . B ( ' Clear ' ) , sg . B ( ' Open Folder ' ) ] ,
2021-01-24 18:08:24 +00:00
[ sg . Text ( ' Find: ' , tooltip = find_tooltip ) , sg . Input ( size = ( 25 , 1 ) , enable_events = True , key = ' -FIND- ' , tooltip = find_tooltip ) ,
2021-02-24 17:59:02 +00:00
sg . T ( size = ( 15 , 1 ) , k = ' -FIND NUMBER- ' ) ] ,
] , element_justification = ' l ' )
lef_col_find_re = sg . pin ( sg . Col ( [
[ sg . Text ( ' Find: ' , tooltip = find_re_tooltip ) , sg . Input ( size = ( 25 , 1 ) , key = ' -FIND RE- ' , tooltip = find_re_tooltip ) , sg . B ( ' Find RE ' ) ] ] , k = ' -RE COL- ' ) )
2021-01-17 21:30:27 +00:00
right_col = [
[ sg . Multiline ( size = ( 70 , 21 ) , write_only = True , key = ML_KEY , reroute_stdout = True , echo_stdout_stderr = True ) ] ,
[ sg . Button ( ' Edit Me (this program) ' ) , sg . B ( ' Settings ' ) , sg . Button ( ' Exit ' ) ] ,
[ sg . T ( ' PySimpleGUI ver ' + sg . version . split ( ' ' ) [ 0 ] + ' tkinter ver ' + sg . tclversion_detailed , font = ' Default 8 ' , pad = ( 0 , 0 ) ) ] ,
]
2021-02-24 17:59:02 +00:00
options_at_bottom = sg . pin ( sg . Column ( [ [ sg . CB ( ' Verbose ' , enable_events = True , k = ' -VERBOSE- ' ) ,
sg . CB ( ' Show only first match in file ' , default = True , enable_events = True , k = ' -FIRST MATCH ONLY- ' ) ,
sg . CB ( ' Find ignore case ' , default = True , enable_events = True , k = ' -IGNORE CASE- ' ) ,
sg . T ( ' <---- NOTE: Only the " Verbose " setting is implemented at this time ' ) ] ] , pad = ( 0 , 0 ) , k = ' -OPTIONS BOTTOM- ' ) )
choose_folder_at_top = sg . pin ( sg . Column ( [ [ sg . T ( ' Click settings to set top of your tree or choose a previously chosen folder ' ) ,
sg . Combo ( sorted ( sg . user_settings_get_entry ( ' -folder names- ' , [ ] ) ) , default_value = sg . user_settings_get_entry ( ' -demos folder- ' , ' ' ) , size = ( 50 , 1 ) , key = ' -FOLDERNAME- ' , enable_events = True , readonly = True ) ] ] , pad = ( 0 , 0 ) , k = ' -FOLDER CHOOSE- ' ) )
2021-01-17 21:30:27 +00:00
# ----- Full layout -----
2021-02-24 17:59:02 +00:00
layout = [ [ sg . Text ( ' PySimpleGUI Demo Program & Project Browser ' , font = ' Any 20 ' ) ] ,
[ choose_folder_at_top ] ,
sg . vtop ( [ sg . Column ( [ [ left_col ] , [ lef_col_find_re ] ] , element_justification = ' l ' ) , sg . Col ( right_col , element_justification = ' c ' ) ] ) ,
[ options_at_bottom ]
]
2021-01-17 21:30:27 +00:00
# --------------------------------- Create Window ---------------------------------
2021-02-24 17:59:02 +00:00
window = sg . Window ( ' PSG Demo & Project Browser ' , layout , finalize = True , icon = icon )
if not advanced_mode ( ) :
window [ ' -FOLDER CHOOSE- ' ] . update ( visible = False )
window [ ' -RE COL- ' ] . update ( visible = False )
window [ ' -OPTIONS BOTTOM- ' ] . update ( visible = False )
2021-01-17 21:30:27 +00:00
sg . cprint_set_output_destination ( window , ML_KEY )
return window
2021-02-24 17:59:02 +00:00
2021-01-17 21:30:27 +00:00
# --------------------------------- Main Program Layout ---------------------------------
def main ( ) :
"""
The main program that contains the event loop .
It will call the make_window function to create the window .
"""
2021-02-24 17:59:02 +00:00
find_in_file . old_file_list = None
old_typed_value = None
2021-01-28 19:37:14 +00:00
editor_program = get_editor ( )
2021-02-24 17:59:02 +00:00
explorer_program = get_explorer ( )
file_list_dict = get_file_list_dict ( )
file_list = get_file_list ( )
2021-01-17 21:30:27 +00:00
window = make_window ( )
2021-02-24 17:59:02 +00:00
window [ ' -FILTER NUMBER- ' ] . update ( f ' { len ( file_list ) } files ' )
2021-01-17 21:30:27 +00:00
while True :
event , values = window . read ( )
2021-02-24 17:59:02 +00:00
if event in ( sg . WINDOW_CLOSED , ' Exit ' ) :
2021-01-17 21:30:27 +00:00
break
if event == ' Edit ' :
for file in values [ ' -DEMO LIST- ' ] :
2021-01-28 19:37:14 +00:00
sg . cprint ( f ' Editing using { editor_program } ' , text_color = ' white ' , background_color = ' red ' , end = ' ' )
2021-01-17 21:30:27 +00:00
sg . cprint ( ' ' )
2021-02-24 17:59:02 +00:00
sg . cprint ( f ' { file_list_dict [ file ] } ' , text_color = ' white ' , background_color = ' purple ' )
execute_command_subprocess ( f ' { editor_program } ' , f ' " { file_list_dict [ file ] } " ' )
2021-01-17 21:30:27 +00:00
elif event == ' Run ' :
2021-01-28 19:37:14 +00:00
sg . cprint ( ' Running.... ' , c = ' white on green ' , end = ' ' )
2021-01-17 21:30:27 +00:00
sg . cprint ( ' ' )
for file in values [ ' -DEMO LIST- ' ] :
2021-02-24 17:59:02 +00:00
file_to_run = str ( file_list_dict [ file ] )
sg . cprint ( file_to_run , text_color = ' white ' , background_color = ' purple ' )
execute_command_subprocess ( ' python ' if running_windows ( ) else ' python3 ' , f ' { file_to_run } ' )
# run_py(file_to_run)
2021-01-17 21:30:27 +00:00
elif event . startswith ( ' Edit Me ' ) :
2021-02-24 17:59:02 +00:00
sg . cprint ( f ' opening using { editor_program } : ' )
sg . cprint ( f ' { __file__ } ' , text_color = ' white ' , background_color = ' red ' , end = ' ' )
2021-01-30 23:24:45 +00:00
execute_command_subprocess ( f ' { editor_program } ' , f ' " { __file__ } " ' )
2021-01-17 21:30:27 +00:00
elif event == ' -FILTER- ' :
2021-02-24 17:59:02 +00:00
new_list = [ i for i in file_list if values [ ' -FILTER- ' ] . lower ( ) in i . lower ( ) ]
2021-01-17 21:30:27 +00:00
window [ ' -DEMO LIST- ' ] . update ( new_list )
2021-01-24 18:08:24 +00:00
window [ ' -FILTER NUMBER- ' ] . update ( f ' { len ( new_list ) } files ' )
window [ ' -FIND NUMBER- ' ] . update ( ' ' )
2021-01-27 16:57:36 +00:00
window [ ' -FIND- ' ] . update ( ' ' )
2021-02-24 17:59:02 +00:00
window [ ' -FIND RE- ' ] . update ( ' ' )
2021-01-17 21:30:27 +00:00
elif event == ' -FIND- ' :
2021-02-24 17:59:02 +00:00
current_typed_value = str ( values [ ' -FIND- ' ] )
if values [ ' -VERBOSE- ' ] :
window [ ML_KEY ] . update ( ' ' )
if find_in_file . old_file_list is None or old_typed_value is None :
# New search.
old_typed_value = current_typed_value
file_list = find_in_file ( values [ ' -FIND- ' ] , get_file_list_dict ( ) , verbose = values [ ' -VERBOSE- ' ] , window = window )
elif current_typed_value . startswith ( old_typed_value ) :
old_typed_value = current_typed_value
file_list = find_in_file ( values [ ' -FIND- ' ] , find_in_file . old_file_list , verbose = values [ ' -VERBOSE- ' ] , window = window )
else :
old_typed_value = current_typed_value
file_list = find_in_file ( values [ ' -FIND- ' ] , get_file_list_dict ( ) , verbose = values [ ' -VERBOSE- ' ] , window = window )
2021-01-17 21:30:27 +00:00
window [ ' -DEMO LIST- ' ] . update ( sorted ( file_list ) )
2021-01-24 18:08:24 +00:00
window [ ' -FIND NUMBER- ' ] . update ( f ' { len ( file_list ) } files ' )
window [ ' -FILTER NUMBER- ' ] . update ( ' ' )
2021-02-24 17:59:02 +00:00
window [ ' -FIND RE- ' ] . update ( ' ' )
window [ ' -FILTER- ' ] . update ( ' ' )
elif event == ' Find RE ' :
window [ ' -ML- ' ] . update ( ' ' )
file_list = find_in_file ( values [ ' -FIND RE- ' ] , get_file_list_dict ( ) , regex = True , verbose = values [ ' -VERBOSE- ' ] , window = window )
window [ ' -DEMO LIST- ' ] . update ( sorted ( file_list ) )
window [ ' -FIND NUMBER- ' ] . update ( f ' { len ( file_list ) } files ' )
window [ ' -FILTER NUMBER- ' ] . update ( ' ' )
window [ ' -FIND- ' ] . update ( ' ' )
2021-01-27 16:57:36 +00:00
window [ ' -FILTER- ' ] . update ( ' ' )
2021-01-17 21:30:27 +00:00
elif event == ' Settings ' :
if settings_window ( ) is True :
window . close ( )
window = make_window ( )
2021-01-28 19:37:14 +00:00
editor_program = get_editor ( )
2021-02-24 17:59:02 +00:00
explorer_program = get_explorer ( )
file_list_dict = get_file_list_dict ( )
file_list = get_file_list ( )
window [ ' -FILTER NUMBER- ' ] . update ( f ' { len ( file_list ) } files ' )
2021-01-17 21:30:27 +00:00
elif event == ' Clear ' :
2021-02-24 17:59:02 +00:00
file_list = get_file_list ( )
2021-01-17 21:30:27 +00:00
window [ ' -FILTER- ' ] . update ( ' ' )
2021-02-24 17:59:02 +00:00
window [ ' -FILTER NUMBER- ' ] . update ( f ' { len ( file_list ) } files ' )
2021-01-17 21:30:27 +00:00
window [ ' -FIND- ' ] . update ( ' ' )
2021-02-24 17:59:02 +00:00
window [ ' -DEMO LIST- ' ] . update ( file_list )
2021-01-24 18:08:24 +00:00
window [ ' -FIND NUMBER- ' ] . update ( ' ' )
2021-02-24 17:59:02 +00:00
window [ ' -FIND RE- ' ] . update ( ' ' )
window [ ' -ML- ' ] . update ( ' ' )
elif event == ' -FOLDERNAME- ' :
sg . user_settings_set_entry ( ' -demos folder- ' , values [ ' -FOLDERNAME- ' ] )
file_list_dict = get_file_list_dict ( )
file_list = get_file_list ( )
window [ ' -DEMO LIST- ' ] . update ( values = file_list )
window [ ' -FILTER NUMBER- ' ] . update ( f ' { len ( file_list ) } files ' )
elif event == ' -VERBOSE- ' :
window [ ML_KEY ] . update ( ' ' )
if values [ ' -FIND- ' ] :
current_typed_value = str ( values [ ' -FIND- ' ] )
if find_in_file . old_file_list is None or old_typed_value is None :
# New search.
old_typed_value = current_typed_value
file_list = find_in_file ( values [ ' -FIND- ' ] , get_file_list_dict ( ) , verbose = values [ ' -VERBOSE- ' ] , window = window )
elif current_typed_value . startswith ( old_typed_value ) :
old_typed_value = current_typed_value
file_list = find_in_file ( values [ ' -FIND- ' ] , find_in_file . old_file_list , verbose = values [ ' -VERBOSE- ' ] , window = window )
else :
old_typed_value = current_typed_value
file_list = find_in_file ( values [ ' -FIND- ' ] , get_file_list_dict ( ) , verbose = values [ ' -VERBOSE- ' ] , window = window )
elif values [ ' -FIND RE- ' ] :
window [ ' -ML- ' ] . update ( ' ' )
file_list = find_in_file ( values [ ' -FIND RE- ' ] , get_file_list_dict ( ) , regex = True , verbose = values [ ' -VERBOSE- ' ] , window = window )
window [ ' -DEMO LIST- ' ] . update ( sorted ( file_list ) )
window [ ' -FIND NUMBER- ' ] . update ( f ' { len ( file_list ) } files ' )
window [ ' -FILTER NUMBER- ' ] . update ( ' ' )
window [ ' -FIND- ' ] . update ( ' ' )
window [ ' -FILTER- ' ] . update ( ' ' )
elif event == ' Open Folder ' :
if explorer_program :
sg . cprint ( ' Opening Folder.... ' , c = ' white on green ' , end = ' ' )
sg . cprint ( ' ' )
for file in values [ ' -DEMO LIST- ' ] :
file_selected = str ( file_list_dict [ file ] )
file_path = os . path . dirname ( file_selected )
if running_windows ( ) :
file_path = file_path . replace ( ' / ' , ' \\ ' )
sg . cprint ( file_path , text_color = ' white ' , background_color = ' purple ' )
execute_command_subprocess ( explorer_program , file_path )
2021-01-17 21:30:27 +00:00
window . close ( )
def execute_command_subprocess ( command , * args , wait = False ) :
2021-02-24 17:59:02 +00:00
2021-01-17 21:30:27 +00:00
if sys . platform == ' linux ' :
arg_string = ' '
for arg in args :
arg_string + = ' ' + str ( arg )
2021-02-24 17:59:02 +00:00
sp = subprocess . Popen ( str ( command ) + arg_string , shell = True , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
2021-01-17 21:30:27 +00:00
else :
expanded_args = ' ' . join ( args )
2021-02-21 15:01:10 +00:00
sp = subprocess . Popen ( [ command , args ] , shell = True , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
2021-01-17 21:30:27 +00:00
if wait :
out , err = sp . communicate ( )
if out :
print ( out . decode ( " utf-8 " ) )
if err :
print ( err . decode ( " utf-8 " ) )
if __name__ == ' __main__ ' :
2021-02-24 17:59:02 +00:00
# https://www.vecteezy.com/free-vector/idea-bulb is where I got the icon
2021-01-24 18:24:45 +00:00
2021-02-24 17:59:02 +00:00
icon = b ' iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAAK/2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4NCjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDA3IDEuMTM2ODgxLCAyMDEwLzA2LzEwLTE4OjExOjM1ICAgICAgICAiPg0KICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPg0KICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0iRUM4REZFNUEyMEM0QjcwMzFBMjNBRDA4NENCNzZCODAiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0iRUM4REZFNUEyMEM0QjcwMzFBMjNBRDA4NENCNzZCODAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUVBNkIyNzA3NjYyRTkxMThDQzNFODdFN0ZEQTgwNTEiIGRjOmZvcm1hdD0iaW1hZ2UvanBlZyIgeG1wOlJhdGluZz0iNSIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wNC0xOVQxMjoxMTozOSswNDozMCI+DQogICAgICA8eG1wTU06SGlzdG9yeT4NCiAgICAgICAgPHJkZjpTZXE+DQogICAgICAgICAgPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOkYwNjRBQzcwNzY2MkU5MTFBNkU1QzYwODhFRTUxMzM5IiBzdEV2dDp3aGVuPSIyMDE5LTA0LTE5VDEyOjExOjM5KzA0OjMwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ2FtZXJhIFJhdyA3LjAiIHN0RXZ0OmNoYW5nZWQ9Ii9tZXRhZGF0YSIgLz4NCiAgICAgICAgICA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6OUVBNkIyNzA3NjYyRTkxMThDQzNFODdFN0ZEQTgwNTEiIHN0RXZ0OndoZW49IjIwMTktMDQtMTlUMTI6MTE6MzkrMDQ6MzAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDYW1lcmEgUmF3IDcuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii9tZXRhZGF0YSIgLz4NCiAgICAgICAgPC9yZGY6U2VxPg0KICAgICAgPC94bXBNTTpIaXN0b3J5Pg0KICAgICAgPGRjOnRpdGxlPg0KICAgICAgICA8cmRmOkFsdD4NCiAgICAgICAgICA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPkJ1bGIgSWNvbiBEZXNpZ248L3JkZjpsaT4NCiAgICAgICAgPC9yZGY6QWx0Pg0KICAgICAgPC9kYzp0aXRsZT4NCiAgICAgIDxkYzpjcmVhdG9yPg0KICAgICAgICA8cmRmOlNlcT4NCiAgICAgICAgICA8cmRmOmxpPklZSUtPTjwvcmRmOmxpPg0KICAgICAgICA8L3JkZjpTZXE+DQogICAgICA8L2RjOmNyZWF0b3I+DQogICAgICA8ZGM6ZGVzY3JpcHRpb24+DQogICAgICAgIDxyZGY6QWx0Pg0KICAgICAgICAgIDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+QnVsYiBJY29uIERlc2lnbg0KPC9yZGY6bGk+DQogICAgICAgIDwvcmRmOkFsdD4NCiAgICAgIDwvZGM6ZGVzY3JpcHRpb24+DQogICAgICA8ZGM6c3ViamVjdD4NCiAgICAgICAgPHJkZjpCYWc+DQogICAgICAgICAgPHJkZjpsaT5idWxiPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5lbmVyZ3k8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlkZWE8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpZ2h0PC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5saWdodGJ1bGI8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmJ1bGIgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZW5lcmd5IGljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlkZWEgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bGlnaHQgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bGlnaHRidWxiIGljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlsbHVzdHJhdGlvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZGVzaWduPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5zaWduPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5zeW1ib2w8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmdyYXBoaWM8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpbmU8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpbmVhcjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+b3V0bGluZTwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZmxhdDwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+Z2x5cGg8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmdyYWRpZW50PC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5jaXJjbGU8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPnNoYWRvdzwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bG93IHBvbHk8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPnBvbHlnb25hbDwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+c3F1YXJlPC9yZGY6bGk+DQogICAgICAgIDwvcmRmOkJhZz4NCiAgICAgIDwvZGM6c3ViamVjdD4NCiAgICA8L3JkZjpEZXNjcmlwdGlvbj4NCiAgPC9yZGY6UkRGPg0KPC94OnhtcG1ldGE+DQo8P3hwYWNrZXQgZW5kPSJyIj8+ncdlNwAABG5JREFUWMPtV2tMk1cYfr6vINBRKpVLpVIuGZfOjiARochYO/EyMWHDjOIYYSyQ6MaignEkEgJLyNxMRthmJBkalKmgUacsjMiCBRFWqKsBFJEwtkILLYxBuQi0/c5+sE5mJmvBxR/zJO+fc877vE/ey5NzKEIInuWi8YzXcwIrInCtuirlWnVVykowHGy9qFYqo+bn5pyj4uIarXtBope6H7+nbGp6dZWT0+yGqCjlUy
2021-02-21 13:51:41 +00:00
main ( )