This commit is contained in:
teebarjunk 2021-11-24 11:09:48 -05:00
parent 498fb79e89
commit 40beef4690
22 changed files with 652 additions and 159 deletions

View File

@ -1,3 +1,16 @@
# 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.
- File View filter will scan symbols as well.
- File List dims characters `0123456789-_`.
- Image Preview on `ctrl + click` in Markdown: `![](icon.png)` will display `"res://icon.png"`
- Tab title ignores leading numbers: "001_character" = "character"
- Directories are highlighted if they have a file with a selected tag.
- Holding `ctrl` while selecting a tag allows multiple to be selected.
- Added tab icon based on folder color.
- Fixed Markdown symbol generator including `#` inside code.
- Fixed meta container resizing.
# 1.8
- Added filter to symbols list.
- Added filter to file list.

View File

@ -1,5 +1,5 @@
# Text Editor
Version `1.8`
Version `1.9`
![](README/readme_preview.png)
@ -16,7 +16,8 @@ Version `1.8`
- Recycling.
- Moving.
- Search files.
- Auto save/load settings
- Image previews.
- Auto save/load settings.
- Many little *Ease of Life* functions:
- Comment toggling for:
- `.md`: `<!-- -->`
@ -89,3 +90,4 @@ This will then highlight *Files* and *Symbols* that have that tag.
# 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 97 KiB

View File

@ -28,12 +28,25 @@ const FILE_FILTERS:PoolStringArray = PoolStringArray([
"*.yaml ; YAML",
])
const DIR_COLORS:Dictionary = {
"red": Color.tomato,
"yellow": Color.gold,
"blue": Color.deepskyblue,
"green": Color.chartreuse
}
func get_tint_color(tint) -> Color:
if tint in DIR_COLORS:
return DIR_COLORS[tint]
return Color.white
signal updated_file_list()
signal file_opened(file_path)
signal file_closed(file_path)
signal file_selected(file_path)
signal file_saved(file_path)
signal file_renamed(old_path, new_path)
signal dir_tint_changed(dir)
signal symbols_updated()
signal tags_updated()
signal save_files()
@ -80,7 +93,14 @@ 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 console:RichTextLabel = $c/div1/div2/c/c/meta_tabs/console
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()
@ -90,16 +110,19 @@ var current_directory:String = "res://"
var file_list:Dictionary = {}
var dir_paths:Array = []
var file_paths:Array = []
var file_data:Dictionary = {}
var symbols:Dictionary = {}
var tags:Array = []
var tags_enabled:Dictionary = {}
var tag_counts:Dictionary = {}
var tags_enabled:Array = []
var tags:Dictionary = {}
var exts_enabled:Dictionary = {}
var opened:Array = []
var closed:Array = []
var ignore_head_numbers:bool = true
var show_tab_color:bool = true
func _ready():
console.info("active: %s" % is_plugin_active())
@ -198,9 +221,72 @@ func _ready():
_e = word_wrap.connect("pressed", self, "_toggle_word_wrap")
word_wrap.add_font_override("font", FONT_R)
# tab colors
_e = tab_colors.connect("pressed", self, "_toggle_tab_colors")
tab_colors.add_font_override("font", FONT_R)
load_state()
update_checks()
set_directory()
file_data.clear()
_scanning = true
_start_load_at = OS.get_system_time_secs()
_files_to_load = get_all_file_paths().duplicate()
start_progress(len(_files_to_load))
set_process(true)
func start_progress(maxx:int):
progress_bar.visible = true
progress_bar.value = 0
progress_bar.max_value = maxx
var _scanning = true
var _start_load_at = 0
var _files_to_load = []
func _process(delta):
var time = OS.get_system_time_secs()
while _files_to_load:
update_file_data(_files_to_load.pop_back())
progress_bar.value += 1
if OS.get_system_time_secs() - time >= 1:
break
if not _files_to_load:
_scanning = false
progress_bar.visible = false
set_process(false)
func update_file_data(file_path:String):
var helper = get_extension_helper(file_path)
var text = TE_Util.load_text(file_path)
var symbols = helper.get_symbols(text)
var ftags = helper.get_tag_counts(symbols)
var f:String = file_path
var data = file_data.get(file_path, { icon = "", tint = "", open = false })
data.symbols = symbols#helper.get_symbol_names(symbols)
data.tags = ftags
file_data[file_path] = data
tags.clear()
for d in file_data.values():
for tag in d.tags:
if not tag in tags:
tags[tag] = d.tags[tag]
else:
tags[tag] += d.tags[tag]
emit_signal("tags_updated")
# "001_file" -> ["001_", "file"]
func _split_header(fname:String):
var out = ["", ""]
var i = 0
for c in fname:
if i == 0 and not c in "0123456789_":
i = 1
out[i] += c
return out
func _toggle_word_wrap():
set_word_wrap(word_wrap.pressed)
@ -210,6 +296,14 @@ func set_word_wrap(ww:bool):
for tab in get_all_tabs():
tab.set_wrap_enabled(ww)
func _toggle_tab_colors():
set_tab_colors(tab_colors.pressed)
func set_tab_colors(tc:bool):
show_tab_color = tc
for tab in get_all_tabs():
tab.update_name()
func select_symbol_line(line:int):
emit_signal("selected_symbol_line", line)
@ -252,9 +346,10 @@ func save_state():
"tabs": {},
"selected": get_selected_file(),
"word_wrap": word_wrap.pressed,
"ignore_head_numbers": ignore_head_numbers,
"show_tab_color": show_tab_color,
"show": show,
"tags": tags,
"tag_counts": tag_counts,
"tags_enabled": tags_enabled,
"exts_enabled": exts_enabled,
"shortcuts": shortcuts,
@ -275,11 +370,6 @@ func save_state():
TE_Util.save_json(current_directory.plus_file(FNAME_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(current_directory.plus_file(FNAME_STATE))
if not state:
@ -290,6 +380,17 @@ func load_state():
word_wrap.pressed = ww
set_word_wrap(ww)
# show tab color
var stc = state.get("show_tab_color", show_tab_color)
tab_colors.pressed = stc
set_tab_colors(stc)
for k in ["ignore_head_numbers"]:
if k in state:
self[k] = state[k]
_load_property(state, "file_list")
var selected_file:String
for file_path in state.tabs:
var st = state.tabs[file_path]
@ -309,10 +410,6 @@ 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")
_load_property(state, "exts_enabled")
_load_property(state, "shortcuts")
@ -523,32 +620,41 @@ func _selected_file_changed(file_path:String):
emit_signal("file_selected", last_selected_file)
func is_tag_enabled(tag:String) -> bool:
return tags_enabled.get(tag, false)
return tag in tags_enabled
func enable_tag(tag:String, enabled:bool=true):
tags_enabled[tag] = enabled
tags.clear()
for t in tags_enabled:
if tags_enabled[t]:
tags.append(t)
if enabled:
if tag in tags and not tag in tags_enabled:
tags_enabled.append(tag)
else:
if tag in tags_enabled:
tags_enabled.erase(tag)
emit_signal("tags_updated")
func is_tagged_or_visible(file_tags:Array) -> bool:
if not len(tags):
if not len(tags_enabled):
return true
for t in tags:
for t in tags_enabled:
if not t in file_tags:
return false
return true
func is_tagged(file_path:String) -> bool:
var tab = get_tab(file_path)
if tab:
return is_tagged_or_visible(tab.tags.keys())
# wont work immediately, while files are being scanned
if not file_path in file_data:
return false
return is_tagged_or_visible(file_data[file_path].tags.keys())
func is_dir_tagged(dir:Dictionary) -> bool:
for f in dir.files:
if is_tagged(f):
return true
return false
func is_tagging() -> bool:
return len(tags) > 0
return len(tags_enabled) > 0
func popup_create_file(dir:String=current_directory, text:String="", callback:FuncRef=null):
file_dialog.mode = FileDialog.MODE_SAVE_FILE
@ -628,6 +734,7 @@ func save_file(file_path:String, text:String):
var _err = f.open(file_path, File.WRITE)
f.store_string(text)
f.close()
update_file_data(file_path)
emit_signal("file_saved", file_path)
func open_last_file():
@ -683,6 +790,9 @@ func is_allowed_extension(file_path:String) -> bool:
var ext = get_extension(file)
return ext in MAIN_EXTENSIONS
func is_image(file_path:String) -> bool:
return file_path.get_extension().to_lower() in ["png", "jpg", "jpeg", "webp", "bmp"]
func open_file(file_path:String, temporary:bool=false):
var tab = get_tab(file_path)
if tab:
@ -692,6 +802,9 @@ func open_file(file_path:String, temporary:bool=false):
push_error("no file %s" % file_path)
return null
elif is_image(file_path) and not file_path == "":
$c/div1/div2/c/c/c/meta_tabs.show_image(file_path)
elif not is_allowed_extension(file_path) and not file_path == "":
push_error("can't open %s" % file_path)
return null
@ -726,6 +839,7 @@ func unrecycle(file_path:String):
d.remove(op)
d.remove(np)
d.remove(file_path)
update_file_data(file_path)
refresh_files()
else:
var err_msg = "can't unrecyle %s" % file_path
@ -779,6 +893,7 @@ func recycle(file_path:String, is_file:bool):
save_file(new_dir.plus_file(".old_path"), old_path)
save_file(new_dir.plus_file(".new_path"), new_path)
file_data.erase(file_path)
refresh_files()
if tab:
@ -804,6 +919,8 @@ func rename_file(old_path:String, new_path:String):
var was_selected = old_path == get_selected_file()
if Directory.new().rename(old_path, new_path) == OK:
file_data[new_path] = file_data[old_path]
file_data.erase(old_path)
refresh_files()
emit_signal("file_renamed", old_path, new_path)
if was_selected:
@ -836,7 +953,8 @@ func select_file(file_path:String):
open_file(file_path, true)
# select current tab
tab_parent.current_tab = get_tab(file_path).get_index()
var current = get_tab(file_path)
tab_parent.current_tab = current.get_index()
_selected_file_changed(file_path)
func set_directory(path:String=current_directory):
@ -845,19 +963,19 @@ func set_directory(path:String=current_directory):
refresh_files()
func _file_symbols_updated(file_path:String):
var tg = get_tab(file_path).tags
tags_enabled.clear()
for tag in tg:
if not tag in tags_enabled:
tags_enabled[tag] = false
tag_counts.clear()
for child in get_all_tabs():
for t in child.tags:
if not t in tag_counts:
tag_counts[t] = child.tags[t]
else:
tag_counts[t] += child.tags[t]
# var tg = get_tab(file_path).tags
# tags_enabled.clear()
# for tag in tg:
# if not tag in tags_enabled:
# tags_enabled[tag] = false
#
# tag_counts.clear()
# for child in get_all_tabs():
# for t in child.tags:
# if not t in tag_counts:
# tag_counts[t] = child.tags[t]
# else:
# tag_counts[t] += child.tags[t]
emit_signal("symbols_updated")
@ -878,8 +996,8 @@ func refresh_files():
var err_msg = "error trying to load %s: %s" % [current_directory, err]
push_error(err_msg)
console.err(err_msg)
func show_dir(fname:String, base_dir:String) -> bool:
func _can_show_dir(fname:String, base_dir:String) -> bool:
if not show.dir.gdignore and File.new().file_exists(base_dir.plus_file(".gdignore")):
return false
@ -893,7 +1011,7 @@ func show_dir(fname:String, base_dir:String) -> bool:
return true
func show_file(fname:String) -> bool:
func _can_show_file(fname:String) -> bool:
# hidden
if fname.begins_with("."):
if not show.file.hidden: return false
@ -904,6 +1022,26 @@ func show_file(fname:String) -> bool:
var ext = get_extension(fname)
return exts_enabled.get(ext, false)
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)
func get_file_tint_name(fpath:String) -> String:
var bdir = fpath.get_base_dir()
var dir = get_dir_info(bdir)
if dir:
return dir.tint
return ""
func _scan_dir(id:String, path:String, dir:Directory, last_dir:Dictionary, old_last_dir:Dictionary):
var _e = dir.list_dir_begin(true, false)
var a_dirs_and_files = {}
@ -916,7 +1054,7 @@ func _scan_dir(id:String, path:String, dir:Directory, last_dir:Dictionary, old_l
dirs=a_dirs,
show=true,
open=old_last_dir.get("open", true),
tint=old_last_dir.get("tint", Color.white)
tint=old_last_dir.get("tint", Color.white),
}
last_dir[id] = info
@ -926,13 +1064,13 @@ func _scan_dir(id:String, path:String, dir:Directory, last_dir:Dictionary, old_l
var file_path = dir.get_current_dir().plus_file(fname)
if dir.current_is_dir():
if show_dir(fname, file_path):
if _can_show_dir(fname, file_path):
var sub_dir = Directory.new()
sub_dir.open(file_path)
_scan_dir(fname, file_path, sub_dir, a_dirs_and_files, old_last_dir.get("all", {}).get(fname, {}))
else:
if show_file(fname):
if _can_show_file(fname):
a_dirs_and_files[fname] = file_path
fname = dir.get_next()
@ -982,7 +1120,7 @@ var complained_ext:Array = []
func get_extension_helper(file_path:String) -> TE_ExtensionHelper:
var ext:String = get_extension(file_path).replace(".", "_")
var ext_path:String = "res://addons/text_editor/ext/ext_%s.gd" % ext
if ext in ["cfg", "csv", "ini", "json", "md", "yaml"]:
if ext in ["cfg", "csv", "ini", "json", "md", "yaml", "txt"]:
return load(ext_path).new()
# only complain once

View File

@ -18,6 +18,8 @@ var last_shift:bool
var last_selected:bool
var last_selection:Array = [0, 0, 0, 0]
var color:String = ""
var hscroll:int = 0
var vscroll:int = 0
var in_focus:bool = false
@ -35,6 +37,7 @@ func _ready():
_e = editor.connect("save_files", self, "save_file")
_e = editor.connect("file_selected", self, "_file_selected")
_e = editor.connect("file_renamed", self, "_file_renamed")
_e = editor.connect("dir_tint_changed", self, "_dir_tint_changed")
_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])
@ -76,6 +79,10 @@ func _ready():
TE_Util.dig(self, self, "_node")
func _dir_tint_changed(dir:String):
if file_path.get_base_dir() == dir:
update_name()
func _popup_menu(index:int):
match get_menu().get_item_text(index):
"Uppercase": selection_uppercase()
@ -316,6 +323,11 @@ func _file_selected(p:String):
grab_focus()
grab_click_focus()
func goto_symbol(index:int):
var syms = symbols.keys()
if syms and index >= 0 and index < len(syms):
goto_line(syms[index])
func goto_line(line:int):
# force scroll to bottom so selected line will be at top
cursor_set_line(get_line_count())
@ -434,15 +446,28 @@ func update_name():
else:
n = file_path.get_file().split(".", true, 1)[0]
if editor.ignore_head_numbers:
n = editor._split_header(n)[1]
if temporary: n = "?" + n
if modified: n = "*" + n
if len(n) > 12:
n = n.substr(0, 9) + "..."
if editor.show_tab_color:
var color = editor.get_file_tint_name(file_path)
var path = "res://addons/text_editor/icons/icon_%s.png" % color
if File.new().file_exists(path):
editor.tab_parent.set_tab_icon(get_index(), load(path))
else:
editor.tab_parent.set_tab_icon(get_index(), null)
else:
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
update_heading()
func update_heading():
if Engine.editor_hint:

View File

@ -73,19 +73,24 @@ func _dir_popup(index:int):
editor.recycle(file, type == "f")
"Tint Yellow":
selected[1].tint = Color.gold
selected[1].tint = "yellow"#Color.gold
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
"Tint Red":
selected[1].tint = Color.tomato
selected[1].tint = "red"#Color.tomato
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
"Tint Blue":
selected[1].tint = Color.deepskyblue
selected[1].tint = "blue"#Color.deepskyblue
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
"Tint Green":
selected[1].tint = Color.chartreuse
selected[1].tint = "green"#Color.chartreuse
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
"Reset Tint":
selected[1].tint = Color.white
selected[1].tint = ""#Color.white
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
func _file_popup(index:int):
@ -128,51 +133,67 @@ func _input(e:InputEvent):
var file = meta_hovered[1]
if e.button_index == BUTTON_LEFT:
if e.pressed:
if type in ["f", "d"]:
var file_path = file if type == "f" else file.file_path
# can't move recycling
if editor.is_trash_path(file_path):
return
if type == "f" and Input.is_key_pressed(KEY_CONTROL):
editor.file_data[file].open = not editor.file_data[file].open
_redraw()
# select for drag
else:
dragging = meta_hovered
var file_path = file if type == "f" else file.file_path
drag_label = DragLabel.new(file_path.get_file())
drag_label.editor = editor
editor.add_child(drag_label)
# can't move recycling
if editor.is_trash_path(file_path):
return
# select for drag
else:
dragging = meta_hovered
drag_label = DragLabel.new(file_path.get_file())
drag_label.editor = editor
editor.add_child(drag_label)
else:
if dragging and dragging != meta_hovered:
var drag_type = dragging[0]
var drag_file = dragging[1]
# dragged onto directory?
if type == "d":
var dir:String = file.file_path
var old_path:String = drag_file if drag_type == "f" else drag_file.file_path
var new_path:String = dir.plus_file(old_path.get_file())
editor.rename_file(old_path, new_path)
dragging = []
if type == "f" and Input.is_key_pressed(KEY_CONTROL):
pass
else:
match type:
# toggle directory
"d":
file.open = not file.open
_redraw()
if dragging and dragging != meta_hovered:
var drag_type = dragging[0]
var drag_file = dragging[1]
# unrecycle
"unrecycle":
editor.unrecycle(file.file_path)
# dragged onto directory?
if type == "d":
var dir:String = file.file_path
var old_path:String = drag_file if drag_type == "f" else drag_file.file_path
var new_path:String = dir.plus_file(old_path.get_file())
editor.rename_file(old_path, new_path)
# select
"f":
editor.select_file(file)
dragging = []
else:
match type:
# toggle directory
"d":
file.open = not file.open
_redraw()
# unrecycle
"unrecycle":
editor.unrecycle(file.file_path)
# select
"f":
editor.select_file(file)
# select file symbol
"fs":
editor.select_file(file)
var tab = editor.get_selected_tab()
yield(get_tree(), "idle_frame")
tab.goto_symbol(meta_hovered[2])
get_tree().set_input_as_handled()
@ -201,20 +222,37 @@ func _redraw():
_draw_dir(editor.file_list[""], 0)
set_bbcode(lines.join("\n"))
func _dull_nonwords(s:String, clr:Color, dull:Color) -> String:
var on = false
var parts = []
for c in s:
on = c in "0123456789_-"
if not parts or parts[-1][0] != on:
parts.append([on, ""])
parts[-1][1] += c
var out = ""
for p in parts:
out += clr(p[1], dull if p[0] else clr)
return out
const FOLDER:String = "🗀" # not visible in godot
func _draw_dir(dir:Dictionary, deep:int):
var is_tagging = editor.is_tagging()
var dimmest:float = .5 if is_tagging else 0.0
var tint = editor.get_tint_color(dir.tint)
var dull = Color.white.darkened(.65)
var dull_tint = tint.darkened(.5)
var space = clr("".repeat(deep), Color.white.darkened(.8))
var file:String = dir.file_path
var head:String = "" if dir.open else ""
head = clr(space+FOLDER, Color.gold) + clr(head, Color.white.darkened(.5))
head += " " + b(file.get_file())
head += " " + b(_dull_nonwords(file.get_file(), tint.darkened(0 if editor.is_dir_tagged(dir) else 0.5), dull))
var link:String = meta(head, ["d", dir], editor.get_localized_path(file))
if editor.is_trash_path(file):
link += " " + meta(clr("", Color.yellowgreen), ["unrecycle", dir], file)
lines.append(clr(link, dir.tint.darkened(dimmest)))
lines.append(link)
var sel = editor.get_selected_tab()
sel = sel.file_path if sel else ""
@ -237,37 +275,54 @@ func _draw_dir(dir:Dictionary, deep:int):
var is_selected = file_path == sel
var is_opened = editor.is_opened(file_path)
var color = dir.tint
var color = tint
head = "┣╸" if i != last else "┗╸"
var fname_lower = file.to_lower()
if filter and not filter in fname_lower:
continue
if "readme" in fname_lower:
head = "🛈"
head = clr(head, Color.white.darkened(.5 if is_opened else .75))
var bold = false
if is_tagging:
if editor.is_tagged(file_path):
file = b(file)
bold = true
else:
color = color.darkened(dimmest)
else:
pass
file = clr(file, color)
ext = "" if not ext else clr("." + ext, Color.white.darkened(.65))
file = _dull_nonwords(file, color, dull)
if bold:
file = b(file)
ext = "" if not ext else clr("." + ext, dull)
var line = file + ext
if is_selected:
line = u(line)
# if is_opened:
# line = b(line)
var hint_path = editor.get_localized_path(file_path)
var symbol_lines = []
lines.append(meta(space + head + line, ["f", file_path], editor.get_localized_path(file_path)))
if not editor._scanning:
var fdata = editor.file_data[file_path]
var symbols = fdata.symbols.values()
for j in range(1, len(symbols)):
if fdata.open or filter:
var sdata = symbols[j]
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 h = hint_path + " #" + sname
symbol_lines.append(meta(space + s, ["fs", file_path, j], h))
if symbol_lines or not (filter and not filter in fname_lower):
lines.append(meta(space + head + line, ["f", file_path], hint_path))
lines.append_array(symbol_lines)

View File

@ -15,5 +15,10 @@ func _unhandled_key_input(e):
# Ctrl + M = meta tabs
if e.scancode == KEY_M and e.control and e.pressed:
visible = not visible
get_parent().visible = not get_parent().visible
get_tree().set_input_as_handled()
func show_image(file_path:String):
get_parent().visible = true
current_tab = $image.get_index()
$image/image.texture = TE_Util.load_image(file_path)

View File

@ -16,18 +16,15 @@ func _ready():
theme.set_font("font", "TooltipLabel", editor.FONT_R)
call_deferred("_redraw")
#
#func _hovered(index):
# var tag = tag_indices[int(index)]
# var count = editor.tag_counts[tag]
# hint_tooltip =
#func _unhover(t):
# hint_tooltip = ""
func _clicked(args:Array):
var tag = args[0]
editor.enable_tag(tag, not editor.is_tag_enabled(tag))
var was_enabled = editor.is_tag_enabled(tag)
if not Input.is_key_pressed(KEY_CONTROL):
editor.tags_enabled.clear()
editor.enable_tag(tag, not was_enabled)
func sort_tags(tags:Dictionary):
var sorter:Array = []
@ -46,7 +43,7 @@ func _sort_tags(a, b):
func _redraw():
var tab = editor.get_selected_tab()
var tags = editor.tag_counts
var tags = editor.tags
var tab_tags = {} if not tab else tab.tags
sort_tags(tags)
@ -59,7 +56,7 @@ func _redraw():
var count_color1 = Color.tomato.to_html()
var count_color2 = Color.tomato.darkened(.75).to_html()
for tag in tags:
var count = editor.tag_counts[tag]
var count = editor.tags[tag]
var enabled = editor.is_tag_enabled(tag)
var x = tag

View File

@ -90,6 +90,16 @@ static func load_json(path:String, loud:bool=false) -> Dictionary:
push_error("no json at \"%s\"" % path)
return {}
static func load_image(path:String) -> ImageTexture:
var f:File = File.new()
if f.file_exists(path):
var image:Image = Image.new()
image.load(path)
var texture:ImageTexture = ImageTexture.new()
texture.create_from_image(image)
return texture
return null
static func save_json(path:String, data:Dictionary):
var f:File = File.new()
f.open(path, File.WRITE)
@ -126,23 +136,55 @@ static func get_whitespace_tail(t:String):
var length = len(t) - len(t.strip_edges(false, true))
return t.substr(len(t)-length)
static func dig(d, obj:Object, fname:String):
var f = funcref(obj, fname)
if d is Dictionary:
_dig_dict(d, f)
elif d is Node:
_dig_node(d, f)
const _dig = {depth=0}
static func _dig_dict(d:Dictionary, f:FuncRef):
static func get_dig_depth() -> int:
return _dig.depth
static func dig_for(d, property:String, value):
var depth:int = 0
if d is Dictionary:
return _dig_for_dict(d, property, value, depth)
# elif d is Node:
# return _dig_for_node(d, propert, value, depth)
return null
static func _dig_for_dict(d:Dictionary, property:String, value, depth:int):
_dig.depth = depth
if property in d and d[property] == value:
return d
for k in d:
if d[k] is Dictionary:
var got = _dig_for_dict(d[k], property, value, depth+1)
if got != null:
return got
return null
#static func _dig_for_node(d:Node, f:FuncRef, depth:int):
# _dig.depth = depth
# f.call_func(d)
# for i in d.get_child_count():
# _dig_node(d.get_child(i), f, depth+1)
static func dig(d, obj:Object, fname:String):
var f:FuncRef = funcref(obj, fname)
var depth:int = 0
if d is Dictionary:
_dig_dict(d, f, depth)
elif d is Node:
_dig_node(d, f, depth)
static func _dig_dict(d:Dictionary, f:FuncRef, depth:int):
_dig.depth = depth
f.call_func(d)
for k in d:
if d[k] is Dictionary:
_dig_dict(d[k], f)
_dig_dict(d[k], f, depth+1)
static func _dig_node(d:Node, f:FuncRef):
static func _dig_node(d:Node, f:FuncRef, depth:int):
_dig.depth = depth
f.call_func(d)
for i in d.get_child_count():
_dig_node(d.get_child(i), f)
_dig_node(d.get_child(i), f, depth+1)
static func file_size(path:String) -> String:
var f:File = File.new()

View File

@ -50,6 +50,8 @@ script = ExtResource( 2 )
__meta__ = {
"_edit_use_anchors_": false
}
p_console = NodePath("c/div1/div2/c/c/c/meta_tabs/console")
p_progress_bar = NodePath("c/c/c/progress")
[node name="file_editor" type="TextEdit" parent="."]
visible = false
@ -122,15 +124,35 @@ margin_right = 155.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_bottom = 24.0
text = "tab colors"
[node name="space" type="Control" parent="c/c/c"]
margin_left = 254.0
margin_right = 978.0
margin_bottom = 24.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="progress" type="ProgressBar" parent="c/c/c"]
visible = false
margin_left = 878.0
margin_right = 978.0
margin_bottom = 24.0
rect_min_size = Vector2( 100, 0 )
size_flags_vertical = 3
[node name="version" type="Label" parent="c/c/c"]
modulate = Color( 1, 1, 1, 0.521569 )
margin_left = 159.0
margin_left = 982.0
margin_top = 3.0
margin_right = 1010.0
margin_bottom = 20.0
size_flags_horizontal = 3
custom_fonts/font = ExtResource( 12 )
text = "v1.8"
text = "v1.9"
align = 2
[node name="div1" type="HSplitContainer" parent="c"]
@ -167,11 +189,12 @@ __meta__ = {
[node name="filter" type="LineEdit" parent="c/div1/c2/c/c"]
margin_right = 192.0
margin_bottom = 24.0
margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 )
clear_button_enabled = true
[node name="list_files" type="RichTextLabel" parent="c/div1/c2/c/c"]
margin_top = 28.0
margin_top = 31.0
margin_right = 192.0
margin_bottom = 548.0
size_flags_horizontal = 3
@ -230,13 +253,14 @@ margin_right = 614.0
margin_bottom = 562.0
size_flags_horizontal = 3
size_flags_vertical = 3
split_offset = -200
[node name="tab_container" type="TabContainer" parent="c/div1/div2/c/c"]
margin_right = 614.0
margin_bottom = 562.0
margin_bottom = 275.0
size_flags_horizontal = 3
size_flags_vertical = 3
custom_constants/top_margin = 0
custom_constants/side_margin = 0
custom_fonts/font = ExtResource( 12 )
tab_align = 0
drag_to_rearrange_enabled = true
@ -245,14 +269,25 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="meta_tabs" type="TabContainer" parent="c/div1/div2/c/c"]
visible = false
margin_top = 326.0
[node name="c" type="Control" parent="c/div1/div2/c/c"]
margin_top = 287.0
margin_right = 614.0
margin_bottom = 562.0
script = ExtResource( 16 )
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="console" type="RichTextLabel" parent="c/div1/div2/c/c/meta_tabs"]
[node name="meta_tabs" type="TabContainer" parent="c/div1/div2/c/c/c"]
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
script = ExtResource( 16 )
__meta__ = {
"_edit_use_anchors_": false
}
[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
@ -273,10 +308,11 @@ active: False
active: False
active: False
active: False
active: False
"
script = ExtResource( 1 )
[node name="meta" type="RichTextLabel" parent="c/div1/div2/c/c/meta_tabs"]
[node name="meta" type="RichTextLabel" parent="c/div1/div2/c/c/c/meta_tabs"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
@ -295,7 +331,7 @@ custom_fonts/normal_font = ExtResource( 12 )
bbcode_enabled = true
script = ExtResource( 9 )
[node name="search" type="VBoxContainer" parent="c/div1/div2/c/c/meta_tabs"]
[node name="search" type="VBoxContainer" parent="c/div1/div2/c/c/c/meta_tabs"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
@ -306,32 +342,32 @@ margin_bottom = -4.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="c" type="HBoxContainer" parent="c/div1/div2/c/c/meta_tabs/search"]
[node name="c" type="HBoxContainer" parent="c/div1/div2/c/c/c/meta_tabs/search"]
margin_right = 606.0
margin_bottom = 27.0
[node name="le" type="LineEdit" parent="c/div1/div2/c/c/meta_tabs/search/c"]
margin_right = 423.0
[node name="le" type="LineEdit" parent="c/div1/div2/c/c/c/meta_tabs/search/c"]
margin_right = 409.0
margin_bottom = 27.0
size_flags_horizontal = 3
custom_fonts/font = ExtResource( 12 )
[node name="all" type="CheckBox" parent="c/div1/div2/c/c/meta_tabs/search/c"]
margin_left = 427.0
margin_right = 501.0
[node name="all" type="CheckBox" parent="c/div1/div2/c/c/c/meta_tabs/search/c"]
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/meta_tabs/search/c"]
margin_left = 505.0
[node name="case" type="CheckBox" parent="c/div1/div2/c/c/c/meta_tabs/search/c"]
margin_left = 508.0
margin_right = 606.0
margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 )
text = "match case"
[node name="rte" type="RichTextLabel" parent="c/div1/div2/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_right = 606.0
margin_bottom = 231.0
@ -346,7 +382,7 @@ bbcode_enabled = true
meta_underlined = false
script = ExtResource( 15 )
[node name="sys" type="VBoxContainer" parent="c/div1/div2/c/c/meta_tabs"]
[node name="sys" type="VBoxContainer" parent="c/div1/div2/c/c/c/meta_tabs"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
@ -355,17 +391,17 @@ margin_top = 32.0
margin_right = -4.0
margin_bottom = -4.0
[node name="update" type="Button" parent="c/div1/div2/c/c/meta_tabs/sys"]
[node name="update" type="Button" parent="c/div1/div2/c/c/c/meta_tabs/sys"]
margin_right = 606.0
margin_bottom = 28.0
margin_bottom = 23.0
size_flags_horizontal = 3
custom_fonts/font = ExtResource( 12 )
text = "⟳"
[node name="sys" type="RichTextLabel" parent="c/div1/div2/c/c/meta_tabs/sys"]
margin_top = 32.0
[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 = 232.0
margin_bottom = 227.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 13 )
@ -379,6 +415,22 @@ meta_underlined = false
text = "idwords ⯆unique"
script = ExtResource( 17 )
[node name="image" type="VBoxContainer" parent="c/div1/div2/c/c/c/meta_tabs"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 32.0
margin_right = -4.0
margin_bottom = -4.0
[node name="image" type="TextureRect" parent="c/div1/div2/c/c/c/meta_tabs/image"]
margin_right = 606.0
margin_bottom = 239.0
size_flags_horizontal = 3
size_flags_vertical = 3
expand = true
stretch_mode = 6
[node name="c2" type="PanelContainer" parent="c/div1/div2"]
margin_left = 626.0
margin_right = 806.0
@ -411,11 +463,12 @@ __meta__ = {
[node name="filter" type="LineEdit" parent="c/div1/div2/c2/c/c/c"]
margin_right = 166.0
margin_bottom = 24.0
margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 )
clear_button_enabled = true
[node name="list_symbols" type="RichTextLabel" parent="c/div1/div2/c2/c/c/c"]
margin_top = 28.0
margin_top = 31.0
margin_right = 166.0
margin_bottom = 448.0
size_flags_vertical = 3

View File

@ -68,6 +68,23 @@ func get_symbols(t:String) -> Dictionary:
symbols = {}
return symbols
#func get_symbol_names(s:Dictionary):
# var out = []
# for k in s:
# if k != -1:
# out.append(s[k].name)
# return out
func get_tag_counts(s:Dictionary) -> Dictionary:
var out = {}
for k in s:
for tag in s[k].tags:
if not tag in out:
out[tag] = 1
else:
out[tag] += 1
return out
func apply_colors(e, t:TextEdit):
t.add_color_override("font_color", e.color_text)
t.add_color_override("number_color", e.color_var)

View File

@ -124,7 +124,7 @@ func toggle_comment(t:TextEdit, head:String="<!-- ", tail:String=" -->"):
func apply_colors(e:TE_Editor, t:TextEdit):
.apply_colors(e, t)
var code:Color = TE_Util.hue_shift(e.color_var, .33)#.darkened(.25)
var code:Color = lerp(Color.white.darkened(.5), Color.deepskyblue, .333)
var quote:Color = lerp(e.color_text, e.color_symbol, .5)
t.add_color_override("function_color", e.color_text)
@ -187,8 +187,6 @@ func apply_colors(e:TE_Editor, t:TextEdit):
# tables
t.add_color_region("|", "", Color.tan, true)
func get_symbols(t:String) -> Dictionary:
var out = .get_symbols(t)
@ -213,6 +211,12 @@ func get_symbols(t:String) -> Dictionary:
i += 1
# i += 1
elif lines[i].begins_with("```") or lines[i].begins_with("~~~"):
var head = lines[i].substr(0, 3)
i += 1
while i < len(lines) and not lines[i].begins_with(head):
i += 1
# symbols
elif lines[i].begins_with("#"):
var p = lines[i].split(" ", true, 1)

View File

@ -0,0 +1,2 @@
tool
extends TE_ExtensionHelper

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon_blue.png-4b6f1e67dbe59cc990b970ce70a743ca.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/text_editor/icons/icon_blue.png"
dest_files=[ "res://.import/icon_blue.png-4b6f1e67dbe59cc990b970ce70a743ca.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon_green.png-01008ffea524815bdbefdafa2b021148.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/text_editor/icons/icon_green.png"
dest_files=[ "res://.import/icon_green.png-01008ffea524815bdbefdafa2b021148.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon_red.png-68ce187cb535e9b040383f41e156a86c.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/text_editor/icons/icon_red.png"
dest_files=[ "res://.import/icon_red.png-68ce187cb535e9b040383f41e156a86c.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon_yellow.png-4fd0044497c78a10c7a9305f6c12f846.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/text_editor/icons/icon_yellow.png"
dest_files=[ "res://.import/icon_yellow.png-4fd0044497c78a10c7a9305f6c12f846.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View File

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