From 96c064c2b9af629de28af3e3eae9a760b5a4863a Mon Sep 17 00:00:00 2001 From: teebarjunk Date: Fri, 22 Oct 2021 23:51:34 -0400 Subject: [PATCH] 1.6 --- CHANGES.md | 14 +++++++ README.md | 7 +++- addons/text_editor/TE_Editor.gd | 57 +++++++++++++++++++++++----- addons/text_editor/TE_FileEditor.gd | 53 +++++++++++++++++++++++--- addons/text_editor/TE_FilesList.gd | 27 +++++++++++-- addons/text_editor/TE_LineEdit.gd | 1 - addons/text_editor/TE_ScriptInfo.gd | 23 +++++++++-- addons/text_editor/TE_SymbolsList.gd | 33 +++++++++++++++- addons/text_editor/TextEditor.tscn | 3 +- addons/text_editor/ext/ext_json.gd | 19 +++++----- addons/text_editor/ext/ext_md.gd | 9 ++++- addons/text_editor/plugin.cfg | 2 +- 12 files changed, 209 insertions(+), 39 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5d469d1..9197dd4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,17 @@ +# 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 editor will auto scroll symbol view. +- Folders can be tinted. +- `word_wrap` state is saved/loaded. +- Fixed error that occured when folder containing binary was moved. +- Markdown can have a `progress` field in meta data which can be sorted in `sys`. +- Markdown meta info taken into account for `sys` +- Markdown meta info colourized. +- Markdown code color based on variable color. +- JSON comments like YAML: `"#": "comment"` +- JSON color tweaks. + # 1.5 - Added `Ctrl + N` to immediately create new file without defining path. - New unsaved file will have contents remembered. diff --git a/README.md b/README.md index 2917d56..811b133 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Text Editor -Version `1.5` +Version `1.6` ![](README/readme_preview.png) @@ -35,6 +35,11 @@ Version `1.5` - `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 + +## Symbol View +- `ctrl + click` Select entire block + children. +- `ctrl + shift + click` Select block without children. # Symbols and Tags To make it easier to find stuff there is a *Symbol* viewer. diff --git a/addons/text_editor/TE_Editor.gd b/addons/text_editor/TE_Editor.gd index b7dbee3..172a77c 100644 --- a/addons/text_editor/TE_Editor.gd +++ b/addons/text_editor/TE_Editor.gd @@ -40,6 +40,8 @@ signal save_files() signal state_saved() signal state_loaded() +signal selected_symbol_line(symbol_index) + var plugin = null var plugin_hint:bool = false @@ -64,7 +66,7 @@ var color_comment:Color = Color.white.darkened(.6) var color_symbol:Color = Color.deepskyblue var color_tag:Color = Color.yellow var color_var:Color = Color.orange -var color_varname:Color = Color.white.darkened(.25) +var color_varname:Color = color_text.darkened(.25) onready var test_button:Node = $c/c/c/test onready var tab_parent:TabContainer = $c/div1/div2/c/c/tab_container @@ -198,9 +200,15 @@ func _ready(): set_directory() func _toggle_word_wrap(): - tab_prefab.set_wrap_enabled(word_wrap.pressed) + set_word_wrap(word_wrap.pressed) + +func set_word_wrap(ww:bool): + tab_prefab.set_wrap_enabled(ww) for tab in get_all_tabs(): - tab.set_wrap_enabled(word_wrap.pressed) + tab.set_wrap_enabled(ww) + +func select_symbol_line(line:int): + emit_signal("selected_symbol_line", line) func update_checks(): # Directories @@ -223,13 +231,21 @@ func update_checks(): var ext = INTERNAL_EXTENSIONS[i] var id = i+len(MAIN_EXTENSIONS)+3 +func get_localized_path(file_path:String): + assert(file_path.begins_with(current_directory)) + return file_path.substr(len(current_directory)) + +func get_globalized_path(file_path:String): + return current_directory.plus_file(file_path) + func save_state(): var state:Dictionary = { "save_version": "1", "font_size": FONT.size, "font_size_ui": FONT_R.size, "tabs": {}, - "selected": get_selected_file(), + "selected": get_localized_path(get_selected_file()), + "word_wrap": word_wrap.pressed, "show": show, "tags": tags, "tag_counts": tag_counts, @@ -247,20 +263,32 @@ func save_state(): state["window_size"] = [ws.x, ws.y] for tab in get_all_tabs(): - state.tabs[tab.file_path] = tab.get_state() + state.tabs[get_localized_path(tab.file_path)] = tab.get_state() TE_Util.save_json(PATH_STATE, state) emit_signal("state_saved") +func _fix_tint(d:Dictionary): + if "tint" in d: + var c = d.tint.split_floats(",") + d.tint = Color(c[0], c[1], c[2], c[3]) + func load_state(): var state:Dictionary = TE_Util.load_json(PATH_STATE) if not state: return + # word wrap + var ww = state.get("word_wrap", word_wrap) + word_wrap.pressed = ww + set_word_wrap(ww) + var selected 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(state.tabs[file_path]) + tab.set_state(st) if file_path == state.selected: selected = tab @@ -274,6 +302,8 @@ func load_state(): for f in [FONT_R, FONT_B, FONT_I, FONT_BI]: f.size = font_size_ui + TE_Util.dig(state.file_list, self, "_fix_tint") + _load_property(state, "file_list") _load_property(state, "tag_counts") _load_property(state, "tags_enabled") @@ -557,6 +587,9 @@ func get_temporary_tab() -> TextEdit: return child return null +func load_file(file_path:String) -> String: + return TE_Util.load_text(file_path) + func save_file(file_path:String, text:String): var f:File = File.new() var _err = f.open(file_path, File.WRITE) @@ -702,7 +735,9 @@ func rename_file(old_path:String, new_path:String): return if File.new().file_exists(new_path): - push_error("can't rename %s to %s. file already exists." % [old_path, new_path]) + var err_msg = "can't rename %s to %s. file already exists." % [old_path, new_path] + push_error(err_msg) + console.err(err_msg) return var selected = get_selected_file() @@ -713,7 +748,9 @@ func rename_file(old_path:String, new_path:String): emit_signal("file_renamed", old_path, new_path) else: - push_error("couldn't rename %s to %s." % [old_path, new_path]) + var err_msg = "couldn't rename %s to %s." % [old_path, new_path] + push_error(err_msg) + console.err(err_msg) func select_file(file_path:String): if not File.new().file_exists(file_path): @@ -809,7 +846,9 @@ func _scan_dir(id:String, path:String, dir:Directory, last_dir:Dictionary, old_l files=a_files, dirs=a_dirs, show=true, - open=old_last_dir.get("open", true) } + open=old_last_dir.get("open", true), + tint=old_last_dir.get("tint", Color.white) + } last_dir[id] = info var fname = dir.get_next() diff --git a/addons/text_editor/TE_FileEditor.gd b/addons/text_editor/TE_FileEditor.gd index 830c15e..1d6845d 100644 --- a/addons/text_editor/TE_FileEditor.gd +++ b/addons/text_editor/TE_FileEditor.gd @@ -9,6 +9,7 @@ var helper:TE_ExtensionHelper var temporary:bool = false setget set_temporary var modified:bool = false var file_path:String = "" +var mouse_inside:bool = false var symbols:Dictionary = {} var tags:Dictionary = {} @@ -37,13 +38,23 @@ func _ready(): _e = connect("text_changed", self, "text_changed") _e = connect("focus_entered", self, "set", ["in_focus", true]) _e = connect("focus_exited", self, "set", ["in_focus", false]) + _e = connect("mouse_entered", self, "set", ["mouse_inside", true]) + _e = connect("mouse_exited", self, "set", ["mouse_inside", false]) if get_parent() is TabContainer: get_parent().connect("tab_changed", self, "_tab_changed") get_parent().connect("tab_selected", self, "_tab_changed") add_font_override("font", editor.FONT) - get_menu().add_font_override("font", editor.FONT) + var popup = get_menu() + popup.add_font_override("font", editor.FONT) + + popup.add_separator() + popup.add_item("Uppercase") + popup.add_item("Lowercase") + popup.add_item("Capitalize") + popup.add_item("Variable") + _e = popup.connect("index_pressed", self, "_popup_menu") # hint theme = Theme.new() @@ -51,6 +62,25 @@ func _ready(): TE_Util.dig(self, self, "_node") +func _popup_menu(index:int): + match get_menu().get_item_text(index): + "Uppercase": selection_uppercase() + "Lowercase": selection_lowercase() + "Capitalize": selection_capitalize() + "Variable": selection_variable() + +func selection_uppercase(): + insert_text_at_cursor(get_selection_text().to_upper()) + +func selection_lowercase(): + insert_text_at_cursor(get_selection_text().to_lower()) + +func selection_variable(): + insert_text_at_cursor(get_selection_text().to_lower().replace(" ", "_")) + +func selection_capitalize(): + insert_text_at_cursor(get_selection_text().capitalize()) + func _node(n): var _e if n is HScrollBar: @@ -105,11 +135,23 @@ func _input(e): if not editor.is_plugin_active(): return - if not visible or not in_focus: + if not visible or not in_focus or not mouse_inside: return 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 + var ca = line.find("(") var cb = line.find_last(")") if ca != -1 and cb != -1: @@ -209,7 +251,6 @@ func _file_selected(p:String): func goto_line(line:int): - prints("goto ", line) # force scroll to bottom so selected line will be at top cursor_set_line(get_line_count()) cursor_set_line(line) @@ -285,7 +326,7 @@ func _popup(msg): func load_file(path:String): file_path = path if path != "": - text = TE_Util.load_text(path) + text = editor.load_file(path) update_colors() update_name() @@ -328,8 +369,8 @@ func update_name(): if temporary: n = "?" + n if modified: n = "*" + n - if len(n) > 9: - n = n.substr(0, 6) + "..." + if len(n) > 12: + n = n.substr(0, 9) + "..." editor.tab_parent.set_tab_title(get_index(), n) editor.tab_parent.get_tab_control(get_index()).hint_tooltip = file_path diff --git a/addons/text_editor/TE_FilesList.gd b/addons/text_editor/TE_FilesList.gd index bb401b0..6965660 100644 --- a/addons/text_editor/TE_FilesList.gd +++ b/addons/text_editor/TE_FilesList.gd @@ -35,6 +35,12 @@ func _ready(): dir_popup.add_item("New File") dir_popup.add_separator() dir_popup.add_item("Remove") + dir_popup.add_separator() + dir_popup.add_item("Tint Yellow") + dir_popup.add_item("Tint Red") + dir_popup.add_item("Tint Blue") + dir_popup.add_item("Tint Green") + dir_popup.add_item("Reset Tint") _e = dir_popup.connect("index_pressed", self, "_dir_popup") dir_popup.add_font_override("font", editor.FONT) @@ -52,6 +58,21 @@ func _dir_popup(index:int): match dir_popup.get_item_text(index): "New File": editor.popup_create_file(file) "Remove": editor.recycle(file) + "Tint Yellow": + selected[1].tint = Color.gold + _redraw() + "Tint Red": + selected[1].tint = Color.tomato + _redraw() + "Tint Blue": + selected[1].tint = Color.deepskyblue + _redraw() + "Tint Green": + selected[1].tint = Color.chartreuse + _redraw() + "Reset Tint": + selected[1].tint = Color.white + _redraw() func _file_popup(index:int): var type = selected[0] @@ -115,7 +136,7 @@ func _input(e:InputEvent): if type == "d": var dir:String = file.file_path - var old_path:String = drag_file + var old_path:String = drag_file.file_path var new_path:String = dir.plus_file(old_path.get_file()) editor.rename_file(old_path, new_path) @@ -176,7 +197,7 @@ func _draw_dir(dir:Dictionary, deep:int): var link:String = meta(head, ["d", dir], file) if file.begins_with(editor.PATH_TRASH) and file.count("/") == 3: link += " " + meta(clr("⬅", Color.yellowgreen), ["unrecycle", dir], file) - lines.append(clr(link, Color.white.darkened(dimmest))) + lines.append(clr(link, dir.tint.darkened(dimmest))) var sel = editor.get_selected_tab() sel = sel.file_path if sel else "" @@ -199,7 +220,7 @@ func _draw_dir(dir:Dictionary, deep:int): var is_selected = file_path == sel var is_opened = editor.is_opened(file_path) - var color = Color.white + var color = dir.tint head = "┣╸" if i != last else "┗╸" if "readme" in file.to_lower(): diff --git a/addons/text_editor/TE_LineEdit.gd b/addons/text_editor/TE_LineEdit.gd index 7ae695b..9ed9657 100644 --- a/addons/text_editor/TE_LineEdit.gd +++ b/addons/text_editor/TE_LineEdit.gd @@ -33,6 +33,5 @@ func _lost_focus(): func _enter(t:String): if fr: - print("calling %s with %s" % [fr, t]) fr.call_func(t) hide() diff --git a/addons/text_editor/TE_ScriptInfo.gd b/addons/text_editor/TE_ScriptInfo.gd index 3b26a2e..54cd88a 100644 --- a/addons/text_editor/TE_ScriptInfo.gd +++ b/addons/text_editor/TE_ScriptInfo.gd @@ -3,7 +3,7 @@ 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 } +var sort_reverse:Dictionary = { id=false, words=false, chaps=false, "%":false } func _ready(): var btn = get_parent().get_node("update") @@ -32,13 +32,13 @@ func _update(): 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 }) + chapter_info.append({ path=path, line=line, id=id, words=0, chaps=0, "%":0.0 }) func _process_md(path:String): var lines = TE_Util.load_text(path).split("\n") var is_entire_file:bool = false - _chapter(path, 0, "NOH") + _chapter(path, 0, "(Noname)") var i = 0 while i < len(lines): # skip head meta @@ -46,6 +46,14 @@ func _process_md(path:String): 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("%", "")) + i += 1 # skip code blocks @@ -106,7 +114,7 @@ func _redraw(): var c1 = Color.white.darkened(.4) var c2 = Color.white.darkened(.3) - var cols = ["id", "words", "chaps"] + var cols = ["id", "words", "chaps", "%"] push_align(RichTextLabel.ALIGN_CENTER) push_table(len(cols)) for id in cols: @@ -146,6 +154,13 @@ func _redraw(): add_text(TE_Util.commas(item[x])) pop() pop() + + # percent + push_cell() + push_color(clr) + add_text(str(int(item["%"]))) + pop() + pop() pop() pop() diff --git a/addons/text_editor/TE_SymbolsList.gd b/addons/text_editor/TE_SymbolsList.gd index 719d5bf..7868b8a 100644 --- a/addons/text_editor/TE_SymbolsList.gd +++ b/addons/text_editor/TE_SymbolsList.gd @@ -8,6 +8,7 @@ func _ready(): _e = editor.connect("symbols_updated", self, "_redraw") _e = editor.connect("tags_updated", self, "_redraw") _e = editor.connect("file_selected", self, "_file_selected") + _e = editor.connect("selected_symbol_line", self, "_selected_symbol_line") _e = get_v_scroll().connect("value_changed", self, "_scrolling") add_font_override("normal_font", editor.FONT_R) @@ -17,6 +18,10 @@ func _ready(): call_deferred("_redraw") +func _selected_symbol_line(line:int): +# scroll_to_line(get_line_count()-1) + scroll_to_line(line) + func _file_selected(file_path:String): yield(get_tree(), "idle_frame") get_v_scroll().value = hscrolls.get(file_path, 0) @@ -26,7 +31,33 @@ func _scrolling(v): func _clicked(args:Array): var te:TextEdit = editor.get_selected_tab() - te.goto_line(args[1]) + + # select entire symbol block? + if Input.is_key_pressed(KEY_CONTROL): + var tab = editor.get_selected_tab() + var symbols = {} if not tab else tab.symbols + var line_index:int = args[1] + var symbol_index:int = symbols.keys().find(line_index) + var next_line:int + + # select sub symbol blocks? + if not Input.is_key_pressed(KEY_SHIFT): + var deep = symbols[line_index].deep + + while symbol_index < len(symbols)-1 and symbols.values()[symbol_index+1].deep > deep: + symbol_index += 1 + + if symbol_index == len(symbols)-1: + next_line = tab.get_line_count()-1 + + else: + next_line = symbols.keys()[symbol_index+1]-1 + + tab.select(line_index, 0, next_line, len(tab.get_line(next_line))) + te.goto_line(line_index) + + else: + te.goto_line(args[1]) func _redraw(): var tab = editor.get_selected_tab() diff --git a/addons/text_editor/TextEditor.tscn b/addons/text_editor/TextEditor.tscn index 8f7a266..46304da 100644 --- a/addons/text_editor/TextEditor.tscn +++ b/addons/text_editor/TextEditor.tscn @@ -171,7 +171,7 @@ items = [ "Rename", null, 0, false, false, 0, 0, null, "", false, "", null, 0, f margin_right = 20.0 margin_bottom = 20.0 custom_fonts/font = ExtResource( 14 ) -items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "New Folder", null, 0, false, false, 1, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Remove", null, 0, false, false, 3, 0, null, "", false ] +items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Remove", null, 0, false, false, 2, 0, null, "", false ] [node name="div2" type="HSplitContainer" parent="c/div1"] margin_left = 218.0 @@ -241,6 +241,7 @@ custom_fonts/normal_font = ExtResource( 12 ) bbcode_enabled = true meta_underlined = false text = "active: False +active: False " script = ExtResource( 1 ) diff --git a/addons/text_editor/ext/ext_json.gd b/addons/text_editor/ext/ext_json.gd index 693b6b3..76e1bb3 100644 --- a/addons/text_editor/ext/ext_json.gd +++ b/addons/text_editor/ext/ext_json.gd @@ -17,19 +17,18 @@ func get_symbols(t:String): var deep = max(0, len(lines[i]) - len(lines[i].strip_edges(true, false)) - 1) last = add_symbol(i, deep, key) - # tags -# elif "/* #" in lines[i]: -# for tag in lines[i].split("/* #", true, 1)[1].split("*/", true, 1)[0].split("#"): -# tag = tag.strip_edges() -# if tag: -# last.tags.append(tag) - elif '"#": "' in lines[i]: for tag in lines[i].split('"#": "', true, 1)[1].split('"', true, 1)[0].split("#"): tag = tag.strip_edges() if tag: last.tags.append(tag) + elif '"tags": "' in lines[i]: + for tag in lines[i].split('"tags": "', true, 1)[1].split('"', true, 1)[0].split("#"): + tag = tag.strip_edges() + if tag: + last.tags.append(tag) + i += 1 return out @@ -38,12 +37,12 @@ func apply_colors(e:TE_Editor, t:TextEdit): .apply_colors(e, t) # vars - t.add_color_region(' "', '"', e.color_var) + t.add_color_region(' "', '"', e.color_varname) t.add_color_region('"', '"', e.color_varname) t.add_keyword_color("true", e.color_var) t.add_keyword_color("false", e.color_var) t.add_keyword_color("null", e.color_var) # comments - t.add_color_region("/*", "*/", e.color_comment) - t.add_color_region("//", "", e.color_comment, true) +# t.add_color_region("/*", "*/", e.color_comment) + t.add_color_region('\t"#"', ",", e.color_comment, false) diff --git a/addons/text_editor/ext/ext_md.gd b/addons/text_editor/ext/ext_md.gd index 13aa6e3..d7eb4f3 100644 --- a/addons/text_editor/ext/ext_md.gd +++ b/addons/text_editor/ext/ext_md.gd @@ -42,9 +42,10 @@ func apply_colors(e:TE_Editor, t:TextEdit): t.add_color_region("- [", " ]", e.color_text.darkened(.6), false) # code blocks - var code:Color = lerp(e.color_text.darkened(.5), Color.yellowgreen, .5) + var code:Color = TE_Util.hue_shift(e.color_var, .33)#.darkened(.25) t.add_color_region("```", "```", code, false) t.add_color_region("~~~", "~~~", code, false) + t.add_color_region("---", "---", code, false) # strikeout t.add_color_region("~~", "~~", Color.tomato, false) @@ -75,8 +76,12 @@ func get_symbols(t:String) -> Dictionary: tag = tag.strip_edges() if tag: last.tags.append(tag) + +# elif "name: " in lines[i]: +# last.name = lines[i].split("name: ", true, 1)[1] + i += 1 - i += 1 +# i += 1 # symbols elif lines[i].begins_with("#"): diff --git a/addons/text_editor/plugin.cfg b/addons/text_editor/plugin.cfg index b8170bc..6df22b8 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.5" +version="1.6" script="plugin.gd"