This commit is contained in:
teebarjunk 2021-11-27 05:35:18 -05:00
parent 40beef4690
commit dfe30486d2
15 changed files with 501 additions and 142 deletions

View File

@ -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 # 1.9
- Tag Viewer now shows all tags regardless of whether the file is open or not. - Tag Viewer now shows all tags regardless of whether the file is open or not.
- File View can show symbols. Toggle with `ctrl` click. - File View can show symbols. Toggle with `ctrl` click.

View File

@ -1,5 +1,5 @@
# Text Editor # Text Editor
Version `1.9` Version `1.10`
![](README/readme_preview.png) ![](README/readme_preview.png)
@ -9,7 +9,7 @@ Version `1.9`
- Multi file tab system. - Multi file tab system.
- File browser filtering. - File browser filtering.
- Highlighting for common formats (`md` `json` `ini`...) - Highlighting for common formats (`md` `json` `ini`...)
- Tag system. - Tag [System](#mini-features-tags).
- File Management: - File Management:
- Creation. - Creation.
- Renaming. - Renaming.
@ -18,13 +18,7 @@ Version `1.9`
- Search files. - Search files.
- Image previews. - Image previews.
- Auto save/load settings. - Auto save/load settings.
- Many little *Ease of Life* functions: - Many little *Ease of Life* [features](#mini-features).
- Comment toggling for:
- `.md`: `<!-- -->`
- `.json`: `/* */`
- `.ini`: `; `
- `.cfg`: `; `
- `.yaml`: `# `
# Controls # Controls
- `ctrl + N` New file. - `ctrl + N` New file.
@ -89,5 +83,68 @@ This will then highlight *Files* and *Symbols* that have that tag.
- [ ] Color themes. - [ ] Color themes.
# Mini features # 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`: `<!-- #tag1 #tag2 -->`
- `.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.

View File

@ -1,6 +1,9 @@
tool tool
extends "res://addons/text_editor/TE_RichTextLabel.gd" extends "res://addons/text_editor/TE_RichTextLabel.gd"
func _ready():
clear()
func msg(msg): func msg(msg):
append_bbcode(str(msg)) append_bbcode(str(msg))
newline() newline()

View File

@ -83,29 +83,36 @@ var color_tag:Color = Color.yellow
var color_var:Color = Color.orange var color_var:Color = Color.orange
var color_varname:Color = color_text.darkened(.25) 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 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:ConfirmationDialog = $popup
onready var popup_unsaved:ConfirmationDialog = $popup_unsaved onready var popup_unsaved:ConfirmationDialog = $popup_unsaved
onready var file_dialog:FileDialog = $file_dialog onready var file_dialog:FileDialog = $file_dialog
onready var line_edit:LineEdit = $c/div1/div2/c/line_edit 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 word_wrap:CheckBox = $c/c/c/word_wrap
onready var tab_colors:CheckBox = $c/c/c/tab_colors 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 current_directory:String = "res://"
var file_list:Dictionary = {} var file_list:Dictionary = {}
var dir_paths:Array = [] var dir_paths:Array = []
@ -149,7 +156,7 @@ func _ready():
btn.connect("pressed", popup_unsaved, "hide") btn.connect("pressed", popup_unsaved, "hide")
TE_Util.dig(popup_unsaved, self, "_apply_fonts") TE_Util.dig(popup_unsaved, self, "_apply_fonts")
# menu # menu: file
menu_file.add_font_override("font", FONT_R) menu_file.add_font_override("font", FONT_R)
popup_file = menu_file.get_popup() popup_file = menu_file.get_popup()
popup_file.clear() popup_file.clear()
@ -159,7 +166,7 @@ func _ready():
popup_file.add_item("Open last closed", 300) popup_file.add_item("Open last closed", 300)
_e = popup_file.connect("index_pressed", self, "_menu_file") _e = popup_file.connect("index_pressed", self, "_menu_file")
# view # menu: view
menu_view.add_font_override("font", FONT_R) menu_view.add_font_override("font", FONT_R)
popup_view = menu_view.get_popup() popup_view = menu_view.get_popup()
popup_view.clear() popup_view.clear()
@ -209,6 +216,15 @@ func _ready():
popup_view.add_submenu_item("Files", "Files") popup_view.add_submenu_item("Files", "Files")
_e = popup_view_file.connect("index_pressed", self, "_menu_view_file") _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 # file dialog
_e = file_dialog.connect("file_selected", self, "_file_dialog_file") _e = file_dialog.connect("file_selected", self, "_file_dialog_file")
file_dialog.add_font_override("title_font", FONT_R) file_dialog.add_font_override("title_font", FONT_R)
@ -232,10 +248,25 @@ func _ready():
file_data.clear() file_data.clear()
_scanning = true _scanning = true
_start_load_at = OS.get_system_time_secs() _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)) start_progress(len(_files_to_load))
set_process(true) 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): func start_progress(maxx:int):
progress_bar.visible = true progress_bar.visible = true
progress_bar.value = 0 progress_bar.value = 0
@ -537,12 +568,34 @@ func _apply_fonts(n:Node):
if n.has_font("font"): if n.has_font("font"):
n.add_font_override("font", FONT_R) 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): func _menu_file(index:int):
var text = popup_file.get_item_text(index) var text = popup_file.get_item_text(index)
match text: match text:
"New File": popup_create_file() # "New File" "New File": popup_create_file() # "New File"
"Open last closed": open_last_file() # "Open last closed" "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): func _menu_view_dir(index:int):
var text = popup_view_dir.get_item_text(index) var text = popup_view_dir.get_item_text(index)
match text: match text:
@ -675,6 +728,7 @@ func create_file(file_path:String, text:String=""):
if f.open(file_path, File.WRITE) == OK: if f.open(file_path, File.WRITE) == OK:
f.store_string(text) f.store_string(text)
f.close() f.close()
update_file_data(file_path)
refresh_files() refresh_files()
if file_dialog.has_meta("callback"): if file_dialog.has_meta("callback"):
@ -1025,15 +1079,15 @@ func _can_show_file(fname:String) -> bool:
func get_dir_info(path:String) -> Dictionary: func get_dir_info(path:String) -> Dictionary:
return TE_Util.dig_for(file_list, "file_path", path) return TE_Util.dig_for(file_list, "file_path", path)
var all_file_paths:Array = [] #var all_file_paths:Array = []
func get_all_file_paths(): #func get_all_file_paths():
all_file_paths.clear() # all_file_paths.clear()
TE_Util.dig(file_list, self, "_get_all_file_paths") # TE_Util.dig(file_list, self, "_get_all_file_paths")
return all_file_paths # return all_file_paths
#
func _get_all_file_paths(d:Dictionary): #func _get_all_file_paths(d:Dictionary):
if "files" in d: # if "files" in d:
all_file_paths.append_array(d.files) # all_file_paths.append_array(d.files)
func get_file_tint_name(fpath:String) -> String: func get_file_tint_name(fpath:String) -> String:
var bdir = fpath.get_base_dir() var bdir = fpath.get_base_dir()

View File

@ -126,7 +126,7 @@ func selection_lowercase():
func selection_variable(): func selection_variable():
_remember_selection() _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() _remake_selection()
func selection_capitalize(): func selection_capitalize():
@ -134,6 +134,8 @@ func selection_capitalize():
insert_text_at_cursor(get_selection_text().capitalize()) insert_text_at_cursor(get_selection_text().capitalize())
_remake_selection() _remake_selection()
func _node(n): func _node(n):
var _e var _e
if n is HScrollBar: if n is HScrollBar:
@ -188,20 +190,27 @@ func _update_selected_line():
var l = cursor_get_line() var l = cursor_get_line()
editor.select_symbol_line(0) 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): for i in len(symbols):
var sindex = clamp(i, 0, len(symbols)) var sindex = clamp(i, 0, len(symbols))
var symbol = symbols.values()[sindex] var symbol = symbols.values()[sindex]
while len(depth) <= symbol.deep: while len(depth) <= symbol.deep:
depth.append("") 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: if i == len(symbols)-1 or symbols.keys()[i+1] > line:
editor.select_symbol_line(sindex)
depth.resize(symbol.deep+1) depth.resize(symbol.deep+1)
hint_tooltip = "[%s]\n%s" % [editor.get_localized_path(file_path), depth.join("\n")]
break break
return depth
func _input(e): func _input(e):
if not editor.is_plugin_active(): if not editor.is_plugin_active():
@ -272,10 +281,29 @@ func _input(e):
select(f+1, 0, t+1, len(get_line(t+1))) select(f+1, 0, t+1, len(get_line(t+1)))
cursor_set_line(cursor_get_line()+1, false) cursor_set_line(cursor_get_line()+1, false)
if e.scancode == KEY_U: selection_uppercase() if e.scancode == KEY_U:
if e.scancode == KEY_L: selection_lowercase() if get_selection_text() == get_selection_text().to_upper():
if e.scancode == KEY_O: selection_capitalize() selection_lowercase()
if e.scancode == KEY_P: selection_variable() 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): func _unhandled_key_input(e):
if not visible: if not visible:
@ -328,9 +356,10 @@ func goto_symbol(index:int):
if syms and index >= 0 and index < len(syms): if syms and index >= 0 and index < len(syms):
goto_line(syms[index]) 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 # 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) cursor_set_line(line)
_update_selected_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_icon(get_index(), null)
editor.tab_parent.set_tab_title(get_index(), n) editor.tab_parent.set_tab_title(get_index(), n)
editor.tab_parent.get_tab_control(get_index()).hint_tooltip = file_path
func update_heading(): func update_heading():
if Engine.editor_hint: if Engine.editor_hint:

View File

@ -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]

View File

@ -319,7 +319,7 @@ func _draw_dir(dir:Dictionary, deep:int):
var sname = sdata.name var sname = sdata.name
if filter and not filter in sname.to_lower(): if filter and not filter in sname.to_lower():
continue 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 var h = hint_path + " #" + sname
symbol_lines.append(meta(space + s, ["fs", file_path, j], h)) symbol_lines.append(meta(space + s, ["fs", file_path, j], h))

View File

@ -13,12 +13,26 @@ func _unhandled_key_input(e):
if not editor.is_plugin_active(): if not editor.is_plugin_active():
return return
# Ctrl + M = meta tabs if e.control and e.pressed:
if e.scancode == KEY_M and e.control and e.pressed: match e.scancode:
get_parent().visible = not get_parent().visible # show this menu
get_tree().set_input_as_handled() 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): func show_image(file_path:String):
get_parent().visible = true get_parent().visible = true
current_tab = $image.get_index() select_tab($image)
$image/image.texture = TE_Util.load_image(file_path) $image/image.texture = TE_Util.load_image(file_path)

View File

@ -17,20 +17,10 @@ func _ready():
all_toggle.add_font_override("font", editor.FONT_R) all_toggle.add_font_override("font", editor.FONT_R)
case_toggle.add_font_override("font", editor.FONT_R) case_toggle.add_font_override("font", editor.FONT_R)
func _unhandled_key_input(e): func select():
if not editor.is_plugin_active(): line_edit.grab_focus()
return line_edit.grab_click_focus()
line_edit.select_all()
# 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 _clicked(args): func _clicked(args):
match args[0]: match args[0]:
@ -39,12 +29,16 @@ func _clicked(args):
editor.select_file(args[1]) editor.select_file(args[1])
yield(get_tree(), "idle_frame") yield(get_tree(), "idle_frame")
# goto line # goto line
var line = int(args[2]) var hfrom = int(args[2])
tab.goto_line(line) var line = int(args[3])
tab.goto_line(hfrom)
tab.goto_line(line, false)
# select area # select area
var from = int(args[3]) var from = int(args[4])
var lenn = int(args[4]) var lenn = int(args[5])
tab.select(line, from, line, from + lenn) tab.select(line, from, line, from + lenn)
tab.cursor_set_line(line)
tab.cursor_set_column(from)
func _text_entered(search_for:String): func _text_entered(search_for:String):
last_search = search_for 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) l = meta(l, ["goto", file_path, 0, 0, 0], file_path)
bbcode.append(l) 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 result = found[file_path][j]
var got_lines = result[0] var got_lines = result[0]
var line_index = result[1] var highlight_from = result[1]
var char_index = result[2] var line_index = result[2]
var char_index = result[3]
if j != 0: bbcode.append(clr(" %s/%s" % [j+1, len(all_found)], Color.orange))
bbcode.append("\t" + clr("...", Color.gray))
for i in len(got_lines): for i in len(got_lines):
l = "" l = ""
var highlight = got_lines[i][0]
var lindex = got_lines[i][1]
var ltext = got_lines[i][2]
if i == 2: if highlight:
var line:String = got_lines[i] var line:String = ltext
var head:String = line.substr(0, char_index) var head:String = line.substr(0, char_index)
var midd:String = line.substr(char_index, len(search_for)) var midd:String = line.substr(char_index, len(search_for))
var tail: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)) head = clr(head, Color.white.darkened(.25))
midd = clr(midd, Color.deepskyblue.darkened(.25)) midd = b(clr(midd, Color.white))
tail = clr(tail, Color.deepskyblue.lightened(.5)) tail = clr(tail, Color.white.darkened(.25))
l = "\t" + clr(str(line_index-2+i+1) + ": ", Color.deepskyblue.lightened(.5)) + (head+midd+tail) l = "\t" + clr(str(lindex) + ": ", Color.white.darkened(.25)) + (head+midd+tail)
elif line_index-2+i >= 0: else:
l = "\t" + clr(str(line_index-2+i+1) + ": ", Color.gray) + got_lines[i] l = "\t" + clr(str(lindex) + ": ", Color.white.darkened(.65)) + clr(ltext, Color.white.darkened(.5))
if l: 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) bbcode.append(l)
set_bbcode(bbcode.join("\n")) set_bbcode(bbcode.join("\n"))
@ -120,7 +118,7 @@ func _search(search_for:String) -> Dictionary:
else: else:
paths = [sel] paths = [sel]
for path in paths: for path in paths:
var lines = TE_Util.load_text(path).split("\n") var lines = TE_Util.load_text(path).split("\n")
for line_index in len(lines): for line_index in len(lines):
@ -136,17 +134,25 @@ func _search(search_for:String) -> Dictionary:
if not path in out: if not path in out:
out[path] = [] out[path] = []
var preview_lines = PoolStringArray() var preview_lines = [[true, line_index, lines[line_index]]]
var highlight_from:int = line_index var highlight_from:int = line_index
# show surrounding 5 lines. # previous few lines before a blank
for i in range(-2, 3): for i in range(1, 3):
if line_index+i >= 0 and line_index+i < len(lines): if line_index-i >= 0:
preview_lines.append(lines[line_index+i]) if not lines[line_index-i].strip_edges():
else: break
preview_lines.append("") 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 # 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 return out

View File

@ -120,19 +120,18 @@ func _redraw():
if filter and not filter in symbol_info.name.to_lower(): if filter and not filter in symbol_info.name.to_lower():
continue continue
if deep == 0: if symbol_info.name.begins_with("*") and symbol_info.name.ends_with("*"):
cl = editor.color_symbol cl = editor.get_symbol_color(deep, -.33)
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('"'):
elif symbol_info.name.begins_with('"') and symbol_info.name.ends_with('"'): cl = editor.get_symbol_color(deep, .33)
cl = TE_Util.hue_shift(cl, .33)
else:
cl = editor.get_symbol_color(deep)
if not editor.is_tagged_or_visible(symbol_info.tags): if not editor.is_tagged_or_visible(symbol_info.tags):
cl = cl.darkened(.7) 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 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) var text = clr(meta(space + symbol_info.name, [symbol_info, line_index], tags), cl)
if i == selected_line: if i == selected_line:

View File

@ -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_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 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 var word_count:int = 0
for sentence in text.split("."): for sentence in text.split("."):
for word in sentence.split(" "): for word in sentence.split(" "):
word = _sanitize_word(word) word = _sanitize_word(word)
if not word: continue 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 if skip_words and word in skip_words: continue
word_count += 1 word_count += 1
@ -69,6 +69,9 @@ static func _sanitize_word(word:String):
return out return out
static func to_var(s:String) -> String:
return s.to_lower().replace(" ", "_")
static func load_text(path:String) -> String: static func load_text(path:String) -> String:
var f:File = File.new() var f:File = File.new()
if f.file_exists(path): 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: 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) 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): #static func sort(d, reverse:bool=false):
# return Dict.new(d).sort(reverse) # return Dict.new(d).sort(reverse)
# #

View File

@ -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_Console.gd" type="Script" id=1]
[ext_resource path="res://addons/text_editor/TE_Editor.gd" type="Script" id=2] [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_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_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_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] [sub_resource type="Theme" id=8]
@ -50,8 +53,13 @@ script = ExtResource( 2 )
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_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_console = NodePath("c/div1/div2/c/c/c/meta_tabs/console")
p_progress_bar = NodePath("c/c/c/progress") 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="."] [node name="file_editor" type="TextEdit" parent="."]
visible = false visible = false
@ -97,7 +105,7 @@ margin_right = 12.0
margin_bottom = 24.0 margin_bottom = 24.0
text = "⟳" 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_left = 16.0
margin_right = 48.0 margin_right = 48.0
margin_bottom = 24.0 margin_bottom = 24.0
@ -107,7 +115,7 @@ __meta__ = {
"_edit_use_anchors_": false "_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_left = 52.0
margin_right = 93.0 margin_right = 93.0
margin_bottom = 24.0 margin_bottom = 24.0
@ -118,21 +126,32 @@ __meta__ = {
"_edit_use_anchors_": false "_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_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 margin_bottom = 24.0
text = "wrap" text = "wrap"
[node name="tab_colors" type="CheckBox" parent="c/c/c"] [node name="tab_colors" type="CheckBox" parent="c/c/c"]
margin_left = 159.0 margin_left = 212.0
margin_right = 250.0 margin_right = 303.0
margin_bottom = 24.0 margin_bottom = 24.0
text = "tab colors" text = "tab colors"
[node name="space" type="Control" parent="c/c/c"] [node name="space" type="Control" parent="c/c/c"]
margin_left = 254.0 margin_left = 307.0
margin_right = 978.0 margin_right = 971.0
margin_bottom = 24.0 margin_bottom = 24.0
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
@ -147,12 +166,12 @@ size_flags_vertical = 3
[node name="version" type="Label" parent="c/c/c"] [node name="version" type="Label" parent="c/c/c"]
modulate = Color( 1, 1, 1, 0.521569 ) modulate = Color( 1, 1, 1, 0.521569 )
margin_left = 982.0 margin_left = 975.0
margin_top = 3.0 margin_top = 3.0
margin_right = 1010.0 margin_right = 1010.0
margin_bottom = 20.0 margin_bottom = 20.0
custom_fonts/font = ExtResource( 12 ) custom_fonts/font = ExtResource( 12 )
text = "v1.9" text = "v1.10"
align = 2 align = 2
[node name="div1" type="HSplitContainer" parent="c"] [node name="div1" type="HSplitContainer" parent="c"]
@ -192,6 +211,7 @@ margin_right = 192.0
margin_bottom = 27.0 margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 ) custom_fonts/font = ExtResource( 12 )
clear_button_enabled = true clear_button_enabled = true
placeholder_text = "Filter"
[node name="list_files" type="RichTextLabel" parent="c/div1/c2/c/c"] [node name="list_files" type="RichTextLabel" parent="c/div1/c2/c/c"]
margin_top = 31.0 margin_top = 31.0
@ -253,10 +273,17 @@ margin_right = 614.0
margin_bottom = 562.0 margin_bottom = 562.0
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 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_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_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
custom_constants/top_margin = 0 custom_constants/top_margin = 0
@ -269,8 +296,62 @@ __meta__ = {
"_edit_use_anchors_": false "_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"] [node name="c" type="Control" parent="c/div1/div2/c/c"]
margin_top = 287.0 margin_top = 387.0
margin_right = 614.0 margin_right = 614.0
margin_bottom = 562.0 margin_bottom = 562.0
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -287,7 +368,6 @@ __meta__ = {
} }
[node name="console" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs"] [node name="console" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs"]
visible = false
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
margin_left = 4.0 margin_left = 4.0
@ -304,11 +384,6 @@ custom_fonts/normal_font = ExtResource( 12 )
bbcode_enabled = true bbcode_enabled = true
meta_underlined = false meta_underlined = false
text = "active: False text = "active: False
active: False
active: False
active: False
active: False
active: False
" "
script = ExtResource( 1 ) script = ExtResource( 1 )
@ -357,7 +432,6 @@ margin_left = 413.0
margin_right = 504.0 margin_right = 504.0
margin_bottom = 27.0 margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 ) custom_fonts/font = ExtResource( 12 )
pressed = true
text = "all files" text = "all files"
[node name="case" type="CheckBox" parent="c/div1/div2/c/c/c/meta_tabs/search/c"] [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"] [node name="rte" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs/search"]
margin_top = 31.0 margin_top = 31.0
margin_right = 606.0 margin_right = 606.0
margin_bottom = 231.0 margin_bottom = 139.0
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
theme = SubResource( 12 ) theme = SubResource( 12 )
@ -401,7 +475,7 @@ text = "⟳"
[node name="sys" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs/sys"] [node name="sys" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs/sys"]
margin_top = 27.0 margin_top = 27.0
margin_right = 606.0 margin_right = 606.0
margin_bottom = 227.0 margin_bottom = 239.0
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
theme = SubResource( 13 ) theme = SubResource( 13 )
@ -416,6 +490,7 @@ text = "idwords ⯆unique"
script = ExtResource( 17 ) script = ExtResource( 17 )
[node name="image" type="VBoxContainer" parent="c/div1/div2/c/c/c/meta_tabs"] [node name="image" type="VBoxContainer" parent="c/div1/div2/c/c/c/meta_tabs"]
visible = false
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
margin_left = 4.0 margin_left = 4.0
@ -466,6 +541,7 @@ margin_right = 166.0
margin_bottom = 27.0 margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 ) custom_fonts/font = ExtResource( 12 )
clear_button_enabled = true clear_button_enabled = true
placeholder_text = "Filter"
[node name="list_symbols" type="RichTextLabel" parent="c/div1/div2/c2/c/c/c"] [node name="list_symbols" type="RichTextLabel" parent="c/div1/div2/c2/c/c/c"]
margin_top = 31.0 margin_top = 31.0

View File

@ -128,9 +128,10 @@ func apply_colors(e:TE_Editor, t:TextEdit):
var quote:Color = lerp(e.color_text, e.color_symbol, .5) var quote:Color = lerp(e.color_text, e.color_symbol, .5)
t.add_color_override("function_color", e.color_text) 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("true", e.color_var)
t.add_keyword_color("false", e.color_var) # t.add_keyword_color("false", e.color_var)
# bold italic # bold italic
t.add_color_region("***", "***", Color.tomato.darkened(.3), false) t.add_color_region("***", "***", Color.tomato.darkened(.3), false)
@ -148,6 +149,8 @@ func apply_colors(e:TE_Editor, t:TextEdit):
# non official markdown: # non official markdown:
# formatted # 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)
# t.add_color_region("(", ")", lerp(e.color_text, e.color_var, .5).darkened(.25), false)
if false: if false:
# quote # quote
t.add_color_region('"', '"', quote, false) 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)) t.add_color_region("![", ")", e.color_var.lightened(.5))
# headings # headings
var head = e.color_symbol for i in range(1, 7):
var tint1 = TE_Util.hue_shift(head, -.33)
var tint2 = TE_Util.hue_shift(head, .33)
for i in range(1, 6):
var h = "#".repeat(i) var h = "#".repeat(i)
t.add_color_region("%s *" % h, "*", tint1, true) t.add_color_region("%s *" % h, "*", e.get_symbol_color(i-1, -.33), true)
t.add_color_region("%s \"" % h, "\"", tint2, true) t.add_color_region("%s \"" % h, "\"", e.get_symbol_color(i-1, .33), true)
t.add_color_region("%s " % h, "*", head, true) t.add_color_region("%s " % h, "*", e.get_symbol_color(i-1), true)
# lists # lists
t.add_color_region("- [x", "]", Color.yellowgreen, false) t.add_color_region("- [x", "]", Color.yellowgreen, false)

View File

@ -3,5 +3,5 @@
name="TextEditor" name="TextEditor"
description="A text editor for Godot." description="A text editor for Godot."
author="teebar" author="teebar"
version="1.9" version="1.10"
script="plugin.gd" script="plugin.gd"

View File

@ -0,0 +1,3 @@
[gd_resource type="StyleBoxEmpty" format=2]
[resource]