From 2b6ce7590ebe0b13d86a4fb6e27759cb05ad2144 Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Sat, 30 Jan 2021 18:23:56 -0500 Subject: [PATCH 1/3] set encoding="utf8" so that can have special chars in files. ..otherwhise reads fail --- DemoPrograms/Demo_GitHub_File_Copier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DemoPrograms/Demo_GitHub_File_Copier.py b/DemoPrograms/Demo_GitHub_File_Copier.py index 80550c38..dc09f4ec 100644 --- a/DemoPrograms/Demo_GitHub_File_Copier.py +++ b/DemoPrograms/Demo_GitHub_File_Copier.py @@ -72,7 +72,7 @@ def find_in_file(string): for file in demo_files: filename = os.path.join(demo_path, file) try: - with open(filename, 'r') as f: + with open(filename, 'r', encoding="utf8") as f: for line in f.readlines(): if string in line.lower(): file_list.append(file) From 9b656d35e786688892ba3b21d1329a67ea7b9c23 Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Sat, 30 Jan 2021 18:24:45 -0500 Subject: [PATCH 2/3] set encoding="utf8" so that can have special chars in files. ..otherwhise reads fail, Added quotes around strings to run, --- DemoPrograms/Demo_Demo_Programs_Browser.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/DemoPrograms/Demo_Demo_Programs_Browser.py b/DemoPrograms/Demo_Demo_Programs_Browser.py index 5da88dad..f3a729cf 100644 --- a/DemoPrograms/Demo_Demo_Programs_Browser.py +++ b/DemoPrograms/Demo_Demo_Programs_Browser.py @@ -58,10 +58,7 @@ def get_demo_path(): def get_editor(): try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path - if sg.pysimplegui_user_settings: - global_editor = sg.pysimplegui_user_settings.get('-editor program-') - else: - global_editor = '' + global_editor = sg.pysimplegui_user_settings.get('-editor program-') except: global_editor = '' @@ -90,7 +87,7 @@ def find_in_file(string): for file in demo_files: filename = os.path.join(demo_path, file) try: - with open(filename, 'r') as f: + with open(filename, 'r', encoding="utf8") as f: for line in f.readlines(): if string in line.lower(): file_list.append(file) @@ -125,7 +122,7 @@ def settings_window(): event, values = window.read(close=True) if event == 'Ok': sg.user_settings_set_entry('-demos folder-', values['-DEMOS-']) - new_editor = global_editor if not values['-EDITOR PROGRAM-'] else values['-EDITOR PROGRAM-'] + new_editor = editor_program if not values['-EDITOR PROGRAM-'] else values['-EDITOR PROGRAM-'] sg.user_settings_set_entry('-editor program-', new_editor) new_theme = sg.theme_global() if values['-THEME-'] == '' else values['-THEME-'] sg.user_settings_set_entry('-theme-', new_theme) @@ -200,8 +197,8 @@ def main(): for file in values['-DEMO LIST-']: sg.cprint(f'Editing using {editor_program}', text_color='white', background_color='red', end='') sg.cprint('') - sg.cprint(f'{os.path.join(demo_path, file)}', text_color='white', background_color='purple') - execute_command_subprocess(f'{editor_program}', os.path.join(demo_path, file)) + sg.cprint(f'{os.path.join(demo_path, file)}', t='white', b='purple') + execute_command_subprocess(f'{editor_program}', f'"{os.path.join(demo_path, file)}"') elif event == 'Run': sg.cprint('Running....', c='white on green', end='') sg.cprint('') @@ -209,8 +206,8 @@ def main(): sg.cprint(os.path.join(demo_path, file),text_color='white', background_color='purple') run_py(os.path.join(demo_path, file)) elif event.startswith('Edit Me'): - sg.cprint(f'opening using {editor_program}\nThis file - {__file__}', text_color='white', background_color='green', end='') - execute_command_subprocess(f'{editor_program}', __file__) + sg.cprint(f'opening using {editor_program}\nThis file - {__file__}', t='white', b='green', end='') + execute_command_subprocess(f'{editor_program}', f'"{__file__}"') elif event == '-FILTER-': new_list = [i for i in demo_files if values['-FILTER-'].lower() in i.lower()] window['-DEMO LIST-'].update(new_list) From f9b3c9aa49276ccb0c639cd7edc1783f4fd8992b Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Sat, 30 Jan 2021 18:28:09 -0500 Subject: [PATCH 3/3] NEW demo - Project File Searcher Launcher - point to the top of a project tree and it'll find all py files, can search the names and the contents, edit and run. --- .../Demo_Project_File_Searcher_Launcher.py | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 DemoPrograms/Demo_Project_File_Searcher_Launcher.py diff --git a/DemoPrograms/Demo_Project_File_Searcher_Launcher.py b/DemoPrograms/Demo_Project_File_Searcher_Launcher.py new file mode 100644 index 00000000..39cdee67 --- /dev/null +++ b/DemoPrograms/Demo_Project_File_Searcher_Launcher.py @@ -0,0 +1,251 @@ +import os.path +import subprocess +import sys +from idlelib import tooltip + +import PySimpleGUI as sg + +""" + PySimpleGUI Code Finder & Launcher + + Use to filter and search your source code tree. + Then run or edit your files + + Filter the list of : + * Search using filename + * Searching within the demo program's source code (like grep) + + The basic file operations are + * Edit a file in your editor + * Run a file + * Filter file list + * Search in files + + Additional operations + * Edit this file in editor + + Copyright 2021 PySimpleGUI.org +""" + + + +def get_demo_git_files(): + """ + Get the files in the demo and the GitHub folders + Returns files as 2 lists + + :return: two lists of files + :rtype: Tuple[List[str], List[str]] + """ + + demo_path = get_demo_path() + demo_files_dict = {} + for dirname, dirnames, filenames in os.walk(demo_path): + for filename in filenames: + if filename.endswith('.py'): + fname_full = os.path.join(dirname, filename) + if filename not in demo_files_dict.keys(): + demo_files_dict[filename] = fname_full + else: + # print(f'duplicate filename found {filename} path {dirname}') + demo_files_dict[f'{filename}_1'] = fname_full + + return demo_files_dict + + +def get_demo_path(): + demo_path = sg.user_settings_get_entry('-demos folder-', os.path.dirname(__file__)) + + return demo_path + + +def get_editor(): + try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path + global_editor = sg.pysimplegui_user_settings.get('-editor program-') + except: + global_editor = '' + + return sg.user_settings_get_entry('-editor program-', global_editor) + + +def get_theme(): + try: + global_theme = sg.theme_global() + except: + global_theme = sg.theme() + + return sg.user_settings_get_entry('-theme-', global_theme) + +def find_in_file(string): + """ + 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] + """ + + demo_files_dict = get_demo_git_files() + string = string.lower() + file_list = [] + for file in demo_files_dict: + full_filename = demo_files_dict[file] + try: + with open(full_filename, 'r', encoding="utf8") as f: + for line in f.readlines(): + if string in line.lower(): + file_list.append(file) + # print(f'{os.path.basename(file)} -- {line}') + except Exception as e: + pass + print(f'{file}',e) + return list(set(file_list)) + + +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) + """ + + editor_program = get_editor() + + layout = [[sg.T('Program Settings', font='DEFAIULT 18')], + [sg.T('Path to Demos', size=(20,1)), sg.In(sg.user_settings_get_entry('-demos folder-', '.'), k='-DEMOS-'), sg.FolderBrowse()], + [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(r"For PyCharm, Add this to your PyCharm main program's folder \bin\pycharm.bat")], + [sg.Combo(['']+sg.theme_list(), sg.user_settings_get_entry('-theme-', None), k='-THEME-')], + [sg.B('Ok', bind_return_key=True), sg.B('Cancel')], + ] + + window = sg.Window('Settings', layout) + event, values = window.read(close=True) + if event == 'Ok': + sg.user_settings_set_entry('-demos folder-', values['-DEMOS-']) + new_editor = editor_program if not values['-EDITOR PROGRAM-'] else values['-EDITOR PROGRAM-'] + sg.user_settings_set_entry('-editor program-', new_editor) + new_theme = sg.theme_global() if values['-THEME-'] == '' else values['-THEME-'] + sg.user_settings_set_entry('-theme-', new_theme) + return True + + return False + +# --------------------------------- Create the window --------------------------------- +def make_window(): + """ + Creates the main window + :return: The main window object + :rtype: (Window) + """ + + theme = get_theme() + editor = get_editor() + demo_files_dict = get_demo_git_files() + if not theme: + theme = sg.OFFICIAL_PYSIMPLEGUI_THEME + sg.theme(theme) + # First the window layout...2 columns + + find_tooltip = "Find in file\nEnter a string in box to search for string inside of the files.\nFile list will update with list of files string found inside." + filter_tooltip = "Filter files\nEnter a string in box to narrow down the list of files.\nFile list will update with list of files with string in filename." + + ML_KEY = '-ML-' # Multline's key + + left_col = [ + [sg.Listbox(values=list(demo_files_dict.keys()), select_mode=sg.SELECT_MODE_EXTENDED, size=(40, 20), key='-DEMO LIST-')], + [sg.Text('Filter:', tooltip=filter_tooltip), sg.Input(size=(25, 1), enable_events=True, key='-FILTER-', tooltip=filter_tooltip), + sg.T(size=(20,1), k='-FILTER NUMBER-')], + [sg.Button('Run'), sg.B('Edit'), sg.B('Clear')], + [sg.Text('Find:', tooltip=find_tooltip), sg.Input(size=(25, 1), enable_events=True, key='-FIND-', tooltip=find_tooltip), + sg.T(size=(20,1), k='-FIND NUMBER-')]] + + 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))], + ] + + # ----- Full layout ----- + + layout = [[sg.Text('PySimpleGUI Project File Searcher & Launcher', font='Any 20')], + [sg.T('Click settings to set top of your tree')], + sg.vtop([sg.Column(left_col, element_justification='c'), sg.Col(right_col, element_justification='c') ])] + + # --------------------------------- Create Window --------------------------------- + window = sg.Window('PSG Finder Launcher', layout) + + sg.cprint_set_output_destination(window, ML_KEY) + return window +# --------------------------------- Main Program Layout --------------------------------- + +def main(): + """ + The main program that contains the event loop. + It will call the make_window function to create the window. + """ + + editor_program = get_editor() + demo_files_dict = get_demo_git_files() + demo_files = demo_files_dict.keys() + window = make_window() + + while True: + event, values = window.read() + if event in (sg.WINDOW_CLOSED, 'Exit'): + break + if event == 'Edit': + for file in values['-DEMO LIST-']: + sg.cprint(f'Editing using {editor_program}', text_color='white', background_color='red', end='') + sg.cprint('') + sg.cprint(f'{demo_files_dict[file]}', text_color='white', background_color='purple') + sg.execute_subprocess_nonblocking(f'{editor_program}', f'"{demo_files_dict[file]}"') + elif event == 'Run': + sg.cprint('Running....', c='white on green', end='') + sg.cprint('') + sg.cprint(f"Chose {values['-DEMO LIST-']}") + for file in values['-DEMO LIST-']: + file_to_run = str(demo_files_dict[file]) + sg.cprint(file_to_run,text_color='white', background_color='purple') + sg.execute_subprocess_nonblocking('python' if sg._running_windows() else 'python3', f'"{file_to_run}"') + # run_py(file_to_run) + elif event.startswith('Edit Me'): + sg.cprint(f'opening using {editor_program}\nThis file - {__file__}', text_color='white', background_color='green', end='') + sg.execute_subprocess_nonblocking(f'{editor_program}', f'"{__file__}"') + elif event == '-FILTER-': + new_list = [i for i in demo_files if values['-FILTER-'].lower() in i.lower()] + window['-DEMO LIST-'].update(new_list) + window['-FILTER NUMBER-'].update(f'{len(new_list)} files') + window['-FIND NUMBER-'].update('') + window['-FIND-'].update('') + elif event == '-FIND-': + file_list = find_in_file(values['-FIND-']) + window['-DEMO LIST-'].update(sorted(file_list)) + window['-FIND NUMBER-'].update(f'{len(file_list)} files') + window['-FILTER NUMBER-'].update('') + window['-FILTER-'].update('') + elif event == 'Settings': + if settings_window() is True: + window.close() + window = make_window() + editor_program = get_editor() + demo_files_dict = get_demo_git_files() + demo_files = demo_files_dict.keys() + elif event == 'Clear': + window['-FILTER-'].update('') + window['-FIND-'].update('') + window['-DEMO LIST-'].update(demo_files) + window['-FILTER NUMBER-'].update('') + window['-FIND NUMBER-'].update('') + + window.close() + + +if __name__ == '__main__': + + + main()