mirror of
https://github.com/Relintai/Godot-TextEditor.git
synced 2025-01-26 16:59:19 +01:00
1.9
This commit is contained in:
parent
498fb79e89
commit
40beef4690
13
CHANGES.md
13
CHANGES.md
@ -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.
|
||||
|
@ -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 |
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
2
addons/text_editor/ext/ext_txt.gd
Normal file
2
addons/text_editor/ext/ext_txt.gd
Normal file
@ -0,0 +1,2 @@
|
||||
tool
|
||||
extends TE_ExtensionHelper
|
BIN
addons/text_editor/icons/icon_blue.png
Normal file
BIN
addons/text_editor/icons/icon_blue.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 478 B |
35
addons/text_editor/icons/icon_blue.png.import
Normal file
35
addons/text_editor/icons/icon_blue.png.import
Normal 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
|
BIN
addons/text_editor/icons/icon_green.png
Normal file
BIN
addons/text_editor/icons/icon_green.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 478 B |
35
addons/text_editor/icons/icon_green.png.import
Normal file
35
addons/text_editor/icons/icon_green.png.import
Normal 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
|
BIN
addons/text_editor/icons/icon_red.png
Normal file
BIN
addons/text_editor/icons/icon_red.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 478 B |
35
addons/text_editor/icons/icon_red.png.import
Normal file
35
addons/text_editor/icons/icon_red.png.import
Normal 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
|
BIN
addons/text_editor/icons/icon_yellow.png
Normal file
BIN
addons/text_editor/icons/icon_yellow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 478 B |
35
addons/text_editor/icons/icon_yellow.png.import
Normal file
35
addons/text_editor/icons/icon_yellow.png.import
Normal 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
|
@ -3,5 +3,5 @@
|
||||
name="TextEditor"
|
||||
description="A text editor for Godot."
|
||||
author="teebar"
|
||||
version="1.8"
|
||||
version="1.9"
|
||||
script="plugin.gd"
|
||||
|
Loading…
Reference in New Issue
Block a user