diff --git a/CHANGES.md b/CHANGES.md index 4586611..ec5e276 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,15 @@ +# 1.10 +- Added cursor panel at bottom of Text Editor. + - Word counter. + - Symbol path. +- Added `insert` menu, for inserting Date. +- `ctrl + shift + u` and `ctrl + shift + l` will toggle uppercase and lowercase. +- `ctrl + shift + o` and `ctrl + shift + p` will toggle capitalize and variablize. +- Fixed `ctrl + f` not bringing up search pannel. +- Fixed error when creating new file. +- Removed Text Editor hints. +- Color tweaks. + # 1.9 - Tag Viewer now shows all tags regardless of whether the file is open or not. - File View can show symbols. Toggle with `ctrl` click. diff --git a/README.md b/README.md index 6675fb1..371ae0a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Text Editor -Version `1.9` +Version `1.10` ![](README/readme_preview.png) @@ -9,7 +9,7 @@ Version `1.9` - Multi file tab system. - File browser filtering. - Highlighting for common formats (`md` `json` `ini`...) -- Tag system. +- Tag [System](#mini-features-tags). - File Management: - Creation. - Renaming. @@ -18,13 +18,7 @@ Version `1.9` - Search files. - Image previews. - Auto save/load settings. -- Many little *Ease of Life* functions: - - Comment toggling for: - - `.md`: `` - - `.json`: `/* */` - - `.ini`: `; ` - - `.cfg`: `; ` - - `.yaml`: `# ` +- Many little *Ease of Life* [features](#mini-features). # Controls - `ctrl + N` New file. @@ -89,5 +83,68 @@ This will then highlight *Files* and *Symbols* that have that tag. - [ ] 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. -- `ctrl` click in File View to toggle it's symbol list. + +## File List +### Colorize Folder +You can colorize files in a folder for easier identification. Right click a folder and select a color. +The `tab colors` toggle at the top will toggle tabs colorized by folder. + +### Content Preview +You can preview the contents of a file by `ctrl + click`ing it. + +The list is clickable, so you can go straight to a section of the file. + +When using the filter, contents will be scanned. + +## Content List (Symbols) +### Selecting Sections +`ctrl + click`ing on a symbol will select all lines contained in it, and it's childrens. + +`ctrl + shift + click` a symbol will only select it's lines, not it's childrens. + +## File Editor +### Follow Link +You can follow Markdown links by `ctrl + click`ing on them. + +## Tags +The tag list displays all tags throughout the files. + +To add a tag to a file, include a comment, with a hashtag: +- `.md`: `` +- `.json`: `{ "#": "#tag1 #tag2 }` +- `.ini` `.cfg`: `; #tag1 #tag2` +- `.yaml`: `# #tag1 #tag2` + +`click` a tag to select it. + +All files in the File List and symbols in the Symbol List containing the tag, will be highlighted. + +`ctrl + click` to select multiple tags at once. + +## Meta Panel +Toggle the meta panel with `ctrl + M`. + +### Meta +The meta tab updates whenever you make a save. + +It lists some information on the contents of your file. + +Currently it mostly only works for Markdown. + +### Search +todo + +### System +Hitting refrsh will list all files in a table with sortable columns. + +Select a column to sort on: +- Chapter count. +- Word count. +- Unique words. +- Progress. +- Time since modified. + +### Image +In Markdown files (`.md`) you can `ctrl + click` an image to preview it. + +Images look like: `![](image_url.png)` in Markdown. \ No newline at end of file diff --git a/addons/text_editor/TE_Console.gd b/addons/text_editor/TE_Console.gd index 3ab2598..567a146 100644 --- a/addons/text_editor/TE_Console.gd +++ b/addons/text_editor/TE_Console.gd @@ -1,6 +1,9 @@ tool extends "res://addons/text_editor/TE_RichTextLabel.gd" +func _ready(): + clear() + func msg(msg): append_bbcode(str(msg)) newline() diff --git a/addons/text_editor/TE_Editor.gd b/addons/text_editor/TE_Editor.gd index d08a38c..8cab46d 100644 --- a/addons/text_editor/TE_Editor.gd +++ b/addons/text_editor/TE_Editor.gd @@ -83,29 +83,36 @@ var color_tag:Color = Color.yellow var color_var:Color = Color.orange var color_varname:Color = color_text.darkened(.25) +export var p_tab_parent:NodePath +export var p_tab_prefab:NodePath +export var p_console:NodePath +export var p_progress_bar:NodePath + +onready var tab_parent:TabContainer = get_node(p_tab_parent) +onready var tab_prefab:Node = get_node(p_tab_prefab) +onready var console:RichTextLabel = get_node(p_console) +onready var progress_bar:ProgressBar = get_node(p_progress_bar) + +export var p_menu_file:NodePath +export var p_menu_view:NodePath +export var p_menu_insert:NodePath +onready var menu_file:MenuButton = get_node(p_menu_file) +onready var menu_view:MenuButton = get_node(p_menu_view) +onready var menu_insert:MenuButton = get_node(p_menu_insert) +var popup_file:PopupMenu +var popup_view:PopupMenu +var popup_insert:PopupMenu +var popup_view_dir:PopupMenu = PopupMenu.new() +var popup_view_file:PopupMenu = PopupMenu.new() + onready var test_button:Node = $c/c/c/test -onready var tab_parent:TabContainer = $c/div1/div2/c/c/tab_container -onready var tab_prefab:Node = $file_editor onready var popup:ConfirmationDialog = $popup onready var popup_unsaved:ConfirmationDialog = $popup_unsaved onready var file_dialog:FileDialog = $file_dialog onready var line_edit:LineEdit = $c/div1/div2/c/line_edit -onready var menu_file:MenuButton = $c/c/c/file_button -onready var menu_view:MenuButton = $c/c/c/view_button onready var word_wrap:CheckBox = $c/c/c/word_wrap onready var tab_colors:CheckBox = $c/c/c/tab_colors -export var p_console:NodePath -onready var console:RichTextLabel = get_node(p_console) - -export var p_progress_bar:NodePath -onready var progress_bar:ProgressBar = get_node(p_progress_bar) - -var popup_file:PopupMenu -var popup_view:PopupMenu -var popup_view_dir:PopupMenu = PopupMenu.new() -var popup_view_file:PopupMenu = PopupMenu.new() - var current_directory:String = "res://" var file_list:Dictionary = {} var dir_paths:Array = [] @@ -149,7 +156,7 @@ func _ready(): btn.connect("pressed", popup_unsaved, "hide") TE_Util.dig(popup_unsaved, self, "_apply_fonts") - # menu + # menu: file menu_file.add_font_override("font", FONT_R) popup_file = menu_file.get_popup() popup_file.clear() @@ -159,7 +166,7 @@ func _ready(): popup_file.add_item("Open last closed", 300) _e = popup_file.connect("index_pressed", self, "_menu_file") - # view + # menu: view menu_view.add_font_override("font", FONT_R) popup_view = menu_view.get_popup() popup_view.clear() @@ -209,6 +216,15 @@ func _ready(): popup_view.add_submenu_item("Files", "Files") _e = popup_view_file.connect("index_pressed", self, "_menu_view_file") + # menu: insert + menu_insert.add_font_override("font", FONT_R) + popup_insert = menu_insert.get_popup() + popup_insert.clear() + popup_insert.add_font_override("font", FONT_R) + popup_insert.add_item("Date") + popup_insert.add_item("Words Typed") + _e = popup_insert.connect("index_pressed", self, "_menu_insert") + # file dialog _e = file_dialog.connect("file_selected", self, "_file_dialog_file") file_dialog.add_font_override("title_font", FONT_R) @@ -232,10 +248,25 @@ func _ready(): file_data.clear() _scanning = true _start_load_at = OS.get_system_time_secs() - _files_to_load = get_all_file_paths().duplicate() + _files_to_load = file_paths.duplicate()#get_all_file_paths().duplicate() start_progress(len(_files_to_load)) set_process(true) +func override_fonts(node:Node): + if node is RichTextLabel: + var r:RichTextLabel = node + r.add_font_override("normal_font", FONT_R) + r.add_font_override("bold_font", FONT_B) + r.add_font_override("italics_font", FONT_I) + r.add_font_override("bold_italics_font", FONT_BI) + +func get_symbol_color(deep:int=0, off:float=0.0) -> Color: + var t = clamp(deep / 6.0, 0.0, 1.0) + var s = pow(lerp(1.0, 0.33, t), 6.0) + var v = lerp(1.0, 0.33, t) + var c = color_symbol + return c.from_hsv(wrapf(c.h + off, 0.0, 1.0), c.s * s, c.v * v, c.a) + func start_progress(maxx:int): progress_bar.visible = true progress_bar.value = 0 @@ -537,12 +568,34 @@ func _apply_fonts(n:Node): if n.has_font("font"): n.add_font_override("font", FONT_R) +func insert_date(): + var d = OS.get_date() + var m = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][d.month-1] + insert("%s %s, %s" % [m, d.day, d.year]) + +func insert(text:String): + var t:TextEdit = get_selected_tab() + if t: + var l = t.cursor_get_line() + var c = t.cursor_get_column() + t.insert_text_at_cursor(text) + t.select(l, c, l, c+len(text)) + yield(get_tree(), "idle_frame") + t.grab_focus() + t.grab_click_focus() + func _menu_file(index:int): var text = popup_file.get_item_text(index) match text: "New File": popup_create_file() # "New File" "Open last closed": open_last_file() # "Open last closed" +func _menu_insert(index:int): + var text = popup_insert.get_item_text(index) + match text: + "Date": insert_date() + "Words Typed": insert("WORDS TYPED") + func _menu_view_dir(index:int): var text = popup_view_dir.get_item_text(index) match text: @@ -675,6 +728,7 @@ func create_file(file_path:String, text:String=""): if f.open(file_path, File.WRITE) == OK: f.store_string(text) f.close() + update_file_data(file_path) refresh_files() if file_dialog.has_meta("callback"): @@ -1025,15 +1079,15 @@ func _can_show_file(fname:String) -> bool: func get_dir_info(path:String) -> Dictionary: return TE_Util.dig_for(file_list, "file_path", path) -var all_file_paths:Array = [] -func get_all_file_paths(): - all_file_paths.clear() - TE_Util.dig(file_list, self, "_get_all_file_paths") - return all_file_paths - -func _get_all_file_paths(d:Dictionary): - if "files" in d: - all_file_paths.append_array(d.files) +#var all_file_paths:Array = [] +#func get_all_file_paths(): +# all_file_paths.clear() +# TE_Util.dig(file_list, self, "_get_all_file_paths") +# return all_file_paths +# +#func _get_all_file_paths(d:Dictionary): +# if "files" in d: +# all_file_paths.append_array(d.files) func get_file_tint_name(fpath:String) -> String: var bdir = fpath.get_base_dir() diff --git a/addons/text_editor/TE_FileEditor.gd b/addons/text_editor/TE_FileEditor.gd index b4b41ba..21172cc 100644 --- a/addons/text_editor/TE_FileEditor.gd +++ b/addons/text_editor/TE_FileEditor.gd @@ -126,7 +126,7 @@ func selection_lowercase(): func selection_variable(): _remember_selection() - insert_text_at_cursor(get_selection_text().to_lower().replace(" ", "_")) + insert_text_at_cursor(TE_Util.to_var(get_selection_text())) _remake_selection() func selection_capitalize(): @@ -134,6 +134,8 @@ func selection_capitalize(): insert_text_at_cursor(get_selection_text().capitalize()) _remake_selection() + + func _node(n): var _e if n is HScrollBar: @@ -188,20 +190,27 @@ 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] + if i == len(symbols)-1 or symbols.keys()[i+1] > l: + editor.select_symbol_line(sindex) + break + +func get_line_symbols(line:int) -> PoolStringArray: + var depth:PoolStringArray = 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 + depth[symbol.deep] = symbol.name - if i == len(symbols)-1 or symbols.keys()[i+1] > l: - editor.select_symbol_line(sindex) + if i == len(symbols)-1 or symbols.keys()[i+1] > line: depth.resize(symbol.deep+1) - hint_tooltip = "[%s]\n%s" % [editor.get_localized_path(file_path), depth.join("\n")] break + return depth func _input(e): if not editor.is_plugin_active(): @@ -272,10 +281,29 @@ func _input(e): 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() + if e.scancode == KEY_U: + if get_selection_text() == get_selection_text().to_upper(): + selection_lowercase() + else: + selection_uppercase() + + if e.scancode == KEY_L: + if get_selection_text() == get_selection_text().to_lower(): + selection_uppercase() + else: + selection_lowercase() + + if e.scancode == KEY_O: + if get_selection_text() == get_selection_text().capitalize(): + selection_variable() + else: + selection_capitalize() + + if e.scancode == KEY_P: + if get_selection_text() == TE_Util.to_var(get_selection_text()): + selection_capitalize() + else: + selection_variable() func _unhandled_key_input(e): if not visible: @@ -328,9 +356,10 @@ func goto_symbol(index:int): if syms and index >= 0 and index < len(syms): goto_line(syms[index]) -func goto_line(line:int): +func goto_line(line:int, bottom:bool=true): # force scroll to bottom so selected line will be at top - cursor_set_line(get_line_count()) + if bottom: + cursor_set_line(get_line_count()) cursor_set_line(line) _update_selected_line() @@ -467,7 +496,6 @@ func update_name(): editor.tab_parent.set_tab_icon(get_index(), null) editor.tab_parent.set_tab_title(get_index(), n) - editor.tab_parent.get_tab_control(get_index()).hint_tooltip = file_path func update_heading(): if Engine.editor_hint: diff --git a/addons/text_editor/TE_FileInfoLabel.gd b/addons/text_editor/TE_FileInfoLabel.gd new file mode 100644 index 0000000..730e0f1 --- /dev/null +++ b/addons/text_editor/TE_FileInfoLabel.gd @@ -0,0 +1,101 @@ +tool +extends Node + +const DIM:Color = Color.webgray +const CLR:Color = Color.white + +onready var editor:TE_Editor = owner +var tab:TextEdit = null +var typed:String = "" +var word_count:int = 0 + +func _ready(): + var _e + yield(get_tree(), "idle_frame") + _e = editor.tab_parent.connect("tab_changed", self, "_tab_changed") + + editor.override_fonts($l) + editor.override_fonts($m) + editor.override_fonts($r) + +func _tab_changed(index:int): + if tab and is_instance_valid(tab) and not tab.is_queued_for_deletion(): + tab.disconnect("cursor_changed", self, "_cursor_changed") + tab = null + + var new_tab = editor.tab_parent.get_child(index) + if tab == new_tab: + return + tab = new_tab + var _e + _e = tab.connect("cursor_changed", self, "_cursor_changed") + _e = tab.connect("text_changed", self, "_text_changed") + +func _text_changed(): +# print("text changed") + pass + +func _input(event): + if event is InputEventKey and event.pressed and tab and is_instance_valid(tab) and tab.has_focus(): + if not event.scancode == KEY_BACKSPACE: + if char(event.scancode) in " .?!-": + word_count += 1 + typed = "" + else: + typed += char(event.scancode) + _cursor_changed() + +func _cursor_changed(): + var l_lines:PoolStringArray = PoolStringArray() + var m_lines:PoolStringArray = PoolStringArray() + var r_lines:PoolStringArray = PoolStringArray() + var l:RichTextLabel + + if tab.is_selection_active(): + var seltext:String = tab.get_selection_text() + var words = {} + var word_count:int = TE_Util.count_words(seltext, words, null, false) + m_lines.append(kv("chars", len(seltext))) + m_lines.append(kv("words", word_count)) + + var l1 = tab.get_selection_from_line() + 1 + var l2 = tab.get_selection_to_line() + 1 + var c1 = tab.get_selection_from_column() + var c2 = tab.get_selection_to_column() + + if l1 == l2: + l_lines.append(kv("line", l1)) + l_lines.append(kv("char", "%s - %s" % [c1, c2])) + + else: + l_lines.append(clr("line: ", DIM) + clr(str(l1), CLR) + clr(":", DIM) + clr(str(c1), CLR)) + l_lines.append(clr("->", Color.webgray)) + l_lines.append(clr("line: ", DIM) + clr(str(l2), CLR) + clr(":", DIM) + clr(str(c2), CLR)) + + m_lines.append(kv("lines", abs(l2 - l1) + 1)) + + else: + l_lines.append(kv("line", tab.cursor_get_line() + 1)) + l_lines.append(kv("char", tab.cursor_get_column())) + + var depth = tab.get_line_symbols(tab.cursor_get_line()) + for i in len(depth): + depth[i] = b(depth[i]) + r_lines.append(depth.join(clr("/", DIM))) + + m_lines.append(kv("typed", word_count)) + + $l.set_bbcode(l_lines.join(" ")) + $m.set_bbcode("[center]" + m_lines.join(" ")) + $r.set_bbcode("[right]" +r_lines.join(" ")) + +func kv(k:String, v) -> String: + var clr2 = Color.white + if v is int: + v = TE_Util.commas(v) + return clr(k + ": ", DIM) + clr(str(v), clr2) + +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] diff --git a/addons/text_editor/TE_FilesList.gd b/addons/text_editor/TE_FilesList.gd index 678cbe9..9d81566 100644 --- a/addons/text_editor/TE_FilesList.gd +++ b/addons/text_editor/TE_FilesList.gd @@ -319,7 +319,7 @@ func _draw_dir(dir:Dictionary, deep:int): var sname = sdata.name if filter and not filter in sname.to_lower(): continue - var s = " ".repeat(sdata.deep) + clr(" %s) " % [j], dull) + clr(sname, dull_tint) + var s = clr("|%s %s) " % [" ".repeat(sdata.deep), j], dull) + clr(sname, dull_tint) var h = hint_path + " #" + sname symbol_lines.append(meta(space + s, ["fs", file_path, j], h)) diff --git a/addons/text_editor/TE_MetaTabs.gd b/addons/text_editor/TE_MetaTabs.gd index 84a5e27..8a4cd5f 100644 --- a/addons/text_editor/TE_MetaTabs.gd +++ b/addons/text_editor/TE_MetaTabs.gd @@ -13,12 +13,26 @@ func _unhandled_key_input(e): if not editor.is_plugin_active(): return - # Ctrl + M = meta tabs - if e.scancode == KEY_M and e.control and e.pressed: - get_parent().visible = not get_parent().visible - get_tree().set_input_as_handled() + if e.control and e.pressed: + match e.scancode: + # show this menu + KEY_M: + set_visible(not get_parent().visible) + get_tree().set_input_as_handled() + + # find menu + KEY_F: + set_visible(true) + select_tab($search) + $search/rte.select() + +func set_visible(v:bool): + get_parent().visible = v + +func select_tab(tab:Node): + current_tab = tab.get_index() func show_image(file_path:String): get_parent().visible = true - current_tab = $image.get_index() + select_tab($image) $image/image.texture = TE_Util.load_image(file_path) diff --git a/addons/text_editor/TE_Search.gd b/addons/text_editor/TE_Search.gd index 44147d3..07162e3 100644 --- a/addons/text_editor/TE_Search.gd +++ b/addons/text_editor/TE_Search.gd @@ -17,20 +17,10 @@ func _ready(): all_toggle.add_font_override("font", editor.FONT_R) case_toggle.add_font_override("font", editor.FONT_R) -func _unhandled_key_input(e): - if not editor.is_plugin_active(): - return - - # Ctrl + F to search - if e.scancode == KEY_F and e.pressed and e.control: - line_edit.grab_focus() - line_edit.grab_click_focus() - line_edit.select_all() - # show meta tab - get_parent().get_parent().show() - # make search tab current meta tab - get_parent().get_parent().current_tab = get_parent().get_index() - get_tree().set_input_as_handled() +func select(): + line_edit.grab_focus() + line_edit.grab_click_focus() + line_edit.select_all() func _clicked(args): match args[0]: @@ -39,12 +29,16 @@ func _clicked(args): editor.select_file(args[1]) yield(get_tree(), "idle_frame") # goto line - var line = int(args[2]) - tab.goto_line(line) + var hfrom = int(args[2]) + var line = int(args[3]) + tab.goto_line(hfrom) + tab.goto_line(line, false) # select area - var from = int(args[3]) - var lenn = int(args[4]) + var from = int(args[4]) + var lenn = int(args[5]) tab.select(line, from, line, from + lenn) + tab.cursor_set_line(line) + tab.cursor_set_column(from) func _text_entered(search_for:String): last_search = search_for @@ -62,33 +56,37 @@ func _text_entered(search_for:String): l = meta(l, ["goto", file_path, 0, 0, 0], file_path) bbcode.append(l) - for j in len(found[file_path]): + var all_found = found[file_path] + for j in len(all_found): var result = found[file_path][j] var got_lines = result[0] - var line_index = result[1] - var char_index = result[2] + var highlight_from = result[1] + var line_index = result[2] + var char_index = result[3] - if j != 0: - bbcode.append("\t" + clr("...", Color.gray)) + bbcode.append(clr(" %s/%s" % [j+1, len(all_found)], Color.orange)) for i in len(got_lines): l = "" + var highlight = got_lines[i][0] + var lindex = got_lines[i][1] + var ltext = got_lines[i][2] - if i == 2: - var line:String = got_lines[i] + if highlight: + var line:String = ltext var head:String = line.substr(0, char_index) var midd:String = line.substr(char_index, len(search_for)) var tail:String = line.substr(char_index+len(search_for)) - head = clr(head, Color.deepskyblue.lightened(.5)) - midd = clr(midd, Color.deepskyblue.darkened(.25)) - tail = clr(tail, Color.deepskyblue.lightened(.5)) - l = "\t" + clr(str(line_index-2+i+1) + ": ", Color.deepskyblue.lightened(.5)) + (head+midd+tail) + head = clr(head, Color.white.darkened(.25)) + midd = b(clr(midd, Color.white)) + tail = clr(tail, Color.white.darkened(.25)) + l = "\t" + clr(str(lindex) + ": ", Color.white.darkened(.25)) + (head+midd+tail) - elif line_index-2+i >= 0: - l = "\t" + clr(str(line_index-2+i+1) + ": ", Color.gray) + got_lines[i] + else: + l = "\t" + clr(str(lindex) + ": ", Color.white.darkened(.65)) + clr(ltext, Color.white.darkened(.5)) if l: - l = meta(l, ["goto", file_path, line_index, char_index, len(search_for)]) + l = meta(l, ["goto", file_path, highlight_from, line_index, char_index, len(search_for)]) bbcode.append(l) set_bbcode(bbcode.join("\n")) @@ -120,7 +118,7 @@ func _search(search_for:String) -> Dictionary: else: paths = [sel] - + for path in paths: var lines = TE_Util.load_text(path).split("\n") for line_index in len(lines): @@ -136,17 +134,25 @@ func _search(search_for:String) -> Dictionary: if not path in out: out[path] = [] - var preview_lines = PoolStringArray() + var preview_lines = [[true, line_index, lines[line_index]]] var highlight_from:int = line_index - # show surrounding 5 lines. - for i in range(-2, 3): - if line_index+i >= 0 and line_index+i < len(lines): - preview_lines.append(lines[line_index+i]) - else: - preview_lines.append("") + # previous few lines before a blank + for i in range(1, 3): + if line_index-i >= 0: + if not lines[line_index-i].strip_edges(): + break + highlight_from = line_index-i + preview_lines.push_front([false, line_index-i, lines[line_index-i]]) + + # next few lines before a blank + for i in range(1, 3): + if line_index+i < len(lines): + if not lines[line_index+i].strip_edges(): + break + preview_lines.push_back([false, line_index+i, lines[line_index+i]]) # lines, index in file, index in line - out[path].append([preview_lines, line_index, char_index]) + out[path].append([preview_lines, highlight_from, line_index, char_index]) return out diff --git a/addons/text_editor/TE_SymbolsList.gd b/addons/text_editor/TE_SymbolsList.gd index e2a2f85..6fe7e43 100644 --- a/addons/text_editor/TE_SymbolsList.gd +++ b/addons/text_editor/TE_SymbolsList.gd @@ -120,19 +120,18 @@ func _redraw(): if filter and not filter in symbol_info.name.to_lower(): continue - if deep == 0: - cl = editor.color_symbol - if symbol_info.name.begins_with("*") and symbol_info.name.ends_with("*"): - cl = TE_Util.hue_shift(cl, -.33) - elif symbol_info.name.begins_with('"') and symbol_info.name.ends_with('"'): - cl = TE_Util.hue_shift(cl, .33) + if symbol_info.name.begins_with("*") and symbol_info.name.ends_with("*"): + cl = editor.get_symbol_color(deep, -.33) + + elif symbol_info.name.begins_with('"') and symbol_info.name.ends_with('"'): + cl = editor.get_symbol_color(deep, .33) + + else: + cl = editor.get_symbol_color(deep) if not editor.is_tagged_or_visible(symbol_info.tags): cl = cl.darkened(.7) - elif deep >= 1: - cl = cl.darkened(.33 * (deep-1)) - var tags = "" if not symbol_info.tags else PoolStringArray(symbol_info.tags).join(", ") var text = clr(meta(space + symbol_info.name, [symbol_info, line_index], tags), cl) if i == selected_line: diff --git a/addons/text_editor/TE_Util.gd b/addons/text_editor/TE_Util.gd index 1695592..f849064 100644 --- a/addons/text_editor/TE_Util.gd +++ b/addons/text_editor/TE_Util.gd @@ -31,13 +31,13 @@ class Sorter: static func sort_keys(d:Dictionary, reverse:bool=false): return Sorter.new(d).on_keys(reverse) static func sort_vals(d:Dictionary, reverse:bool=false): return Sorter.new(d).on_vals(reverse) -static func count_words(text:String, counter:Dictionary, skip_words=null): +static func count_words(text:String, counter:Dictionary, skip_words=null, stop_words:bool=true): var word_count:int = 0 for sentence in text.split("."): for word in sentence.split(" "): word = _sanitize_word(word) if not word: continue - if word in TE_StopWords.STOP_WORDS: continue + if stop_words and word in TE_StopWords.STOP_WORDS: continue if skip_words and word in skip_words: continue word_count += 1 @@ -69,6 +69,9 @@ static func _sanitize_word(word:String): return out +static func to_var(s:String) -> String: + return s.to_lower().replace(" ", "_") + static func load_text(path:String) -> String: var f:File = File.new() if f.file_exists(path): @@ -197,6 +200,9 @@ static func file_size(path:String) -> String: static func hue_shift(c:Color, h:float) -> Color: return c.from_hsv(wrapf(c.h + h, 0.0, 1.0), c.s, c.v, c.a) +#static func saturate(c:Color, s:float=1.0, v:float=1.0) -> Color: +# return c.from_hsv(c.h, c.s * s, c.v * v, c.a) + #static func sort(d, reverse:bool=false): # return Dict.new(d).sort(reverse) # diff --git a/addons/text_editor/TextEditor.tscn b/addons/text_editor/TextEditor.tscn index 734a68f..91bc7d0 100644 --- a/addons/text_editor/TextEditor.tscn +++ b/addons/text_editor/TextEditor.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=26 format=2] +[gd_scene load_steps=29 format=2] [ext_resource path="res://addons/text_editor/TE_Console.gd" type="Script" id=1] [ext_resource path="res://addons/text_editor/TE_Editor.gd" type="Script" id=2] @@ -17,6 +17,9 @@ [ext_resource path="res://addons/text_editor/TE_Search.gd" type="Script" id=15] [ext_resource path="res://addons/text_editor/TE_MetaTabs.gd" type="Script" id=16] [ext_resource path="res://addons/text_editor/TE_ScriptInfo.gd" type="Script" id=17] +[ext_resource path="res://addons/text_editor/TE_FileInfoLabel.gd" type="Script" id=18] +[ext_resource path="res://addons/text_editor/TE_RichTextLabel.gd" type="Script" id=19] +[ext_resource path="res://addons/text_editor/te_empty_style.tres" type="StyleBox" id=20] [sub_resource type="Theme" id=8] @@ -50,8 +53,13 @@ script = ExtResource( 2 ) __meta__ = { "_edit_use_anchors_": false } +p_tab_parent = NodePath("c/div1/div2/c/c/c2/tab_container") +p_tab_prefab = NodePath("file_editor") p_console = NodePath("c/div1/div2/c/c/c/meta_tabs/console") p_progress_bar = NodePath("c/c/c/progress") +p_menu_file = NodePath("c/c/c/file") +p_menu_view = NodePath("c/c/c/view") +p_menu_insert = NodePath("c/c/c/insert") [node name="file_editor" type="TextEdit" parent="."] visible = false @@ -97,7 +105,7 @@ margin_right = 12.0 margin_bottom = 24.0 text = "⟳" -[node name="file_button" type="MenuButton" parent="c/c/c"] +[node name="file" type="MenuButton" parent="c/c/c"] margin_left = 16.0 margin_right = 48.0 margin_bottom = 24.0 @@ -107,7 +115,7 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="view_button" type="MenuButton" parent="c/c/c"] +[node name="view" type="MenuButton" parent="c/c/c"] margin_left = 52.0 margin_right = 93.0 margin_bottom = 24.0 @@ -118,21 +126,32 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="word_wrap" type="CheckBox" parent="c/c/c"] +[node name="insert" type="MenuButton" parent="c/c/c"] margin_left = 97.0 -margin_right = 155.0 +margin_right = 146.0 +margin_bottom = 24.0 +focus_mode = 2 +text = "insert" +items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "Extensions", null, 0, false, false, 1, 0, null, "Extensions", false, "New File", null, 0, false, false, 2, 0, null, "", false, "Extensions", null, 0, false, false, 3, 0, null, "Extensions", false ] +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="word_wrap" type="CheckBox" parent="c/c/c"] +margin_left = 150.0 +margin_right = 208.0 margin_bottom = 24.0 text = "wrap" [node name="tab_colors" type="CheckBox" parent="c/c/c"] -margin_left = 159.0 -margin_right = 250.0 +margin_left = 212.0 +margin_right = 303.0 margin_bottom = 24.0 text = "tab colors" [node name="space" type="Control" parent="c/c/c"] -margin_left = 254.0 -margin_right = 978.0 +margin_left = 307.0 +margin_right = 971.0 margin_bottom = 24.0 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -147,12 +166,12 @@ size_flags_vertical = 3 [node name="version" type="Label" parent="c/c/c"] modulate = Color( 1, 1, 1, 0.521569 ) -margin_left = 982.0 +margin_left = 975.0 margin_top = 3.0 margin_right = 1010.0 margin_bottom = 20.0 custom_fonts/font = ExtResource( 12 ) -text = "v1.9" +text = "v1.10" align = 2 [node name="div1" type="HSplitContainer" parent="c"] @@ -192,6 +211,7 @@ margin_right = 192.0 margin_bottom = 27.0 custom_fonts/font = ExtResource( 12 ) clear_button_enabled = true +placeholder_text = "Filter" [node name="list_files" type="RichTextLabel" parent="c/div1/c2/c/c"] margin_top = 31.0 @@ -253,10 +273,17 @@ margin_right = 614.0 margin_bottom = 562.0 size_flags_horizontal = 3 size_flags_vertical = 3 +split_offset = 100 -[node name="tab_container" type="TabContainer" parent="c/div1/div2/c/c"] +[node name="c2" type="VBoxContainer" parent="c/div1/div2/c/c"] margin_right = 614.0 -margin_bottom = 275.0 +margin_bottom = 375.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="tab_container" type="TabContainer" parent="c/div1/div2/c/c/c2"] +margin_right = 614.0 +margin_bottom = 353.0 size_flags_horizontal = 3 size_flags_vertical = 3 custom_constants/top_margin = 0 @@ -269,8 +296,62 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="c" type="HBoxContainer" parent="c/div1/div2/c/c/c2"] +margin_top = 357.0 +margin_right = 614.0 +margin_bottom = 375.0 +size_flags_horizontal = 3 +script = ExtResource( 18 ) + +[node name="l" type="RichTextLabel" parent="c/div1/div2/c/c/c2/c"] +margin_right = 202.0 +margin_bottom = 18.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_fonts/bold_italics_font = ExtResource( 13 ) +custom_fonts/italics_font = ExtResource( 10 ) +custom_fonts/bold_font = ExtResource( 11 ) +custom_fonts/normal_font = ExtResource( 12 ) +custom_styles/focus = ExtResource( 20 ) +custom_styles/normal = ExtResource( 20 ) +bbcode_enabled = true +fit_content_height = true +script = ExtResource( 19 ) + +[node name="m" type="RichTextLabel" parent="c/div1/div2/c/c/c2/c"] +margin_left = 206.0 +margin_right = 408.0 +margin_bottom = 18.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_fonts/bold_italics_font = ExtResource( 13 ) +custom_fonts/italics_font = ExtResource( 10 ) +custom_fonts/bold_font = ExtResource( 11 ) +custom_fonts/normal_font = ExtResource( 12 ) +custom_styles/focus = ExtResource( 20 ) +custom_styles/normal = ExtResource( 20 ) +bbcode_enabled = true +fit_content_height = true +script = ExtResource( 19 ) + +[node name="r" type="RichTextLabel" parent="c/div1/div2/c/c/c2/c"] +margin_left = 412.0 +margin_right = 614.0 +margin_bottom = 18.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_fonts/bold_italics_font = ExtResource( 13 ) +custom_fonts/italics_font = ExtResource( 10 ) +custom_fonts/bold_font = ExtResource( 11 ) +custom_fonts/normal_font = ExtResource( 12 ) +custom_styles/focus = ExtResource( 20 ) +custom_styles/normal = ExtResource( 20 ) +bbcode_enabled = true +fit_content_height = true +script = ExtResource( 19 ) + [node name="c" type="Control" parent="c/div1/div2/c/c"] -margin_top = 287.0 +margin_top = 387.0 margin_right = 614.0 margin_bottom = 562.0 size_flags_horizontal = 3 @@ -287,7 +368,6 @@ __meta__ = { } [node name="console" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs"] -visible = false anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 4.0 @@ -304,11 +384,6 @@ custom_fonts/normal_font = ExtResource( 12 ) bbcode_enabled = true meta_underlined = false text = "active: False -active: False -active: False -active: False -active: False -active: False " script = ExtResource( 1 ) @@ -357,7 +432,6 @@ margin_left = 413.0 margin_right = 504.0 margin_bottom = 27.0 custom_fonts/font = ExtResource( 12 ) -pressed = true text = "all files" [node name="case" type="CheckBox" parent="c/div1/div2/c/c/c/meta_tabs/search/c"] @@ -370,7 +444,7 @@ text = "match case" [node name="rte" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs/search"] margin_top = 31.0 margin_right = 606.0 -margin_bottom = 231.0 +margin_bottom = 139.0 size_flags_horizontal = 3 size_flags_vertical = 3 theme = SubResource( 12 ) @@ -401,7 +475,7 @@ text = "⟳" [node name="sys" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs/sys"] margin_top = 27.0 margin_right = 606.0 -margin_bottom = 227.0 +margin_bottom = 239.0 size_flags_horizontal = 3 size_flags_vertical = 3 theme = SubResource( 13 ) @@ -416,6 +490,7 @@ text = "idwords ⯆unique" script = ExtResource( 17 ) [node name="image" type="VBoxContainer" parent="c/div1/div2/c/c/c/meta_tabs"] +visible = false anchor_right = 1.0 anchor_bottom = 1.0 margin_left = 4.0 @@ -466,6 +541,7 @@ margin_right = 166.0 margin_bottom = 27.0 custom_fonts/font = ExtResource( 12 ) clear_button_enabled = true +placeholder_text = "Filter" [node name="list_symbols" type="RichTextLabel" parent="c/div1/div2/c2/c/c/c"] margin_top = 31.0 diff --git a/addons/text_editor/ext/ext_md.gd b/addons/text_editor/ext/ext_md.gd index df89dd9..96d87fa 100644 --- a/addons/text_editor/ext/ext_md.gd +++ b/addons/text_editor/ext/ext_md.gd @@ -128,9 +128,10 @@ func apply_colors(e:TE_Editor, t:TextEdit): var quote:Color = lerp(e.color_text, e.color_symbol, .5) t.add_color_override("function_color", e.color_text) + t.add_color_override("number_color", e.color_text) - t.add_keyword_color("true", e.color_var) - t.add_keyword_color("false", e.color_var) +# t.add_keyword_color("true", e.color_var) +# t.add_keyword_color("false", e.color_var) # bold italic t.add_color_region("***", "***", Color.tomato.darkened(.3), false) @@ -148,6 +149,8 @@ func apply_colors(e:TE_Editor, t:TextEdit): # non official markdown: # formatted t.add_color_region("{", "}", lerp(e.color_text, e.color_var, .5).darkened(.25), false) +# t.add_color_region("[", "]", lerp(e.color_text, e.color_var, .5).darkened(.25), false) +# t.add_color_region("(", ")", lerp(e.color_text, e.color_var, .5).darkened(.25), false) if false: # quote t.add_color_region('"', '"', quote, false) @@ -158,14 +161,11 @@ func apply_colors(e:TE_Editor, t:TextEdit): t.add_color_region("![", ")", e.color_var.lightened(.5)) # headings - var head = e.color_symbol - var tint1 = TE_Util.hue_shift(head, -.33) - var tint2 = TE_Util.hue_shift(head, .33) - for i in range(1, 6): + for i in range(1, 7): var h = "#".repeat(i) - t.add_color_region("%s *" % h, "*", tint1, true) - t.add_color_region("%s \"" % h, "\"", tint2, true) - t.add_color_region("%s " % h, "*", head, true) + t.add_color_region("%s *" % h, "*", e.get_symbol_color(i-1, -.33), true) + t.add_color_region("%s \"" % h, "\"", e.get_symbol_color(i-1, .33), true) + t.add_color_region("%s " % h, "*", e.get_symbol_color(i-1), true) # lists t.add_color_region("- [x", "]", Color.yellowgreen, false) diff --git a/addons/text_editor/plugin.cfg b/addons/text_editor/plugin.cfg index 88a9cda..bedc27f 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.9" +version="1.10" script="plugin.gd" diff --git a/addons/text_editor/te_empty_style.tres b/addons/text_editor/te_empty_style.tres new file mode 100644 index 0000000..a417515 --- /dev/null +++ b/addons/text_editor/te_empty_style.tres @@ -0,0 +1,3 @@ +[gd_resource type="StyleBoxEmpty" format=2] + +[resource]