From 06e8d176c4422ab400f5615ea0a2620cfce27b1c Mon Sep 17 00:00:00 2001 From: teebarjunk Date: Sun, 24 Oct 2021 11:27:27 -0400 Subject: [PATCH] 1.7 --- CHANGES.md | 32 +++- README.md | 64 ++++--- README/changes_hint_toc.png | Bin 0 -> 12325 bytes addons/text_editor/TE_Editor.gd | 169 +++++++++++++------ addons/text_editor/TE_FileEditor.gd | 86 ++++++++-- addons/text_editor/TE_FilesList.gd | 51 ++++-- addons/text_editor/TE_MetaInfo.gd | 3 + addons/text_editor/TE_RichTextLabel.gd | 1 + addons/text_editor/TE_ScriptInfo.gd | 141 ++++++++++++---- addons/text_editor/TE_Search.gd | 86 +++++++--- addons/text_editor/TE_StopWords.gd | 3 + addons/text_editor/TE_SymbolsList.gd | 29 +++- addons/text_editor/TE_Util.gd | 69 ++++++++ addons/text_editor/TextEditor.tscn | 49 ++++-- addons/text_editor/ext/TE_ExtensionHelper.gd | 2 +- addons/text_editor/ext/ext_md.gd | 121 ++++++++++++- addons/text_editor/fonts/font.tres | 1 + addons/text_editor/fonts/font_b.tres | 1 + addons/text_editor/fonts/font_bi.tres | 1 + addons/text_editor/fonts/font_i.tres | 1 + addons/text_editor/fonts/font_r.tres | 1 + addons/text_editor/plugin.cfg | 2 +- dummy.gd | 12 ++ word_skip_list.txt | 1 + 24 files changed, 746 insertions(+), 180 deletions(-) create mode 100644 README/changes_hint_toc.png create mode 100644 addons/text_editor/TE_StopWords.gd create mode 100644 dummy.gd create mode 100644 word_skip_list.txt diff --git a/CHANGES.md b/CHANGES.md index 9197dd4..ac6b8a3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,36 @@ +# 1.7 +- Added option to view `Extensionless` files. +- Added Symbol path heirarchy to hint popup so you know where you are in big files: + ![](README/changes_hint_toc.png) +- `ctrl + shift +` + - `U` Make selection uppercase. + - `L` Make selection lowercase. + - `O` Make selection capitalized. + - `P` Make selection variable: `My text -> my_text` +- Select file shorctut: + - `ctrl + shift + 0-9` Remember file. + - `ctrl + 0-9` Swap to file. +- Selected Symbol is now highlighted. +- Improved meta data for `.md` files. +- `search` will autoselect term when clicked. +- `search` `all` toggle added to allow only searching in the selected file. +- `search` `case` toggle added to allow searching based on upper/lower case. +- `sys` panel shows unique word list. +- `sys` panel shows time since modified. +- Can create a `word_skip_list.txt` in main folder for ignoring certain words from showing in `sys` word list. +- File List panel hint paths are localized. +- Removed `.md` function color. +- Fixed `trash` not working in exported binaries. +- Fixed dragging files into directory bug. +- Fixed temporary files not closing properly. +- Fixed close non existing tab bug. +- Fixed symbol list not redrawing after file closed. +- Fixed symbol list not redrawing after file type changed. +- Fixed focus not being grabbed when tab selected. + # 1.6 - Added `Uppercase` `Lowercase` and `Capitalize` option to popup menu for selected text. -- `ctrl + click` in symbol view selects entire "chapter" and sub "chapters". `ctrl + shift + click` selects only one "chapter". +- `ctrl + click` in Symbol View selects entire "chapter" and sub "chapters". `ctrl + shift + click` selects only one "chapter". - `ctrl + click` in editor will auto scroll symbol view. - Folders can be tinted. - `word_wrap` state is saved/loaded. diff --git a/README.md b/README.md index 3f68acd..7a254b5 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,23 @@ # Text Editor -Version `1.6` +Version `1.7` ![](README/readme_preview.png) ***Warning: Use at your own risk. Backup your files before testing.*** # Features -- Tabs with scroll -- File filtering -- Highlighting for common file formats (`md` `json`...) -- Tag filtering system +- Multi file tab system. +- File browser filtering. +- Highlighting for common formats (`md` `json` `ini`...) +- Tag system. - File Management: - - Creation - - Renaming - - Recycling + - Creation. + - Renaming. + - Recycling. + - Moving. +- Search files. - Auto save/load settings -- Many little *Ease of life* functions: - - Folder open/close +- Many little *Ease of Life* functions: - Comment toggling for: - `.md`: `` - `.json`: `/* */` @@ -25,17 +26,19 @@ Version `1.6` - `.yaml`: `# ` # Controls -- `ctrl + N` New file -- `ctrl + W` Close file -- `ctrl + shift + W` Open last closed file -- `ctrl + tab` Select next open file -- `ctrl + shift + tab` Select last open file -- `ctrl + mouse wheel` Adjust font size -- `ctrl + shift + mouse wheel` Adjust ui font size -- `ctrl + up` `ctrl + down` Move selected lines -- `ctrl + /` Toggle line comments -- `ctrl + M` Toggle file meta info -- `ctrl + F` Search for text in all files +- `ctrl + N` New file. +- `ctrl + W` Close file. +- `ctrl + shift + W` Open last closed file . +- `ctrl + tab` Select next open file. +- `ctrl + shift + tab` Select last open file. +- `ctrl + mouse wheel` Adjust font size. +- `ctrl + shift + mouse wheel` Adjust ui font size. +- `ctrl + up` & `ctrl + down` Move selected lines. +- `ctrl + /` Toggle line comments. +- `ctrl + M` Toggle file meta info. +- `ctrl + F` Search for text in all files. +- `ctrl + shift + 0-9` Create hotkey for selected file. +- `ctrl + 0-9` Load hotkeyed file. ## Symbol View - `ctrl + click` Select entire block + children. @@ -44,9 +47,14 @@ Version `1.6` ## Editor View - `ctrl + click` anywhere: Scroll to nearest symbol in symbol view. - `ctrl + click` inside brackets: Goto local file. +- `ctrl + shift +` + - `U` Make selection uppercase. + - `L` Make selection lowercase. + - `O` Make selection capitalized. + - `P` Make selection variable: `My text -> my_text` # Symbols and Tags -*Symbols* are like a Table of Contents for a file. +*Symbols* are like *Table of Contents* for a file. - `Markdown` uses headings `# Heading` - `JSON` uses Dictionaries `"object": {` @@ -70,10 +78,14 @@ This will then highlight *Files* and *Symbols* that have that tag. # Todo - [x] `1.1` Preserve folders open/close state. - [x] `1.3` Search all files. -- [ ] Search file. +- [x] `1.7` Search file. - [ ] Find and replace. -- [ ] Improve meta data based on format. +- [x] `1.7` Improve meta data based on format. - [x] `1.2` Recycle folders. -- [x] `1.2` Unrecylce. (Toggle `view/directories/.trash` and press green arrow. +- [x] `1.2` Unrecylce. (Toggle `view/directories/.trash` and press green arrow.) - [ ] JSON formatting. -- [ ] JSON error testing. \ No newline at end of file +- [ ] JSON error testing. +- [ ] Color themes. + +# Mini features +- Clicking in file will scroll symbol view to the nearest symbol, and display it's name in the tool tip hint. diff --git a/README/changes_hint_toc.png b/README/changes_hint_toc.png new file mode 100644 index 0000000000000000000000000000000000000000..e37ac7399b9167f6964ac9c9e7a0e6fa92321cf0 GIT binary patch literal 12325 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 literal 0 HcmV?d00001 diff --git a/addons/text_editor/TE_Editor.gd b/addons/text_editor/TE_Editor.gd index 172a77c..1341c54 100644 --- a/addons/text_editor/TE_Editor.gd +++ b/addons/text_editor/TE_Editor.gd @@ -9,8 +9,8 @@ const FONT_B:DynamicFont = preload("res://addons/text_editor/fonts/font_b.tres") const FONT_I:DynamicFont = preload("res://addons/text_editor/fonts/font_i.tres") const FONT_BI:DynamicFont = preload("res://addons/text_editor/fonts/font_bi.tres") -const PATH_TRASH:String = "res://.trash" -const PATH_STATE:String = "res://.text_editor_state.json" +const DNAME_TRASH:String = ".trash" +const FNAME_STATE:String = ".text_editor_state.json" const MAIN_EXTENSIONS:PoolStringArray = PoolStringArray([ "txt", "md", "json", "csv", "cfg", "ini", "yaml" @@ -57,11 +57,13 @@ var show:Dictionary = { trash=false }, file={ - hidden=false + hidden=false, + extensionless=false } } var color_text:Color = Color.white +var color_background:Color = Color.transparent#Color.white.darkened(.85) var color_comment:Color = Color.white.darkened(.6) var color_symbol:Color = Color.deepskyblue var color_tag:Color = Color.yellow @@ -161,7 +163,8 @@ func _ready(): popup_view_file.clear() popup_view_file.set_name("Files") popup_view_file.add_font_override("font", FONT_R) - popup_view_file.add_check_item("Hidden", 0) + popup_view_file.add_check_item("Hidden") + popup_view_file.add_check_item("Extensionless") popup_view_file.set_item_checked(0, show.file.hidden) popup_view_file.add_separator() @@ -233,7 +236,10 @@ func update_checks(): func get_localized_path(file_path:String): assert(file_path.begins_with(current_directory)) - return file_path.substr(len(current_directory)) + var out:String = file_path.substr(len(current_directory)) + if out.begins_with("/"): + return out.substr(1) + return out func get_globalized_path(file_path:String): return current_directory.plus_file(file_path) @@ -244,13 +250,14 @@ func save_state(): "font_size": FONT.size, "font_size_ui": FONT_R.size, "tabs": {}, - "selected": get_localized_path(get_selected_file()), + "selected": get_selected_file(), "word_wrap": word_wrap.pressed, "show": show, "tags": tags, "tag_counts": tag_counts, "tags_enabled": tags_enabled, "exts_enabled": exts_enabled, + "shortcuts": shortcuts, "file_list": file_list, @@ -265,7 +272,7 @@ func save_state(): for tab in get_all_tabs(): state.tabs[get_localized_path(tab.file_path)] = tab.get_state() - TE_Util.save_json(PATH_STATE, state) + TE_Util.save_json(current_directory.plus_file(FNAME_STATE), state) emit_signal("state_saved") func _fix_tint(d:Dictionary): @@ -274,7 +281,7 @@ func _fix_tint(d:Dictionary): d.tint = Color(c[0], c[1], c[2], c[3]) func load_state(): - var state:Dictionary = TE_Util.load_json(PATH_STATE) + var state:Dictionary = TE_Util.load_json(current_directory.plus_file(FNAME_STATE)) if not state: return @@ -283,14 +290,14 @@ func load_state(): word_wrap.pressed = ww set_word_wrap(ww) - var selected + var selected_file:String for file_path in state.tabs: var st = state.tabs[file_path] file_path = get_globalized_path(file_path) var tab = _open_file(file_path) tab.set_state(st) if file_path == state.selected: - selected = tab + selected_file = file_path _load_property(state, "show", true) @@ -308,6 +315,7 @@ func load_state(): _load_property(state, "tag_counts") _load_property(state, "tags_enabled") _load_property(state, "exts_enabled") + _load_property(state, "shortcuts") # dividers $c/div1.split_offset = state.get("div1", $c/div1.split_offset) @@ -323,8 +331,10 @@ func load_state(): emit_signal("state_loaded") yield(get_tree(), "idle_frame") - if selected: - emit_signal("file_selected", selected.file_path) + if selected_file: + select_file(selected_file) +# if selected_tab: +# emit_signal("file_selected", selected_tab.file_path) func _load_property(state:Dictionary, property:String, merge:bool=false): if property in state and typeof(state[property]) == typeof(self[property]): @@ -351,6 +361,7 @@ func is_plugin_active(): return plugin_hint and visible +var shortcuts:Dictionary = {} func _input(e): if not is_plugin_active(): return @@ -374,7 +385,10 @@ func _input(e): if e.shift: open_last_file() else: - get_selected_tab().close() + var sel_tab = get_selected_tab() + if sel_tab != null: + sel_tab.close() + get_tree().set_input_as_handled() # create new file @@ -382,8 +396,23 @@ func _input(e): open_file("", true) get_tree().set_input_as_handled() + # shortcuts + elif e.scancode >= KEY_0 and e.scancode <= KEY_9: + if e.shift: + var sf = get_selected_file() + if sf: + shortcuts[str(e.scancode)] = sf + console.msg("shortcut %s: %s" % [e.scancode, sf]) + + else: + if str(e.scancode) in shortcuts: + var sf = shortcuts[str(e.scancode)] + open_file(sf) + select_file(sf) + + get_tree().set_input_as_handled() + if e is InputEventMouseButton and e.control: - # ui font if e.shift: if e.button_index == BUTTON_WHEEL_DOWN: @@ -447,20 +476,24 @@ func _menu_view_dir(index:int): save_state() func _menu_view_file(index:int): - # hidden files - if index == 0: - show.file.hidden = not show.file.hidden - popup_view_file.set_item_checked(index, show.file.hidden) - - # main extensions - else: - var text = popup_view_file.get_item_text(index) - var ext = text.substr(2) - if ext in exts_enabled: - exts_enabled[ext] = not exts_enabled[ext] - popup_view_file.set_item_checked(index, exts_enabled[ext]) - else: - print("no %s in %s" % [ext, exts_enabled]) + var text = popup_view_file.get_item_text(index) + match text: + "Hidden": + show.file.hidden = not show.file.hidden + popup_view_file.set_item_checked(index, show.file.hidden) + + "Extensionless": + show.file.extensionless = not show.file.extensionless + popup_view_file.set_item_checked(index, show.file.extensionless) + + # file extensions + _: + var ext = text.substr(2) + if ext in exts_enabled: + exts_enabled[ext] = not exts_enabled[ext] + popup_view_file.set_item_checked(index, exts_enabled[ext]) + else: + print("no %s in %s" % [ext, exts_enabled]) refresh_files() save_state() @@ -643,7 +676,11 @@ func _open_file(file_path:String): return tab func is_allowed_extension(file_path:String) -> bool: - var ext = get_extension(file_path) + var file = file_path.get_file() + if not "." in file and show.file.extensionless: + return true + + var ext = get_extension(file) return ext in MAIN_EXTENSIONS func open_file(file_path:String, temporary:bool=false): @@ -695,8 +732,18 @@ func unrecycle(file_path:String): push_error(err_msg) console.err(err_msg) -func recycle(file_path:String): - if file_path.begins_with(PATH_TRASH): +func is_trash_path(file_path:String) -> bool: + var path_trash:String = current_directory.plus_file(DNAME_TRASH) + return file_path.begins_with(path_trash) and file_path != path_trash + +func recycle(file_path:String, is_file:bool): + + if not is_file: + print("TODO: close all open windows") + + var path_trash:String = current_directory.plus_file(DNAME_TRASH) + + if file_path.begins_with(path_trash): var err_msg = "can't recycle recycled %s" % file_path push_error(err_msg) console.err(err_msg) @@ -710,14 +757,25 @@ func recycle(file_path:String): # is dir? var base_name = file_path.get_file() - var new_dir = PATH_TRASH.plus_file(time) + var new_dir = path_trash.plus_file(time) var new_path = new_dir.plus_file(base_name) - if not d.dir_exists(PATH_TRASH): - var _err = d.make_dir(PATH_TRASH) + if not d.dir_exists(path_trash): + var err = d.make_dir(path_trash) + if err != OK: + err("can't make dir %s" % path_trash) + return + + var err = d.make_dir(new_dir) + if err != OK: + err("can't make dir %s" % new_dir) + return + + err = d.rename(file_path, new_path) + if err != OK: + err("can't rename %s to %s" % [file_path, new_path]) + return - var _err = d.make_dir(new_dir) - d.rename(file_path, new_path) save_file(new_dir.plus_file(".old_path"), old_path) save_file(new_dir.plus_file(".new_path"), new_path) @@ -730,6 +788,10 @@ func recycle(file_path:String): if opened: select_file(opened[-1]) +func err(err_msg:String): + push_error(err_msg) + console.err(err_msg) + func rename_file(old_path:String, new_path:String): if old_path == new_path or not old_path or not new_path: return @@ -740,12 +802,12 @@ func rename_file(old_path:String, new_path:String): console.err(err_msg) return - var selected = get_selected_file() + var was_selected = old_path == get_selected_file() if Directory.new().rename(old_path, new_path) == OK: refresh_files() - if selected == old_path: - _selected_file_changed(new_path) emit_signal("file_renamed", old_path, new_path) + if was_selected: + _selected_file_changed(new_path) else: var err_msg = "couldn't rename %s to %s." % [old_path, new_path] @@ -760,14 +822,17 @@ func select_file(file_path:String): if not is_allowed_extension(file_path): return - var temp = get_temporary_tab() - if temp: - if temp.file_path == file_path: - temp.temporary = false - else: - temp.close() + if is_opened(file_path): + var tab = get_tab(file_path) + if tab.temporary: + tab.temporary = false - if not is_opened(file_path): + else: + var temp = get_temporary_tab() + if temp != null: + tab_parent.remove_child(temp) + temp.queue_free() + open_file(file_path, true) # select current tab @@ -829,8 +894,12 @@ func show_dir(fname:String, base_dir:String) -> bool: return true func show_file(fname:String) -> bool: + # hidden if fname.begins_with("."): if not show.file.hidden: return false + # extensionless + if not "." in fname: + return show.file.extensionless var ext = get_extension(fname) return exts_enabled.get(ext, false) @@ -908,11 +977,17 @@ static func get_extension(file_path:String) -> String: return file.split(".", true, 1)[1] return "" +var complained_ext:Array = [] + func get_extension_helper(file_path:String) -> TE_ExtensionHelper: var ext:String = get_extension(file_path).replace(".", "_") var ext_path:String = "res://addons/text_editor/ext/ext_%s.gd" % ext if ext in ["cfg", "csv", "ini", "json", "md", "yaml"]: return load(ext_path).new() - console.err("no helper %s" % ext_path) + # only complain once + if not ext in complained_ext: + complained_ext.append(ext) + console.err("no format helper for '%s' files" % ext) + return load("res://addons/text_editor/ext/TE_ExtensionHelper.gd").new() diff --git a/addons/text_editor/TE_FileEditor.gd b/addons/text_editor/TE_FileEditor.gd index 1d6845d..5aa3056 100644 --- a/addons/text_editor/TE_FileEditor.gd +++ b/addons/text_editor/TE_FileEditor.gd @@ -50,10 +50,18 @@ func _ready(): popup.add_font_override("font", editor.FONT) popup.add_separator() - popup.add_item("Uppercase") + popup.add_item("Uppercase", 1000) +# var sc = ShortCut.new() +# sc.shortcut = InputEventKey.new() +# sc.shortcut.shift = true +# sc.shortcut.control = true +# sc.shortcut.scancode = KEY_U +# popup.add_item_shortcut(sc, 1000) popup.add_item("Lowercase") popup.add_item("Capitalize") popup.add_item("Variable") + +# popup.add_shortcut() _e = popup.connect("index_pressed", self, "_popup_menu") # hint @@ -69,17 +77,49 @@ func _popup_menu(index:int): "Capitalize": selection_capitalize() "Variable": selection_variable() +var cl +var cc +var isa +var sl1 +var sc1 +var sl2 +var sc2 + +func _remember_selection(): + cl = cursor_get_line() + cc = cursor_get_column() + isa = is_selection_active() + if isa: + sl1 = get_selection_from_line() + sc1 = get_selection_from_column() + sl2 = get_selection_to_line() + sc2 = get_selection_to_column() + +func _remake_selection(): + cursor_set_line(cl) + cursor_set_column(cc) + if isa: + select(sl1, sc1, sl2, sc2) + func selection_uppercase(): + _remember_selection() insert_text_at_cursor(get_selection_text().to_upper()) + _remake_selection() func selection_lowercase(): + _remember_selection() insert_text_at_cursor(get_selection_text().to_lower()) + _remake_selection() func selection_variable(): + _remember_selection() insert_text_at_cursor(get_selection_text().to_lower().replace(" ", "_")) + _remake_selection() func selection_capitalize(): + _remember_selection() insert_text_at_cursor(get_selection_text().capitalize()) + _remake_selection() func _node(n): var _e @@ -131,6 +171,25 @@ func _file_renamed(old_path:String, new_path:String): update_name() update_colors() +func _update_selected_line(): + var l = cursor_get_line() + editor.select_symbol_line(0) + + var depth = PoolStringArray() + for i in len(symbols): + var sindex = clamp(i, 0, len(symbols)) + var symbol = symbols.values()[sindex] + while len(depth) <= symbol.deep: + depth.append("") + + depth[symbol.deep] = " ".repeat(symbol.deep) + symbol.name + + if i == len(symbols)-1 or symbols.keys()[i+1] > l: + editor.select_symbol_line(sindex) + depth.resize(symbol.deep+1) + hint_tooltip = "[%s]\n%s" % [editor.get_localized_path(file_path), depth.join("\n")] + break + func _input(e): if not editor.is_plugin_active(): return @@ -138,20 +197,14 @@ func _input(e): if not visible or not in_focus or not mouse_inside: return + # show current position in heirarchy as editor hint + if e is InputEventMouseButton and not e.pressed: + _update_selected_line() + if e is InputEventMouseButton and not e.pressed and e.control: var line:String = get_line(cursor_get_line()) - # if selecting a symbol, show it in symbol viewer - if cursor_get_line() in symbols: - editor.select_symbol_line(symbols.keys().find(cursor_get_line())-1) - else: - var l = cursor_get_line() - editor.select_symbol_line(0) - for i in len(symbols): - if symbols.keys()[i] > l: - editor.select_symbol_line(max(0, i-2)) - break - + # click link var ca = line.find("(") var cb = line.find_last(")") if ca != -1 and cb != -1: @@ -205,6 +258,11 @@ func _input(e): for i in len(lines): set_line(f+i, lines[i]) select(f+1, 0, t+1, len(get_line(t+1))) cursor_set_line(cursor_get_line()+1, false) + + if e.scancode == KEY_U: selection_uppercase() + if e.scancode == KEY_L: selection_lowercase() + if e.scancode == KEY_O: selection_capitalize() + if e.scancode == KEY_P: selection_variable() func _unhandled_key_input(e): if not visible: @@ -249,11 +307,15 @@ func _file_selected(p:String): if had_selection: select(fl, fc, tl, tc) + grab_focus() + grab_click_focus() + func goto_line(line:int): # force scroll to bottom so selected line will be at top cursor_set_line(get_line_count()) cursor_set_line(line) + _update_selected_line() func text_changed(): if last_selected: diff --git a/addons/text_editor/TE_FilesList.gd b/addons/text_editor/TE_FilesList.gd index 6965660..edf61d8 100644 --- a/addons/text_editor/TE_FilesList.gd +++ b/addons/text_editor/TE_FilesList.gd @@ -56,8 +56,12 @@ func _dir_popup(index:int): file = file.file_path match dir_popup.get_item_text(index): - "New File": editor.popup_create_file(file) - "Remove": editor.recycle(file) + "New File": + editor.popup_create_file(file) + + "Remove": + editor.recycle(file, type == "f") + "Tint Yellow": selected[1].tint = Color.gold _redraw() @@ -89,7 +93,7 @@ func _file_popup(index:int): "Remove": if type == "f": - editor.recycle(file) + editor.recycle(file, true) _: selected = [] @@ -119,9 +123,11 @@ func _input(e:InputEvent): if type in ["f", "d"]: var file_path = file if type == "f" else file.file_path - if file_path.begins_with(editor.PATH_TRASH): - return # can't move recycling + # can't move recycling + if editor.is_trash_path(file_path): + return + # select for drag else: dragging = meta_hovered @@ -134,9 +140,10 @@ func _input(e:InputEvent): var drag_type = dragging[0] var drag_file = dragging[1] + # dragged onto directory? if type == "d": var dir:String = file.file_path - var old_path:String = drag_file.file_path + var old_path:String = drag_file if drag_type == "f" else drag_file.file_path var new_path:String = dir.plus_file(old_path.get_file()) editor.rename_file(old_path, new_path) @@ -151,7 +158,7 @@ func _input(e:InputEvent): # unrecycle "unrecycle": - editor.unrecycle(file) + editor.unrecycle(file.file_path) # select "f": @@ -194,8 +201,8 @@ func _draw_dir(dir:Dictionary, deep:int): var head:String = "▼" if dir.open else "▶" head = clr(space+FOLDER+head, Color.white.darkened(.5)) head += " " + b(file.get_file()) - var link:String = meta(head, ["d", dir], file) - if file.begins_with(editor.PATH_TRASH) and file.count("/") == 3: + var link:String = meta(head, ["d", dir], editor.get_localized_path(file)) + if editor.is_trash_path(file): link += " " + meta(clr("⬅", Color.yellowgreen), ["unrecycle", dir], file) lines.append(clr(link, dir.tint.darkened(dimmest))) @@ -214,7 +221,7 @@ func _draw_dir(dir:Dictionary, deep:int): for i in len(dir.files): var file_path = dir.files[i] file = file_path.get_file() - var p = file.split(".", true, 1) + var p = [file, ""] if not "." in file else file.split(".", true, 1) file = p[0] var ext = p[1] @@ -226,11 +233,11 @@ func _draw_dir(dir:Dictionary, deep:int): if "readme" in file.to_lower(): head = "🛈" - if is_selected: - head = "● " - - elif is_opened: - head = "○ " +# if is_selected or is_opened: +# head = "● " +# +# elif is_opened: +# head = "○ " head = clr(head, Color.white.darkened(.5 if is_opened else .75)) @@ -244,6 +251,14 @@ func _draw_dir(dir:Dictionary, deep:int): pass file = clr(file, color) - ext = clr("." + ext, Color.white.darkened(.65)) - var line = space + head + file + ext - lines.append(meta(line, ["f", file_path], file_path)) + ext = "" if not ext else clr("." + ext, Color.white.darkened(.65)) + + var line = file + ext + + if is_selected: + line = u(line) + +# if is_opened: +# line = b(line) + + lines.append(meta(space + head + line, ["f", file_path], editor.get_localized_path(file_path))) diff --git a/addons/text_editor/TE_MetaInfo.gd b/addons/text_editor/TE_MetaInfo.gd index d86f538..52c3755 100644 --- a/addons/text_editor/TE_MetaInfo.gd +++ b/addons/text_editor/TE_MetaInfo.gd @@ -17,6 +17,9 @@ func _file_saved(_file_path:String): _redraw() func _redraw(): + if not visible: + return + var tab = editor.get_selected_tab() if tab: tab.helper.generate_meta(tab, self) diff --git a/addons/text_editor/TE_RichTextLabel.gd b/addons/text_editor/TE_RichTextLabel.gd index 2e40792..4ae81cb 100644 --- a/addons/text_editor/TE_RichTextLabel.gd +++ b/addons/text_editor/TE_RichTextLabel.gd @@ -97,6 +97,7 @@ func table(rows) -> String: func b(t:String) -> String: return "[b]%s[/b]" % t func i(t:String) -> String: return "[i]%s[/i]" % t +func u(t:String) -> String: return "[u]%s[/u]" % t func clr(t:String, c:Color) -> String: return "[color=#%s]%s[/color]" % [c.to_html(), t] func center(t:String): return "[center]%s[/center]" % t diff --git a/addons/text_editor/TE_ScriptInfo.gd b/addons/text_editor/TE_ScriptInfo.gd index 54cd88a..83f2e03 100644 --- a/addons/text_editor/TE_ScriptInfo.gd +++ b/addons/text_editor/TE_ScriptInfo.gd @@ -3,7 +3,9 @@ extends "res://addons/text_editor/TE_RichTextLabel.gd" var chapter_info:Array = [] var sort_on:String = "words" -var sort_reverse:Dictionary = { id=false, words=false, chaps=false, "%":false } +var sort_on_index:int = 1 +var sort_reverse:Dictionary = { id=true, chaps=true, words=true, uwords=true, "%":true, modified=true } +var skip_words:PoolStringArray func _ready(): var btn = get_parent().get_node("update") @@ -14,6 +16,10 @@ func _ready(): func _update(): chapter_info.clear() + # load block list + var skip_list = editor.current_directory.plus_file("word_skip_list.txt") + skip_words = TE_Util.load_text(skip_list).replace("\n", " ").strip_edges().to_lower().split(" ") + for path in editor.file_paths: var file = path.get_file() var ext = file.get_extension() @@ -29,33 +35,62 @@ func _update(): _sort() _redraw() -func _chapter(path:String, line:int, id:String): - if not id: - id = "???" - chapter_info.append({ path=path, line=line, id=id, words=0, chaps=0, "%":0.0 }) - +const WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] +const MONTHS = ["Januaray", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] + +const TIMES:Dictionary = { + "second": 60, + "minute": 60, + "hour": 24, + "day": INF +} +func get_time(t:int) -> String: + for k in TIMES: + if t < TIMES[k]: + return "%s %s ago" % [t, k + ("" if t == 1 else "s")] + t /= TIMES[k] + return "???" + func _process_md(path:String): var lines = TE_Util.load_text(path).split("\n") - var is_entire_file:bool = false + var file_time = File.new().get_modified_time(path) + var curr_time = OS.get_unix_time() + var diff_time = curr_time - file_time + var time_nice = get_time(diff_time) - _chapter(path, 0, "(Noname)") + if false and diff_time > 9999999: + time_nice = OS.get_datetime_from_unix_time(file_time) + time_nice.weekday = WEEKDAYS[time_nice.weekday-1].substr(0, 3).to_lower() + time_nice.month = MONTHS[time_nice.month-1].substr(0, 3).to_lower() + time_nice.hour12 = str(time_nice.hour % 12) + time_nice.ampm = "am" if time_nice.hour > 12 else "pm" + time_nice = "{weekday} {month} {day}, {year} {hour12}:{minute}:{second}{ampm}".format(time_nice) + + var out = { path=path, line=0, id=editor.get_localized_path(path), modified=file_time, time_nice=time_nice, words=0, uwords={}, chaps=0, "%":0.0 } + chapter_info.append(out) var i = 0 while i < len(lines): # skip head meta if i == 0 and lines[i].begins_with("---"): - is_entire_file = true i += 1 while i < len(lines) and not lines[i].begins_with("---"): - if lines[i].begins_with("name: "): - chapter_info[-1].id = lines[i].split("name: ", true, 1)[1] - - elif lines[i].begins_with("progress: "): - chapter_info[-1]["%"] = float(lines[i].split("progress: ", true, 1)[1].replace("%", "")) - elif lines[i].begins_with("prog: "): - chapter_info[-1]["%"] = float(lines[i].split("prog: ", true, 1)[1].replace("%", "")) + if ":" in lines[i]: + var p = lines[i].split(":", true, 1) + var k = p[0].strip_edges() + var v = p[1].strip_edges() + match k: + "name": + out.id = v + + "prog", "progress": + out["%"] = float(v.replace("%", "")) i += 1 + # skip comments + elif ""): return .toggle_comment(t, head, tail) func apply_colors(e:TE_Editor, t:TextEdit): .apply_colors(e, t) + t.add_color_override("function_color", e.color_text) +# t.add_color_override("background_color", e.color_background) + t.add_keyword_color("true", e.color_var) t.add_keyword_color("false", e.color_var) @@ -59,7 +179,6 @@ func apply_colors(e:TE_Editor, t:TextEdit): # tables t.add_color_region("|", "", Color.tan, true) - func get_symbols(t:String) -> Dictionary: var out = .get_symbols(t) var last = add_symbol() diff --git a/addons/text_editor/fonts/font.tres b/addons/text_editor/fonts/font.tres index 3b524c2..d984585 100644 --- a/addons/text_editor/fonts/font.tres +++ b/addons/text_editor/fonts/font.tres @@ -5,6 +5,7 @@ [ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3] [resource] +size = 12 use_filter = true font_data = ExtResource( 1 ) fallback/0 = ExtResource( 3 ) diff --git a/addons/text_editor/fonts/font_b.tres b/addons/text_editor/fonts/font_b.tres index fd18dc1..ae35690 100644 --- a/addons/text_editor/fonts/font_b.tres +++ b/addons/text_editor/fonts/font_b.tres @@ -5,6 +5,7 @@ [ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3] [resource] +size = 12 use_filter = true font_data = ExtResource( 1 ) fallback/0 = ExtResource( 3 ) diff --git a/addons/text_editor/fonts/font_bi.tres b/addons/text_editor/fonts/font_bi.tres index 2961810..46c0782 100644 --- a/addons/text_editor/fonts/font_bi.tres +++ b/addons/text_editor/fonts/font_bi.tres @@ -5,6 +5,7 @@ [ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3] [resource] +size = 12 use_filter = true font_data = ExtResource( 1 ) fallback/0 = ExtResource( 3 ) diff --git a/addons/text_editor/fonts/font_i.tres b/addons/text_editor/fonts/font_i.tres index 23aa8e0..33b48ce 100644 --- a/addons/text_editor/fonts/font_i.tres +++ b/addons/text_editor/fonts/font_i.tres @@ -5,6 +5,7 @@ [ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3] [resource] +size = 12 use_filter = true font_data = ExtResource( 1 ) fallback/0 = ExtResource( 3 ) diff --git a/addons/text_editor/fonts/font_r.tres b/addons/text_editor/fonts/font_r.tres index 3b524c2..d984585 100644 --- a/addons/text_editor/fonts/font_r.tres +++ b/addons/text_editor/fonts/font_r.tres @@ -5,6 +5,7 @@ [ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3] [resource] +size = 12 use_filter = true font_data = ExtResource( 1 ) fallback/0 = ExtResource( 3 ) diff --git a/addons/text_editor/plugin.cfg b/addons/text_editor/plugin.cfg index 6df22b8..52c2312 100644 --- a/addons/text_editor/plugin.cfg +++ b/addons/text_editor/plugin.cfg @@ -3,5 +3,5 @@ name="TextEditor" description="A text editor for Godot." author="teebar" -version="1.6" +version="1.7" script="plugin.gd" diff --git a/dummy.gd b/dummy.gd new file mode 100644 index 0000000..a71a3fd --- /dev/null +++ b/dummy.gd @@ -0,0 +1,12 @@ +tool +extends Node2D + +export(String, MULTILINE) var text:String + +func _draw(): + var words = PoolStringArray() + for word in text.split("\n"): + word = TE_Util._sanitize_word(word) + if word: + words.append("\"%s\"" % word) + print("[%s]" % words.join(",")) diff --git a/word_skip_list.txt b/word_skip_list.txt new file mode 100644 index 0000000..e2cb4a4 --- /dev/null +++ b/word_skip_list.txt @@ -0,0 +1 @@ +ctrl file files sys symbol \ No newline at end of file