mirror of
https://github.com/Relintai/Godot-TextEditor.git
synced 2025-02-04 19:15:54 +01:00
1.4
This commit is contained in:
parent
ba5e9148cb
commit
8fd5a31874
14
CHANGES.md
14
CHANGES.md
@ -1,3 +1,16 @@
|
||||
# 1.4
|
||||
- Added `sys` info tab.
|
||||
- Added `console` info tab. (wip)
|
||||
- Changing extension updates colors.
|
||||
- Fixed exported build not styling things properly.
|
||||
- Fixed symbols/tags not showing when first booting editor.
|
||||
- Tweaked colors.
|
||||
- Internal rewriting.
|
||||
|
||||
# 1.3
|
||||
- Basic search implemented. `Ctrl + F`
|
||||
- Can create links inside `()` which makes markdown links clickable.: `Ctrl + Click`
|
||||
|
||||
# 1.2
|
||||
- Can unrecycle now. (Make sure `view/Directories/.trash` is toggled, then press arrow.
|
||||
- Added folder recycle option
|
||||
@ -7,6 +20,7 @@
|
||||
- Settings are saved more frequently.
|
||||
- Fixed file dragging.
|
||||
- Fixed meta table not resizing.
|
||||
- Tweaked symbol colorizer to emphasize depth.
|
||||
- Bug fixes.
|
||||
|
||||
# 1.1
|
||||
|
@ -58,7 +58,8 @@ This will then highlight *Files* and *Symbols* that have that tag.
|
||||
|
||||
# Todo
|
||||
- [x] `1.1` Preserve folders open/close state.
|
||||
- [ ] Search.
|
||||
- [x] `1.3` Search all files.
|
||||
- [ ] Search file.
|
||||
- [ ] Find and replace.
|
||||
- [ ] Improve meta data based on format.
|
||||
- [x] `1.2` Recycle folders.
|
||||
|
13
addons/text_editor/TE_Console.gd
Normal file
13
addons/text_editor/TE_Console.gd
Normal file
@ -0,0 +1,13 @@
|
||||
extends "res://addons/text_editor/TE_RichTextLabel.gd"
|
||||
|
||||
func msg(msg):
|
||||
append_bbcode(str(msg))
|
||||
newline()
|
||||
|
||||
func err(err):
|
||||
append_bbcode(clr(err, Color.tomato))
|
||||
newline()
|
||||
|
||||
func info(info):
|
||||
append_bbcode(clr(info, Color.aquamarine))
|
||||
newline()
|
@ -1,7 +1,7 @@
|
||||
tool
|
||||
extends RichTextLabel
|
||||
|
||||
var editor:TextEditor
|
||||
var editor:TE_TextEditor
|
||||
var click_pos:Vector2
|
||||
|
||||
func _init(text):
|
||||
|
@ -1,7 +1,7 @@
|
||||
tool
|
||||
extends TextEdit
|
||||
|
||||
var editor:TextEditor
|
||||
var editor:TE_TextEditor
|
||||
var _hscroll:HScrollBar
|
||||
var _vscroll:VScrollBar
|
||||
|
||||
@ -82,6 +82,7 @@ func _file_renamed(old_path:String, new_path:String):
|
||||
if old_path == file_path:
|
||||
file_path = new_path
|
||||
update_name()
|
||||
update_colors()
|
||||
|
||||
func _input(e):
|
||||
if not editor.is_plugin_active():
|
||||
@ -90,6 +91,22 @@ func _input(e):
|
||||
if not visible or not in_focus:
|
||||
return
|
||||
|
||||
if e is InputEventMouseButton and not e.pressed and e.control:
|
||||
var line:String = get_line(cursor_get_line())
|
||||
var ca = line.find("(")
|
||||
var cb = line.find_last(")")
|
||||
if ca != -1 and cb != -1:
|
||||
var a:int = cursor_get_column()
|
||||
var b:int = cursor_get_column()
|
||||
if ca < a and cb >= b:
|
||||
while a > 0 and not line[a] in "(": a -= 1
|
||||
while b <= len(line) and not line[b] in ")": b += 1
|
||||
var file = line.substr(a+1, b-a-1)
|
||||
var link = file_path.get_base_dir().plus_file(file)
|
||||
editor.open_file(link)
|
||||
editor.select_file(link)
|
||||
# print(link)
|
||||
|
||||
if e is InputEventKey and e.pressed and e.control:
|
||||
# tab to next
|
||||
if e.scancode == KEY_TAB:
|
||||
@ -172,6 +189,11 @@ func _file_selected(p:String):
|
||||
update_symbols()
|
||||
update_heading()
|
||||
|
||||
func goto_line(line:int):
|
||||
# force scroll to bottom so selected line will be at top
|
||||
cursor_set_line(get_line_count())
|
||||
cursor_set_line(line)
|
||||
|
||||
func text_changed():
|
||||
if last_selected:
|
||||
match last_key:
|
||||
@ -241,17 +263,19 @@ func load_file(path:String):
|
||||
file_path = path
|
||||
text = TE_Util.load_text(path)
|
||||
update_name()
|
||||
update_colors()
|
||||
|
||||
# update colors
|
||||
func update_colors():
|
||||
clear_colors()
|
||||
|
||||
helper = TextEditor.get_extension_helper(file_path)
|
||||
helper = editor.get_extension_helper(file_path)
|
||||
helper.apply_colors(editor, self)
|
||||
|
||||
func save_file():
|
||||
if modified:
|
||||
if not file_path.begins_with("res://"):
|
||||
push_error("can't save to %s" % file_path)
|
||||
if not file_path.begins_with(editor.current_directory):
|
||||
var err_msg = "can't save to %s" % file_path
|
||||
push_error(err_msg)
|
||||
editor.console.err(err_msg)
|
||||
return
|
||||
|
||||
modified = false
|
||||
|
@ -1,12 +1,17 @@
|
||||
extends TabContainer
|
||||
|
||||
onready var editor:TextEditor = owner
|
||||
onready var editor:TE_TextEditor = owner
|
||||
var mouse:bool = false
|
||||
|
||||
func _ready():
|
||||
if not editor.is_plugin_active():
|
||||
return
|
||||
|
||||
var _e
|
||||
_e = connect("mouse_entered", self, "set", ["mouse", true])
|
||||
_e = connect("mouse_exited", self, "set", ["mouse", false])
|
||||
|
||||
add_font_override("font", editor.FONT_R)
|
||||
|
||||
func _input(e):
|
||||
if not editor.is_plugin_active():
|
||||
|
@ -1,21 +1,16 @@
|
||||
tool
|
||||
extends RichTextLabel
|
||||
extends "res://addons/text_editor/TE_RichTextLabel.gd"
|
||||
|
||||
onready var editor:TextEditor = owner
|
||||
onready var file_popup:PopupMenu = $file_popup
|
||||
onready var dir_popup:PopupMenu = $dir_popup
|
||||
|
||||
const DragLabel = preload("res://addons/text_editor/TE_DragLabel.gd")
|
||||
var drag_label:RichTextLabel
|
||||
|
||||
var files:Array = []
|
||||
var dirs:Array = []
|
||||
var selected
|
||||
var hovered:String = ""
|
||||
var dragging:String = ""
|
||||
var selected:Array = []
|
||||
var dragging:Array = []
|
||||
var drag_start:Vector2
|
||||
|
||||
|
||||
func _ready():
|
||||
var _e
|
||||
_e = editor.connect("updated_file_list", self, "_redraw")
|
||||
@ -24,12 +19,6 @@ func _ready():
|
||||
_e = editor.connect("file_closed", self, "_file_closed")
|
||||
_e = editor.connect("file_selected", self, "_file_selected")
|
||||
_e = editor.connect("file_renamed", self, "_file_renamed")
|
||||
_e = connect("meta_hover_started", self, "_meta_entered")
|
||||
_e = connect("meta_hover_ended", self, "_meta_exited")
|
||||
|
||||
# hint
|
||||
theme = Theme.new()
|
||||
theme.set_font("font", "TooltipLabel", editor.FONT_R)
|
||||
|
||||
# file popup
|
||||
file_popup.clear()
|
||||
@ -38,7 +27,7 @@ func _ready():
|
||||
file_popup.add_separator()
|
||||
file_popup.add_item("Remove")
|
||||
_e = file_popup.connect("index_pressed", self, "_file_popup")
|
||||
file_popup.add_font_override("font", TextEditor.FONT)
|
||||
file_popup.add_font_override("font", editor.FONT)
|
||||
|
||||
# dir popup
|
||||
dir_popup.clear()
|
||||
@ -48,7 +37,7 @@ func _ready():
|
||||
dir_popup.add_separator()
|
||||
dir_popup.add_item("Remove")
|
||||
_e = dir_popup.connect("index_pressed", self, "_dir_popup")
|
||||
dir_popup.add_font_override("font", TextEditor.FONT)
|
||||
dir_popup.add_font_override("font", editor.FONT)
|
||||
|
||||
add_font_override("normal_font", editor.FONT_R)
|
||||
add_font_override("bold_font", editor.FONT_B)
|
||||
@ -56,9 +45,10 @@ func _ready():
|
||||
add_font_override("bold_italics_font", editor.FONT_BI)
|
||||
|
||||
func _dir_popup(index:int):
|
||||
var p = _meta_to_file(selected)
|
||||
var type = p[0]
|
||||
var file = p[1]
|
||||
var type = selected[0]
|
||||
var file = selected[1]
|
||||
if type == "d":
|
||||
file = file.file_path
|
||||
|
||||
match dir_popup.get_item_text(index):
|
||||
"New File": editor.popup_create_file(file)
|
||||
@ -66,9 +56,10 @@ func _dir_popup(index:int):
|
||||
"Remove": editor.recycle(file)
|
||||
|
||||
func _file_popup(index:int):
|
||||
var p = _meta_to_file(selected)
|
||||
var type = p[0]
|
||||
var file = p[1]
|
||||
var type = selected[0]
|
||||
var file = selected[1]
|
||||
if type == "d":
|
||||
file = file.file_path
|
||||
|
||||
match file_popup.get_item_text(index):
|
||||
"Rename":
|
||||
@ -82,62 +73,61 @@ func _file_popup(index:int):
|
||||
editor.recycle(file)
|
||||
|
||||
_:
|
||||
selected = {}
|
||||
selected = []
|
||||
|
||||
func _renamed(new_file:String):
|
||||
var p = _meta_to_file(selected)
|
||||
var type = p[0]
|
||||
var file = p[1]
|
||||
var type = selected[0]
|
||||
var file = selected[1]
|
||||
|
||||
var old_path:String = file
|
||||
var old_file:String = old_path.get_file()
|
||||
if new_file != old_file:
|
||||
var new_path:String = old_path.get_base_dir().plus_file(new_file)
|
||||
editor.rename_file(old_path, new_path)
|
||||
selected = {}
|
||||
selected = []
|
||||
|
||||
func _input(e:InputEvent):
|
||||
if not editor.is_plugin_active():
|
||||
return
|
||||
|
||||
if e is InputEventMouseButton and hovered:
|
||||
var p = _meta_to_file(hovered)
|
||||
var type = p[0]
|
||||
var file = p[1]
|
||||
if e is InputEventMouseButton and meta_hovered:
|
||||
var type = meta_hovered[0]
|
||||
var file = meta_hovered[1]
|
||||
|
||||
if e.button_index == BUTTON_LEFT:
|
||||
|
||||
if e.pressed:
|
||||
if type in ["f", "d"]:
|
||||
if file.begins_with(editor.PATH_TRASH):
|
||||
var file_path = file if type == "f" else file.file_path
|
||||
|
||||
if file_path.begins_with(editor.PATH_TRASH):
|
||||
return # can't move recycling
|
||||
|
||||
else:
|
||||
dragging = hovered
|
||||
dragging = meta_hovered
|
||||
|
||||
drag_label = DragLabel.new(file.get_file())
|
||||
drag_label = DragLabel.new(file_path.get_file())
|
||||
drag_label.editor = editor
|
||||
editor.add_child(drag_label)
|
||||
|
||||
else:
|
||||
if dragging and dragging != hovered:
|
||||
var p2 = _meta_to_file(dragging)
|
||||
var drag_type = p2[0]
|
||||
var drag_file = p2[1]
|
||||
if dragging and dragging != meta_hovered:
|
||||
var drag_type = dragging[0]
|
||||
var drag_file = dragging[1]
|
||||
|
||||
if type == "d":
|
||||
var dir:String = file
|
||||
var dir:String = file.file_path
|
||||
var old_path:String = drag_file
|
||||
var new_path:String = dir.plus_file(old_path.get_file())
|
||||
editor.rename_file(old_path, new_path)
|
||||
|
||||
dragging = ""
|
||||
dragging = []
|
||||
|
||||
else:
|
||||
match type:
|
||||
# toggle directory
|
||||
"d":
|
||||
p[2].open = not p[2].open
|
||||
file.open = not file.open
|
||||
_redraw()
|
||||
|
||||
# unrecycle
|
||||
@ -152,7 +142,7 @@ func _input(e:InputEvent):
|
||||
|
||||
elif e.button_index == BUTTON_RIGHT:
|
||||
if e.pressed:
|
||||
selected = hovered
|
||||
selected = meta_hovered
|
||||
match type:
|
||||
"d":
|
||||
dir_popup.set_global_position(get_global_mouse_position())
|
||||
@ -163,27 +153,6 @@ func _input(e:InputEvent):
|
||||
file_popup.popup()
|
||||
get_tree().set_input_as_handled()
|
||||
|
||||
func _meta_to_file(m:String):
|
||||
var p = m.split(":", true, 1)
|
||||
var type = p[0]
|
||||
var index = int(p[1])
|
||||
match type:
|
||||
"d", "unrecycle":
|
||||
return [type, dirs[index].file_path, dirs[index]]
|
||||
"f":
|
||||
return [type, files[index]]
|
||||
|
||||
func _meta_entered(m):
|
||||
hovered = m
|
||||
var f = _meta_to_file(m)
|
||||
match f[0]:
|
||||
"f", "d": hint_tooltip = f[1]
|
||||
"unrecycle": hint_tooltip = "Unrecycle %s" % f[1]
|
||||
|
||||
func _meta_exited(_m):
|
||||
hovered = ""
|
||||
hint_tooltip = ""
|
||||
|
||||
func _file_opened(_file_path:String): _redraw()
|
||||
func _file_closed(_file_path:String): _redraw()
|
||||
func _file_selected(_file_path:String): _redraw()
|
||||
@ -193,16 +162,9 @@ var lines:PoolStringArray = PoolStringArray()
|
||||
|
||||
func _redraw():
|
||||
lines = PoolStringArray()
|
||||
dirs.clear()
|
||||
files.clear()
|
||||
_draw_dir(editor.file_list[""], 0)
|
||||
set_bbcode(lines.join("\n"))
|
||||
|
||||
func clr(s:String, c:Color) -> String: return "[color=#%s]%s[/color]" % [c.to_html(), s]
|
||||
func i(s:String) -> String: return "[i]%s[/i]" % s
|
||||
func b(s:String) -> String: return "[b]%s[/b]" % s
|
||||
func url(s:String, url:String) -> String: return "[url=%s]%s[/url]" % [url, s]
|
||||
|
||||
const FOLDER:String = "🗀" # not visible in godot
|
||||
func _draw_dir(dir:Dictionary, deep:int):
|
||||
var is_tagging = editor.is_tagging()
|
||||
@ -210,14 +172,13 @@ func _draw_dir(dir:Dictionary, deep:int):
|
||||
|
||||
var space = clr("┃ ".repeat(deep), Color.white.darkened(.8))
|
||||
var file:String = dir.file_path
|
||||
var name:String = b(file.get_file())
|
||||
var head:String = "▼" if dir.open else "▶"
|
||||
var dir_index:int = len(dirs)
|
||||
var link:String = url(space+clr(FOLDER+head, Color.white.darkened(.5))+" "+name, "d:%s" % dir_index)
|
||||
head = clr(space+FOLDER+head, Color.white.darkened(.5))
|
||||
head += " " + b(file.get_file())
|
||||
var link:String = meta(head, ["d", dir], file)
|
||||
if file.begins_with(editor.PATH_TRASH) and file.count("/") == 3:
|
||||
link += " " + url(clr("⬅", Color.yellowgreen), "unrecycle:%s" % dir_index)
|
||||
link += " " + meta(clr("⬅", Color.yellowgreen), ["unrecycle", dir], file)
|
||||
lines.append(clr(link, Color.white.darkened(dimmest)))
|
||||
dirs.append(dir)
|
||||
|
||||
var sel = editor.get_selected_tab()
|
||||
sel = sel.file_path if sel else ""
|
||||
@ -266,5 +227,4 @@ func _draw_dir(dir:Dictionary, deep:int):
|
||||
file = clr(file, color)
|
||||
ext = clr("." + ext, Color.white.darkened(.65))
|
||||
var line = space + head + file + ext
|
||||
lines.append(url(line, "f:%s" % len(files)))
|
||||
files.append(file_path)
|
||||
lines.append(meta(line, ["f", file_path], file_path))
|
||||
|
@ -1,7 +1,7 @@
|
||||
tool
|
||||
extends LineEdit
|
||||
|
||||
onready var editor:TextEditor = owner
|
||||
onready var editor:TE_TextEditor = owner
|
||||
var fr:FuncRef
|
||||
|
||||
func _ready():
|
||||
@ -9,16 +9,20 @@ func _ready():
|
||||
_e = connect("text_entered", self, "_enter")
|
||||
_e = connect("focus_exited", self, "_lost_focus")
|
||||
|
||||
add_font_override("font", TextEditor.FONT_R)
|
||||
add_font_override("font", editor.FONT_R)
|
||||
|
||||
func _unhandled_key_input(e):
|
||||
if e.scancode == KEY_ESCAPE and e.pressed:
|
||||
if not editor.is_plugin_active():
|
||||
return
|
||||
|
||||
if visible and e.scancode == KEY_ESCAPE and e.pressed:
|
||||
fr = null
|
||||
hide()
|
||||
get_tree().set_input_as_handled()
|
||||
|
||||
func display(t:String, obj:Object, fname:String):
|
||||
text = t
|
||||
select_all()
|
||||
fr = funcref(obj, fname)
|
||||
show()
|
||||
call_deferred("grab_focus")
|
||||
@ -28,5 +32,7 @@ func _lost_focus():
|
||||
hide()
|
||||
|
||||
func _enter(t:String):
|
||||
fr.call_func(t)
|
||||
if fr:
|
||||
print("calling %s with %s" % [fr, t])
|
||||
fr.call_func(t)
|
||||
hide()
|
||||
|
@ -1,20 +1,13 @@
|
||||
tool
|
||||
extends TE_RichTextLabel
|
||||
|
||||
onready var editor:TextEditor = owner
|
||||
extends "res://addons/text_editor/TE_RichTextLabel.gd"
|
||||
|
||||
func _ready():
|
||||
var _e
|
||||
_e = editor.connect("file_selected", self, "_file_selected")
|
||||
_e = editor.connect("file_saved", self, "_file_saved")
|
||||
_e = connect("resized", self, "_resized")
|
||||
|
||||
func _resized():
|
||||
add_constant_override("table_hseparation", int(rect_size.x / 6.0))
|
||||
|
||||
func _unhandled_key_input(e):
|
||||
if e.scancode == KEY_M and e.pressed:
|
||||
visible = not visible
|
||||
#func _resized():
|
||||
# add_constant_override("table_hseparation", int(rect_size.x / 6.0))
|
||||
|
||||
func _file_selected(_file_path:String):
|
||||
yield(get_tree(), "idle_frame")
|
||||
|
19
addons/text_editor/TE_MetaTabs.gd
Normal file
19
addons/text_editor/TE_MetaTabs.gd
Normal file
@ -0,0 +1,19 @@
|
||||
tool
|
||||
extends TabContainer
|
||||
|
||||
onready var editor:TE_TextEditor = owner
|
||||
|
||||
func _ready():
|
||||
if not editor.is_plugin_active():
|
||||
return
|
||||
|
||||
add_font_override("font", editor.FONT_R)
|
||||
|
||||
func _unhandled_key_input(e):
|
||||
if not editor.is_plugin_active():
|
||||
return
|
||||
|
||||
# Ctrl + M = meta tabs
|
||||
if e.scancode == KEY_M and e.control and e.pressed:
|
||||
visible = not visible
|
||||
get_tree().set_input_as_handled()
|
@ -1,12 +1,87 @@
|
||||
extends RichTextLabel
|
||||
class_name TE_RichTextLabel
|
||||
|
||||
onready var editor:TE_TextEditor = owner
|
||||
|
||||
var meta_items:Array = []
|
||||
var meta_hovered:Array = []
|
||||
|
||||
class Table:
|
||||
var table_id:String
|
||||
var heading:Array = []
|
||||
var columns:Array = []
|
||||
var _sort_index:int
|
||||
var _sort_reverse:bool
|
||||
|
||||
func _init(id:String):
|
||||
table_id = id
|
||||
|
||||
func sort(index:int, reverse:bool):
|
||||
_sort_index = index
|
||||
_sort_reverse = reverse
|
||||
columns.sort_custom(self, "_sort")
|
||||
|
||||
func output(rte:RichTextLabel):
|
||||
rte.push_table(len(heading))
|
||||
for i in len(heading):
|
||||
rte.push_cell()
|
||||
rte.push_bold()
|
||||
rte.push_meta("table|%s|%s" % [table_id, i])
|
||||
rte.add_text(heading[i])
|
||||
rte.pop()
|
||||
rte.pop()
|
||||
rte.pop()
|
||||
for i in len(columns):
|
||||
rte.push_cell()
|
||||
rte.add_text(str(columns[i]))
|
||||
rte.pop()
|
||||
rte.pop()
|
||||
|
||||
class RTE:
|
||||
var rte
|
||||
var s:String
|
||||
|
||||
func start(st:String):
|
||||
s = st
|
||||
return self
|
||||
|
||||
func clr(c:Color):
|
||||
s = "[color=#%s]%s[/color]" % [c.to_html(), s]
|
||||
return self
|
||||
|
||||
func meta(type:String, meta, args=null):
|
||||
var index:int = len(rte.meta_items)
|
||||
rte.meta_items.append(meta)
|
||||
s = "[url=%s|%s]%s[/url]" % [type, index, s]
|
||||
return self
|
||||
|
||||
func out():
|
||||
rte.append_bbcode(s)
|
||||
|
||||
func _ready():
|
||||
# hint
|
||||
theme = Theme.new()
|
||||
theme.set_font("font", "TooltipLabel", editor.FONT_R)
|
||||
|
||||
add_font_override("normal_font", owner.FONT_R)
|
||||
add_font_override("bold_font", owner.FONT_B)
|
||||
add_font_override("italics_font", owner.FONT_I)
|
||||
add_font_override("bold_italics_font", owner.FONT_BI)
|
||||
|
||||
var _e
|
||||
_e = connect("resized", self, "_resized")
|
||||
_e = connect("meta_clicked", self, "_meta_clicked")
|
||||
_e = connect("meta_hover_started", self, "_meta_hover_started")
|
||||
_e = connect("meta_hover_ended", self, "_meta_hover_ended")
|
||||
|
||||
func _resized():
|
||||
pass
|
||||
|
||||
func _clicked(_data):
|
||||
pass
|
||||
|
||||
func clear():
|
||||
.clear()
|
||||
meta_items.clear()
|
||||
|
||||
func table(rows) -> String:
|
||||
var cells = ""
|
||||
@ -19,3 +94,33 @@ func table(rows) -> String:
|
||||
for item in rows[i]:
|
||||
cells += "[cell][color=#%s]%s[/color][/cell]" % [clr, item]
|
||||
return "[center][table=%s]%s[/table][/center]" % [len(rows[0]), cells]
|
||||
|
||||
func b(t:String) -> String: return "[b]%s[/b]" % t
|
||||
func i(t:String) -> String: return "[i]%s[/i]" % t
|
||||
func clr(t:String, c:Color) -> String: return "[color=#%s]%s[/color]" % [c.to_html(), t]
|
||||
func center(t:String): return "[center]%s[/center]" % t
|
||||
|
||||
func _meta_hover_started(meta):
|
||||
var info = meta_items[int(meta)]
|
||||
var hint = info[1]
|
||||
meta_hovered = info[0]
|
||||
if hint:
|
||||
hint_tooltip = hint
|
||||
|
||||
func _meta_hover_ended(_meta):
|
||||
meta_hovered = []
|
||||
hint_tooltip = ""
|
||||
|
||||
func _meta_clicked(meta):
|
||||
var info = meta_items[int(meta)]
|
||||
if info[0]:
|
||||
_clicked(info[0])
|
||||
|
||||
func add_meta(args:Array, hint:String) -> int:
|
||||
var index:int = len(meta_items)
|
||||
meta_items.append([args, hint])
|
||||
return index
|
||||
|
||||
func meta(t:String, args:Array=[], hint:String="") -> String:
|
||||
var index:int = add_meta(args, hint)
|
||||
return "[url=%s]%s[/url]" % [index, t]
|
||||
|
151
addons/text_editor/TE_ScriptInfo.gd
Normal file
151
addons/text_editor/TE_ScriptInfo.gd
Normal file
@ -0,0 +1,151 @@
|
||||
tool
|
||||
extends "res://addons/text_editor/TE_RichTextLabel.gd"
|
||||
|
||||
var chapter_info:Array = []
|
||||
var sort_on:String = "words"
|
||||
var sort_reverse:Dictionary = { id=false, words=false, unique=false }
|
||||
|
||||
func _ready():
|
||||
var _e
|
||||
_e = editor.connect("file_opened", self, "_update")
|
||||
_e = editor.connect("file_saved", self, "_update")
|
||||
|
||||
func _update(f):
|
||||
set_process(true)
|
||||
|
||||
func _process(_delta):
|
||||
chapter_info.clear()
|
||||
|
||||
for path in editor.file_paths:
|
||||
var file = path.get_file()
|
||||
var ext = file.get_extension()
|
||||
match ext:
|
||||
"md": _process_md(path)
|
||||
|
||||
_sort()
|
||||
_redraw()
|
||||
|
||||
set_process(false)
|
||||
|
||||
func _chapter(path:String, line:int, id:String):
|
||||
chapter_info.append({ path=path, line=line, id=id, words=0, chars=0, unique=0 })
|
||||
|
||||
func _process_md(path:String):
|
||||
var lines = TE_Util.load_text(path).split("\n")
|
||||
_chapter(path, 0, "NOH")
|
||||
var i = 0
|
||||
while i < len(lines):
|
||||
# skip head meta
|
||||
if i == 0 and lines[i].begins_with("---"):
|
||||
i += 1
|
||||
while i < len(lines) and not lines[i].begins_with("---"):
|
||||
i += 1
|
||||
|
||||
# skip code blocks
|
||||
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
|
||||
|
||||
# heading
|
||||
elif lines[i].begins_with("#"):
|
||||
var p = lines[i].split(" ", true, 1)
|
||||
var id = lines[i].split(" ", true, 1)[1].strip_edges()
|
||||
_chapter(path, i, id)
|
||||
|
||||
else:
|
||||
var words = lines[i].split(" ", false)
|
||||
var unique = []
|
||||
for word in words:
|
||||
var w = clean_word(word.to_lower())
|
||||
if w and not w in unique:
|
||||
unique.append(w)
|
||||
|
||||
chapter_info[-1].words += len(words)
|
||||
chapter_info[-1].unique += len(unique)
|
||||
|
||||
i += 1
|
||||
|
||||
func clean_word(w:String):
|
||||
var out = ""
|
||||
for c in w:
|
||||
if c in "abcdefghijklmnopqrstuvwxyz":
|
||||
out += c
|
||||
return out
|
||||
|
||||
func _clicked(args):
|
||||
match args[0]:
|
||||
"sort_table":
|
||||
var key = args[1]
|
||||
if sort_on != key:
|
||||
sort_on = key
|
||||
else:
|
||||
sort_reverse[key] = not sort_reverse[key]
|
||||
|
||||
_sort()
|
||||
_redraw()
|
||||
|
||||
"goto":
|
||||
print(args)
|
||||
var tab = editor.open_file(args[1])
|
||||
editor.select_file(args[1])
|
||||
tab.goto_line(args[2])
|
||||
|
||||
func _sort():
|
||||
if sort_reverse[sort_on]:
|
||||
chapter_info.sort_custom(self, "_sort_chapters")
|
||||
else:
|
||||
chapter_info.sort_custom(self, "_sort_chapters_r")
|
||||
|
||||
func _sort_chapters(a, b): return a[sort_on] < b[sort_on]
|
||||
func _sort_chapters_r(a, b): return a[sort_on] >= b[sort_on]
|
||||
|
||||
func _redraw():
|
||||
clear()
|
||||
|
||||
var c1 = Color.white.darkened(.4)
|
||||
var c2 = Color.white.darkened(.3)
|
||||
|
||||
push_align(RichTextLabel.ALIGN_CENTER)
|
||||
push_table(3)
|
||||
for id in ["id", "words", "unique"]:
|
||||
push_cell()
|
||||
push_bold()
|
||||
push_meta(add_meta(["sort_table", id], "sort on %s" % id))
|
||||
add_text(id)
|
||||
if sort_on == id:
|
||||
push_color(Color.white.darkened(.5))
|
||||
add_text(" ⯅" if sort_reverse[id] else " ⯆")
|
||||
pop()
|
||||
pop()
|
||||
pop()
|
||||
pop()
|
||||
|
||||
for i in len(chapter_info):
|
||||
var item = chapter_info[i]
|
||||
|
||||
if item.id == "NOH" and not item.words:
|
||||
continue
|
||||
|
||||
var clr = c1 if i%2==0 else c2
|
||||
|
||||
# id
|
||||
push_cell()
|
||||
push_color(clr)
|
||||
push_meta(add_meta(["goto", item.path, item.line], item.path))
|
||||
add_text(item.id)
|
||||
pop()
|
||||
pop()
|
||||
pop()
|
||||
|
||||
# word cound
|
||||
for w in ["words", "unique"]:
|
||||
push_cell()
|
||||
push_color(clr)
|
||||
add_text(TE_Util.commas(item[w]))
|
||||
pop()
|
||||
pop()
|
||||
|
||||
pop()
|
||||
pop()
|
104
addons/text_editor/TE_Search.gd
Normal file
104
addons/text_editor/TE_Search.gd
Normal file
@ -0,0 +1,104 @@
|
||||
tool
|
||||
extends "res://addons/text_editor/TE_RichTextLabel.gd"
|
||||
|
||||
onready var line_edit:LineEdit = get_parent().get_node("le")
|
||||
|
||||
var console_urls:Array = []
|
||||
var last_search:String = ""
|
||||
|
||||
func _ready():
|
||||
var _e
|
||||
_e = line_edit.connect("text_entered", self, "_text_entered")
|
||||
|
||||
line_edit.add_font_override("font", editor.FONT_R)
|
||||
|
||||
func _unhandled_key_input(e):
|
||||
if not editor.is_plugin_active():
|
||||
return
|
||||
|
||||
# Ctrl + F to search
|
||||
if e.scancode == KEY_F and e.pressed and e.control:
|
||||
line_edit.grab_focus()
|
||||
line_edit.grab_click_focus()
|
||||
get_parent().get_parent().show()
|
||||
get_parent().get_parent().current_tab = get_index()
|
||||
get_tree().set_input_as_handled()
|
||||
|
||||
func _clicked(args):
|
||||
match args[0]:
|
||||
"goto":
|
||||
var tab = editor.open_file(args[1])
|
||||
editor.select_file(args[1])
|
||||
tab.goto_line(int(args[2]))
|
||||
|
||||
func _text_entered(search_for:String):
|
||||
last_search = search_for
|
||||
clear()
|
||||
var found:Dictionary = _search(search_for)
|
||||
var bbcode:PoolStringArray = PoolStringArray()
|
||||
var fpaths = found.keys()
|
||||
|
||||
for k in len(fpaths):
|
||||
if k != 0:
|
||||
bbcode.append("")
|
||||
|
||||
var file_path:String = fpaths[k]
|
||||
var l = clr("%s/%s " % [k+1, len(fpaths)], Color.orange) + clr(file_path.get_file(), Color.yellow)
|
||||
l = meta(l, ["goto", file_path, 0], file_path)
|
||||
bbcode.append(l)
|
||||
|
||||
for j in len(found[file_path]):
|
||||
var result = found[file_path][j]
|
||||
var got_lines = result[0]
|
||||
var line_index = result[1]
|
||||
var char_index = result[2]
|
||||
|
||||
if j != 0:
|
||||
bbcode.append("\t" + clr("...", Color.gray))
|
||||
|
||||
for i in len(got_lines):
|
||||
l = ""
|
||||
|
||||
if i == 2:
|
||||
var line:String = got_lines[i]
|
||||
var head:String = line.substr(0, char_index)
|
||||
var midd:String = line.substr(char_index, len(search_for)+1)
|
||||
var tail:String = line.substr(char_index+len(search_for)+1)
|
||||
head = clr(head, Color.tomato.lightened(.5))
|
||||
midd = clr(midd, Color.tomato.darkened(.25))
|
||||
tail = clr(tail, Color.tomato.lightened(.5))
|
||||
l = "\t" + clr(str(line_index-2+i+1) + ": ", Color.tomato.lightened(.5)) + (head+midd+tail)
|
||||
|
||||
elif line_index-2+i >= 0:
|
||||
l = "\t" + clr(str(line_index-2+i+1) + ": ", Color.gray) + got_lines[i]
|
||||
|
||||
if l:
|
||||
l = meta(l, ["goto", file_path, line_index])
|
||||
bbcode.append(l)
|
||||
|
||||
set_bbcode(bbcode.join("\n"))
|
||||
|
||||
# get a list of files containging lines
|
||||
func _search(search_for:String) -> Dictionary:
|
||||
var found = {}
|
||||
var search_for_l = search_for.to_lower() # lowercase. TODO: match case
|
||||
for path in editor.file_paths:
|
||||
var lines = TE_Util.load_text(path).split("\n")
|
||||
for line_index in len(lines):
|
||||
var line:String = lines[line_index].to_lower()
|
||||
# find index where result is found
|
||||
var char_index:int = line.find(search_for_l)
|
||||
if char_index != -1:
|
||||
if not path in found:
|
||||
found[path] = []
|
||||
var preview_lines = PoolStringArray()
|
||||
var highlight_from:int = line_index
|
||||
# show surrounding 5 lines.
|
||||
for i in range(-2, 3):
|
||||
if line_index+i >= 0 and line_index+i < len(lines):
|
||||
preview_lines.append(lines[line_index+i])
|
||||
else:
|
||||
preview_lines.append("")
|
||||
# lines, index in file, index in line
|
||||
found[path].append([preview_lines, line_index, char_index])
|
||||
return found
|
@ -1,12 +1,8 @@
|
||||
tool
|
||||
extends RichTextLabel
|
||||
|
||||
onready var editor:TextEditor = owner
|
||||
extends "res://addons/text_editor/TE_RichTextLabel.gd"
|
||||
|
||||
func _ready():
|
||||
var _e
|
||||
_e = connect("meta_hover_started", self, "_hovered")
|
||||
_e = connect("meta_clicked", self, "_clicked")
|
||||
_e = editor.connect("symbols_updated", self, "_redraw")
|
||||
_e = editor.connect("tags_updated", self, "_redraw")
|
||||
|
||||
@ -17,21 +13,23 @@ func _ready():
|
||||
|
||||
call_deferred("_redraw")
|
||||
|
||||
func _hovered(_id):
|
||||
pass
|
||||
|
||||
func _clicked(id):
|
||||
var p = id.split(":", true, 1)
|
||||
var i = int(p[1])
|
||||
match p[0]:
|
||||
"l":
|
||||
var te:TextEdit = editor.get_selected_tab()
|
||||
te.cursor_set_line(te.get_line_count()) # force scroll to bottom so selected line will be at top
|
||||
te.cursor_set_line(i)
|
||||
func _clicked(args:Array):
|
||||
var te:TextEdit = editor.get_selected_tab()
|
||||
te.goto_line(args[1])
|
||||
|
||||
func _redraw():
|
||||
var tab = editor.get_selected_tab()
|
||||
var symbols = {} if not tab else tab.symbols
|
||||
var spaces = PoolStringArray([
|
||||
"- ",
|
||||
" - ",
|
||||
" - "
|
||||
])
|
||||
var colors = PoolColorArray([
|
||||
Color.white,
|
||||
Color.white.darkened(.25),
|
||||
Color.white.darkened(.5)
|
||||
])
|
||||
|
||||
# no symbols
|
||||
if not symbols or len(symbols) == 1:
|
||||
@ -44,9 +42,17 @@ func _redraw():
|
||||
if line_index == -1:
|
||||
continue # special file chapter
|
||||
var symbol_info = symbols[line_index]
|
||||
var space = "" if not symbol_info.deep else " ".repeat(symbol_info.deep)
|
||||
var tagged = editor.is_tagged_or_visible(symbol_info.tags)
|
||||
var clr = Color.white.darkened(0.0 if tagged else 0.75).to_html()
|
||||
t.append(space + "[color=#%s][url=l:%s]%s[/url][/color]" % [clr, line_index, symbol_info.name])
|
||||
var deep = symbol_info.deep
|
||||
var space = "" if not deep else clr("-".repeat(deep), Color.white.darkened(.75))
|
||||
var cl = Color.deepskyblue if deep == 0 else Color.white
|
||||
|
||||
if not editor.is_tagged_or_visible(symbol_info.tags):
|
||||
cl = cl.darkened(.7)
|
||||
|
||||
elif deep >= 1:
|
||||
cl = cl.darkened(.33 * (deep-1))
|
||||
|
||||
var tags = "" if not symbol_info.tags else PoolStringArray(symbol_info.tags).join(", ")
|
||||
t.append(clr(meta(space + symbol_info.name, [symbol_info, line_index], tags), cl))
|
||||
|
||||
set_bbcode(t.join("\n"))
|
||||
|
@ -1,7 +1,7 @@
|
||||
tool
|
||||
extends TabContainer
|
||||
|
||||
onready var editor:TextEditor = owner
|
||||
onready var editor:TE_TextEditor = owner
|
||||
|
||||
var mouse_over:bool = false
|
||||
|
||||
|
@ -1,15 +1,8 @@
|
||||
tool
|
||||
extends RichTextLabel
|
||||
|
||||
onready var editor:TextEditor = owner
|
||||
|
||||
var tag_indices:Array = [] # safer to use int in [url=] than str.
|
||||
extends "res://addons/text_editor/TE_RichTextLabel.gd"
|
||||
|
||||
func _ready():
|
||||
var _e
|
||||
_e = connect("meta_hover_started", self, "_hovered")
|
||||
_e = connect("meta_hover_ended", self, "_unhover")
|
||||
_e = connect("meta_clicked", self, "_clicked")
|
||||
_e = editor.connect("symbols_updated", self, "_redraw")
|
||||
_e = editor.connect("tags_updated", self, "_redraw")
|
||||
|
||||
@ -23,17 +16,17 @@ 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 _hovered(index):
|
||||
var tag = tag_indices[int(index)]
|
||||
var count = editor.tag_counts[tag]
|
||||
hint_tooltip = "%s x%s" % [tag, count]
|
||||
#func _unhover(t):
|
||||
# hint_tooltip = ""
|
||||
|
||||
func _unhover(t):
|
||||
hint_tooltip = ""
|
||||
|
||||
func _clicked(id):
|
||||
var tag = tag_indices[int(id)]
|
||||
func _clicked(args:Array):
|
||||
var tag = args[0]
|
||||
editor.enable_tag(tag, not editor.is_tag_enabled(tag))
|
||||
|
||||
func sort_tags(tags:Dictionary):
|
||||
@ -70,26 +63,19 @@ func _redraw():
|
||||
var enabled = editor.is_tag_enabled(tag)
|
||||
|
||||
var x = tag
|
||||
# if count > 1:
|
||||
# x = "[color=#%s][i]%s[/i][/color]%s" % [count_color1 if enabled else count_color2, count, tag]
|
||||
# else:
|
||||
# x = tag
|
||||
|
||||
var color = editor.color_text
|
||||
var dim = 0.75
|
||||
|
||||
if tag in tab_tags:
|
||||
color = editor.color_symbol
|
||||
x = "[b]%s[/b]" % x
|
||||
color = editor.color_tag
|
||||
x = b(x)
|
||||
dim = 0.6
|
||||
|
||||
if enabled:
|
||||
x = x
|
||||
else:
|
||||
x = "[color=#%s]%s[/color]" % [color.darkened(dim).to_html(), x]
|
||||
x = clr(x, color.darkened(dim))
|
||||
|
||||
x = "[url=%s]%s[/url]" % [len(tag_indices), x]
|
||||
t.append(x)
|
||||
tag_indices.append(tag)
|
||||
t.append(meta(x, [tag], "%s x%s" % [tag, count] ))
|
||||
|
||||
set_bbcode("[center]" + t.join(" "))
|
||||
|
@ -1,6 +1,6 @@
|
||||
tool
|
||||
extends Control
|
||||
class_name TextEditor
|
||||
class_name TE_TextEditor
|
||||
|
||||
const FONT:DynamicFont = preload("res://addons/text_editor/fonts/font.tres")
|
||||
|
||||
@ -62,11 +62,12 @@ var show:Dictionary = {
|
||||
var color_text:Color = Color.white
|
||||
var color_comment:Color = Color.white.darkened(.6)
|
||||
var color_symbol:Color = Color.deepskyblue
|
||||
var color_tag:Color = Color.yellow
|
||||
var color_var:Color = Color.orange
|
||||
var color_varname:Color = Color.white.darkened(.25)
|
||||
|
||||
onready var test_button:Node = $c/c/c/test
|
||||
onready var tab_parent:TabContainer = $c/div1/div2/c/tab_container
|
||||
onready var tab_parent:TabContainer = $c/div1/div2/c/c/tab_container
|
||||
onready var tab_prefab:Node = $file_editor
|
||||
onready var popup:ConfirmationDialog = $popup
|
||||
onready var popup_unsaved:ConfirmationDialog = $popup_unsaved
|
||||
@ -74,6 +75,7 @@ onready var file_dialog:FileDialog = $file_dialog
|
||||
onready var line_edit:LineEdit = $c/div1/div2/c/line_edit
|
||||
onready var menu_file:MenuButton = $c/c/c/file_button
|
||||
onready var menu_view:MenuButton = $c/c/c/view_button
|
||||
onready var console:RichTextLabel = $c/div1/div2/c/c/meta_tabs/console
|
||||
var popup_file:PopupMenu
|
||||
var popup_view:PopupMenu
|
||||
var popup_view_dir:PopupMenu = PopupMenu.new()
|
||||
@ -81,6 +83,9 @@ var popup_view_file:PopupMenu = PopupMenu.new()
|
||||
|
||||
var current_directory:String = "res://"
|
||||
var file_list:Dictionary = {}
|
||||
var dir_paths:Array = []
|
||||
var file_paths:Array = []
|
||||
|
||||
var symbols:Dictionary = {}
|
||||
var tags:Array = []
|
||||
var tags_enabled:Dictionary = {}
|
||||
@ -91,9 +96,15 @@ var opened:Array = []
|
||||
var closed:Array = []
|
||||
|
||||
func _ready():
|
||||
console.info("active: %s" % is_plugin_active())
|
||||
|
||||
if not is_plugin_active():
|
||||
return
|
||||
|
||||
if OS.has_feature("standalone"):
|
||||
current_directory = OS.get_executable_path().get_base_dir()
|
||||
|
||||
console.info("current dir: %s" % current_directory)
|
||||
# not needed when editor plugin
|
||||
# get_tree().set_auto_accept_quit(false)
|
||||
|
||||
@ -177,9 +188,6 @@ func _ready():
|
||||
# tab control
|
||||
_e = tab_parent.connect("tab_changed", self, "_tab_changed")
|
||||
|
||||
#
|
||||
tab_parent.add_font_override("font", FONT_R)
|
||||
|
||||
load_state()
|
||||
update_checks()
|
||||
set_directory()
|
||||
@ -200,18 +208,14 @@ func update_checks():
|
||||
#
|
||||
for i in len(MAIN_EXTENSIONS):
|
||||
var ext = MAIN_EXTENSIONS[i]
|
||||
# popup_view_file.set_item_checked(i+2, exts_enabled)
|
||||
#
|
||||
for i in len(INTERNAL_EXTENSIONS):
|
||||
var ext = INTERNAL_EXTENSIONS[i]
|
||||
var id = i+len(MAIN_EXTENSIONS)+3
|
||||
# popup_view_file.set_item_checked(id, false)
|
||||
# TODOOO
|
||||
|
||||
func save_state():
|
||||
var state:Dictionary = {
|
||||
"save_version": "1",
|
||||
"current_directory": current_directory,
|
||||
"font_size": FONT.size,
|
||||
"tabs": {},
|
||||
"selected": get_selected_file(),
|
||||
@ -244,8 +248,6 @@ func load_state():
|
||||
if file_path == state.selected:
|
||||
selected = tab
|
||||
|
||||
current_directory = state.get("current_directory", current_directory)
|
||||
|
||||
_load_property(state, "show", true)
|
||||
|
||||
update_checks()
|
||||
@ -259,6 +261,11 @@ func load_state():
|
||||
$c/div1/div2.split_offset = state.get("div2", $c/div1/div2.split_offset)
|
||||
|
||||
emit_signal("state_loaded")
|
||||
|
||||
yield(get_tree(), "idle_frame")
|
||||
if selected:
|
||||
emit_signal("file_selected", selected.file_path)
|
||||
|
||||
|
||||
func _load_property(state:Dictionary, property:String, merge:bool=false):
|
||||
if property in state and typeof(state[property]) == typeof(self[property]):
|
||||
@ -403,7 +410,7 @@ func is_tagged(file_path:String) -> bool:
|
||||
func is_tagging() -> bool:
|
||||
return len(tags) > 0
|
||||
|
||||
func popup_create_file(dir:String="res://"):
|
||||
func popup_create_file(dir:String=current_directory):
|
||||
file_dialog.mode = FileDialog.MODE_SAVE_FILE
|
||||
file_dialog.current_dir = dir
|
||||
file_dialog.window_title = "Create File"
|
||||
@ -412,7 +419,7 @@ func popup_create_file(dir:String="res://"):
|
||||
file_dialog.set_meta("mode", "create_file")
|
||||
file_dialog.show()
|
||||
|
||||
func popup_create_dir(dir:String="res://"):
|
||||
func popup_create_dir(dir:String=current_directory):
|
||||
file_dialog.mode = FileDialog.MODE_OPEN_DIR
|
||||
file_dialog.current_dir = dir
|
||||
file_dialog.window_title = "Create Folder"
|
||||
@ -429,11 +436,13 @@ func create_file(file_path:String):
|
||||
open_file(file_path)
|
||||
select_file(file_path)
|
||||
else:
|
||||
push_error("couldnt create %s" % file_path)
|
||||
var err_msg = "couldnt create %s" % file_path
|
||||
console.err(err_msg)
|
||||
push_error(err_msg)
|
||||
|
||||
func create_dir(file_path:String):
|
||||
var d:Directory = Directory.new()
|
||||
if file_path and file_path.begins_with("res://") and not d.file_exists(file_path):
|
||||
if file_path and file_path.begins_with(current_directory) and not d.file_exists(file_path):
|
||||
print("creating folder \"%s\"" % file_path)
|
||||
d.make_dir(file_path)
|
||||
refresh_files()
|
||||
@ -509,11 +518,23 @@ func _open_file(file_path:String):
|
||||
tab.load_file(file_path)
|
||||
return tab
|
||||
|
||||
func is_allowed_extension(file_path:String) -> bool:
|
||||
var ext = get_extension(file_path)
|
||||
return ext in MAIN_EXTENSIONS
|
||||
|
||||
func open_file(file_path:String, temporary:bool=false):
|
||||
var tab = get_tab(file_path)
|
||||
if tab:
|
||||
return tab
|
||||
|
||||
elif not File.new().file_exists(file_path):
|
||||
push_error("no file %s" % file_path)
|
||||
return null
|
||||
|
||||
elif not is_allowed_extension(file_path):
|
||||
push_error("can't open %s" % file_path)
|
||||
return null
|
||||
|
||||
else:
|
||||
tab = _open_file(file_path)
|
||||
if temporary:
|
||||
@ -596,6 +617,13 @@ func rename_file(old_path:String, new_path:String):
|
||||
push_error("couldn't rename %s to %s." % [old_path, new_path])
|
||||
|
||||
func select_file(file_path:String):
|
||||
if not File.new().file_exists(file_path):
|
||||
push_error("no file %s" % file_path)
|
||||
return
|
||||
|
||||
if not is_allowed_extension(file_path):
|
||||
return
|
||||
|
||||
var temp = get_temporary_tab()
|
||||
if temp:
|
||||
if temp.file_path == file_path:
|
||||
@ -611,8 +639,10 @@ func select_file(file_path:String):
|
||||
_selected_file_changed(file_path)
|
||||
|
||||
func set_directory(path:String=current_directory):
|
||||
var gpath = ProjectSettings.globalize_path(path)
|
||||
var dname = gpath.get_file()
|
||||
# var gpath = ProjectSettings.globalize_path(path)
|
||||
# var dname = gpath.get_file()
|
||||
console.msg("Set " + path)
|
||||
|
||||
current_directory = path
|
||||
file_dialog.current_dir = path
|
||||
refresh_files()
|
||||
@ -640,13 +670,18 @@ func get_all_tabs() -> Array:
|
||||
func refresh_files():
|
||||
var old_file_list = file_list.duplicate(true)
|
||||
file_list.clear()
|
||||
dir_paths.clear()
|
||||
file_paths.clear()
|
||||
var dir = Directory.new()
|
||||
if dir.open(current_directory) == OK:
|
||||
var err = dir.open(current_directory)
|
||||
if err == OK:
|
||||
_scan_dir("", current_directory, dir, file_list, old_file_list.get("", {}))
|
||||
emit_signal("updated_file_list")
|
||||
else:
|
||||
push_error("error trying to load %s." % current_directory)
|
||||
|
||||
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:
|
||||
if not show.dir.gdignore and File.new().file_exists(base_dir.plus_file(".gdignore")):
|
||||
return false
|
||||
@ -686,6 +721,7 @@ func _scan_dir(id:String, path:String, dir:Directory, last_dir:Dictionary, old_l
|
||||
|
||||
while fname:
|
||||
var file_path = dir.get_current_dir().plus_file(fname)
|
||||
console.msg(file_path)
|
||||
|
||||
if dir.current_is_dir():
|
||||
if show_dir(fname, file_path):
|
||||
@ -704,8 +740,10 @@ func _scan_dir(id:String, path:String, dir:Directory, last_dir:Dictionary, old_l
|
||||
for p in a_dirs_and_files:
|
||||
if a_dirs_and_files[p] is Dictionary:
|
||||
a_dirs.append(p)
|
||||
dir_paths.append(a_dirs_and_files[p].file_path)
|
||||
else:
|
||||
a_files.append(a_dirs_and_files[p])
|
||||
file_paths.append(a_dirs_and_files[p])
|
||||
|
||||
sort_on_ext(a_dirs)
|
||||
sort_on_ext(a_files)
|
||||
@ -737,9 +775,12 @@ static func get_extension(file_path:String) -> String:
|
||||
return file.split(".", true, 1)[1]
|
||||
return ""
|
||||
|
||||
static func get_extension_helper(file_path:String) -> TE_ExtensionHelper:
|
||||
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 File.new().file_exists(ext_path):
|
||||
return load(ext_path).new()
|
||||
var script = load(ext_path)
|
||||
if script:
|
||||
return script.new()
|
||||
|
||||
console.err("no helper %s" % ext_path)
|
||||
return load("res://addons/text_editor/ext/TE_ExtensionHelper.gd").new()
|
||||
|
@ -1,5 +1,6 @@
|
||||
[gd_scene load_steps=16 format=2]
|
||||
[gd_scene load_steps=24 format=2]
|
||||
|
||||
[ext_resource path="res://addons/text_editor/TE_Console.gd" type="Script" id=1]
|
||||
[ext_resource path="res://addons/text_editor/TE_TextEditor.gd" type="Script" id=2]
|
||||
[ext_resource path="res://addons/text_editor/TE_FilesList.gd" type="Script" id=3]
|
||||
[ext_resource path="res://addons/text_editor/TE_FileEditor.gd" type="Script" id=4]
|
||||
@ -13,6 +14,9 @@
|
||||
[ext_resource path="res://addons/text_editor/fonts/font_r.tres" type="DynamicFont" id=12]
|
||||
[ext_resource path="res://addons/text_editor/fonts/font_bi.tres" type="DynamicFont" id=13]
|
||||
[ext_resource path="res://addons/text_editor/fonts/font.tres" type="DynamicFont" id=14]
|
||||
[ext_resource path="res://addons/text_editor/TE_Search.gd" type="Script" id=15]
|
||||
[ext_resource path="res://addons/text_editor/TE_MetaTabs.gd" type="Script" id=16]
|
||||
[ext_resource path="res://addons/text_editor/TE_ScriptInfo.gd" type="Script" id=17]
|
||||
|
||||
[sub_resource type="Theme" id=1]
|
||||
TooltipLabel/fonts/font = ExtResource( 12 )
|
||||
@ -20,6 +24,18 @@ TooltipLabel/fonts/font = ExtResource( 12 )
|
||||
[sub_resource type="Theme" id=2]
|
||||
TooltipLabel/fonts/font = ExtResource( 12 )
|
||||
|
||||
[sub_resource type="Theme" id=3]
|
||||
TooltipLabel/fonts/font = ExtResource( 12 )
|
||||
|
||||
[sub_resource type="Theme" id=4]
|
||||
TooltipLabel/fonts/font = ExtResource( 12 )
|
||||
|
||||
[sub_resource type="Theme" id=5]
|
||||
TooltipLabel/fonts/font = ExtResource( 12 )
|
||||
|
||||
[sub_resource type="Theme" id=6]
|
||||
TooltipLabel/fonts/font = ExtResource( 12 )
|
||||
|
||||
[node name="text_editor" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
@ -146,7 +162,7 @@ items = [ "Rename", null, 0, false, false, 0, 0, null, "", false, "", null, 0, f
|
||||
margin_right = 20.0
|
||||
margin_bottom = 20.0
|
||||
custom_fonts/font = ExtResource( 14 )
|
||||
items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "New Folder", null, 0, false, false, 1, 0, null, "", false ]
|
||||
items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "New Folder", null, 0, false, false, 1, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Remove", null, 0, false, false, 3, 0, null, "", false ]
|
||||
|
||||
[node name="div2" type="HSplitContainer" parent="c/div1"]
|
||||
margin_left = 218.0
|
||||
@ -168,13 +184,20 @@ size_flags_vertical = 3
|
||||
[node name="line_edit" type="LineEdit" parent="c/div1/div2/c"]
|
||||
visible = false
|
||||
margin_right = 614.0
|
||||
margin_bottom = 24.0
|
||||
margin_bottom = 32.0
|
||||
custom_fonts/font = ExtResource( 12 )
|
||||
script = ExtResource( 8 )
|
||||
|
||||
[node name="tab_container" type="TabContainer" parent="c/div1/div2/c"]
|
||||
[node name="c" type="VSplitContainer" parent="c/div1/div2/c"]
|
||||
margin_right = 614.0
|
||||
margin_bottom = 539.0
|
||||
margin_bottom = 566.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 = 566.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
custom_fonts/font = ExtResource( 12 )
|
||||
@ -185,18 +208,98 @@ __meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="meta" type="RichTextLabel" parent="c/div1/div2/c"]
|
||||
margin_top = 543.0
|
||||
[node name="meta_tabs" type="TabContainer" parent="c/div1/div2/c/c"]
|
||||
visible = false
|
||||
margin_top = 288.0
|
||||
margin_right = 614.0
|
||||
margin_bottom = 566.0
|
||||
script = ExtResource( 16 )
|
||||
|
||||
[node name="console" type="RichTextLabel" parent="c/div1/div2/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
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
bbcode_enabled = true
|
||||
meta_underlined = false
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="search" type="VBoxContainer" parent="c/div1/div2/c/c/meta_tabs"]
|
||||
visible = false
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 4.0
|
||||
margin_top = 32.0
|
||||
margin_right = -4.0
|
||||
margin_bottom = -4.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="le" type="LineEdit" parent="c/div1/div2/c/c/meta_tabs/search"]
|
||||
margin_right = 58.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
custom_fonts/font = ExtResource( 12 )
|
||||
|
||||
[node name="rte" type="RichTextLabel" parent="c/div1/div2/c/c/meta_tabs/search"]
|
||||
margin_top = 28.0
|
||||
margin_right = 58.0
|
||||
margin_bottom = 28.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme = SubResource( 2 )
|
||||
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 )
|
||||
bbcode_enabled = true
|
||||
meta_underlined = false
|
||||
script = ExtResource( 15 )
|
||||
|
||||
[node name="meta" type="RichTextLabel" parent="c/div1/div2/c/c/meta_tabs"]
|
||||
visible = false
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 4.0
|
||||
margin_top = 32.0
|
||||
margin_right = -4.0
|
||||
margin_bottom = -4.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme = SubResource( 3 )
|
||||
custom_constants/table_hseparation = 16
|
||||
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 )
|
||||
bbcode_enabled = true
|
||||
fit_content_height = true
|
||||
script = ExtResource( 9 )
|
||||
|
||||
[node name="sys" type="RichTextLabel" parent="c/div1/div2/c/c/meta_tabs"]
|
||||
visible = false
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 4.0
|
||||
margin_top = 32.0
|
||||
margin_right = -4.0
|
||||
margin_bottom = -4.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme = SubResource( 4 )
|
||||
custom_constants/table_hseparation = 101
|
||||
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 )
|
||||
bbcode_enabled = true
|
||||
meta_underlined = false
|
||||
text = "idwords ⯆unique"
|
||||
script = ExtResource( 17 )
|
||||
|
||||
[node name="c2" type="PanelContainer" parent="c/div1/div2"]
|
||||
margin_left = 626.0
|
||||
margin_right = 806.0
|
||||
@ -221,6 +324,7 @@ size_flags_vertical = 3
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
size_flags_vertical = 3
|
||||
theme = SubResource( 5 )
|
||||
custom_fonts/bold_italics_font = ExtResource( 13 )
|
||||
custom_fonts/italics_font = ExtResource( 10 )
|
||||
custom_fonts/bold_font = ExtResource( 11 )
|
||||
@ -246,7 +350,7 @@ anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme = SubResource( 2 )
|
||||
theme = SubResource( 6 )
|
||||
custom_fonts/bold_italics_font = ExtResource( 13 )
|
||||
custom_fonts/italics_font = ExtResource( 10 )
|
||||
custom_fonts/bold_font = ExtResource( 11 )
|
||||
|
@ -4,12 +4,12 @@ class_name TE_ExtensionHelper
|
||||
|
||||
var symbols:Dictionary = {}
|
||||
|
||||
func generate_meta(t:TextEdit, r:TE_RichTextLabel):
|
||||
func generate_meta(t:TextEdit, r:RichTextLabel):
|
||||
var chars = TE_Util.commas(len(t.text))
|
||||
var words = TE_Util.commas(len(t.text.split(" ", false)))
|
||||
var lines = TE_Util.commas(len(TE_Util.split_many(t.text, ".?!\n", false)))
|
||||
var bytes = TE_Util.file_size(t.file_path)
|
||||
r.add_constant_override("table_hseparation", int(r.rect_size.x / 5.0))
|
||||
# r.add_constant_override("table_hseparation", int(r.rect_size.x / 5.0))
|
||||
r.set_bbcode(r.table([
|
||||
["chars", "words", "lines", "bytes"],
|
||||
[chars, words, lines, bytes]
|
||||
|
@ -1,7 +1,7 @@
|
||||
tool
|
||||
extends TE_ExtensionHelper
|
||||
|
||||
func apply_colors(e:TextEditor, t:TextEdit):
|
||||
func apply_colors(e:TE_TextEditor, t:TextEdit):
|
||||
.apply_colors(e, t)
|
||||
# symbols
|
||||
t.add_color_region("[", "]", e.color_symbol, false)
|
||||
|
@ -34,7 +34,7 @@ func get_symbols(t:String):
|
||||
|
||||
return out
|
||||
|
||||
func apply_colors(e:TextEditor, t:TextEdit):
|
||||
func apply_colors(e:TE_TextEditor, t:TextEdit):
|
||||
.apply_colors(e, t)
|
||||
|
||||
# vars
|
||||
|
@ -4,7 +4,7 @@ extends TE_ExtensionHelper
|
||||
func toggle_comment(t:TextEdit, head:String="<!-- ", tail:String=" -->"):
|
||||
return .toggle_comment(t, head, tail)
|
||||
|
||||
func apply_colors(e:TextEditor, t:TextEdit):
|
||||
func apply_colors(e:TE_TextEditor, t:TextEdit):
|
||||
.apply_colors(e, t)
|
||||
|
||||
t.add_keyword_color("true", e.color_var)
|
||||
@ -32,15 +32,9 @@ func apply_colors(e:TextEditor, t:TextEdit):
|
||||
t.add_color_region("%s *" % h, "*", tint1, true)
|
||||
t.add_color_region("%s \"" % h, "\"", tint2, true)
|
||||
t.add_color_region("%s " % h, "*", head, true)
|
||||
# t.add_color_region("# \"", "\"", TE_Util.hue_shift(head, .33), true)
|
||||
# t.add_color_region("# ", "", head, true)
|
||||
# t.add_color_region("## ", "", head, true)
|
||||
# t.add_color_region("### ", "", head, true)
|
||||
# t.add_color_region("#### ", "", head, true)
|
||||
# t.add_color_region("##### ", "", head, true)
|
||||
# t.add_color_region("###### ", "", head, true)
|
||||
|
||||
# url links
|
||||
# t.add_color_region("[]", ")", e.color_var.lightened(.5))
|
||||
t.add_color_region("![", ")", e.color_var.lightened(.5))
|
||||
|
||||
# lists
|
||||
|
@ -43,7 +43,7 @@ func toggle_comment(t:TextEdit, head:String="", tail:String=""):
|
||||
|
||||
return [old, new]
|
||||
|
||||
func apply_colors(e:TextEditor, t:TextEdit):
|
||||
func apply_colors(e:TE_TextEditor, t:TextEdit):
|
||||
.apply_colors(e, t)
|
||||
|
||||
# strings
|
||||
|
@ -3,5 +3,5 @@
|
||||
name="TextEditor"
|
||||
description="A text editor for Godot."
|
||||
author="teebar"
|
||||
version="1.2"
|
||||
version="1.4"
|
||||
script="plugin.gd"
|
||||
|
Loading…
Reference in New Issue
Block a user