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 0000000..e37ac73 Binary files /dev/null and b/README/changes_hint_toc.png differ 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