This commit is contained in:
teebarjunk 2021-10-18 19:50:21 -04:00
parent f2ae9db115
commit 5bcd5a47b0
24 changed files with 413 additions and 201 deletions

View File

@ -1,3 +1,15 @@
# 1.5
- Added `Ctrl + N` to immediately create new file without defining path.
- New unsaved file will have contents remembered.
- Added `Ctrl + Shift + Mouse wheel` to change ui font size.
- Added word wrap toggle.
- Fixed sorting error in `sys`.
- Fixed font size save/load.
- `sys` shows chapter count.
- Preserves symbol view scroll value when tabbing.
- Can access full filesystem.
- Fixed "New File" dialog not gaining focus.
# 1.4
- Added `sys` info tab.
- Added `console` info tab. (wip)

View File

@ -1,7 +1,7 @@
tool
extends RichTextLabel
var editor:TE_TextEditor
var editor:TE_Editor
var click_pos:Vector2
func _init(text):

View File

@ -1,6 +1,6 @@
tool
extends Control
class_name TE_TextEditor
class_name TE_Editor
const FONT:DynamicFont = preload("res://addons/text_editor/fonts/font.tres")
@ -75,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 word_wrap:CheckBox = $c/c/c/word_wrap
onready var console:RichTextLabel = $c/div1/div2/c/c/meta_tabs/console
var popup_file:PopupMenu
var popup_view:PopupMenu
@ -103,6 +104,7 @@ func _ready():
if OS.has_feature("standalone"):
current_directory = OS.get_executable_path().get_base_dir()
file_dialog.access = FileDialog.ACCESS_FILESYSTEM
console.info("current dir: %s" % current_directory)
# not needed when editor plugin
@ -126,10 +128,9 @@ func _ready():
popup_file.clear()
popup_file.add_font_override("font", FONT_R)
popup_file.add_item("New File", 100)
popup_file.add_item("New Folder", 200)
popup_file.add_separator()
popup_file.add_item("Open last closed", 300)
_e = popup_file.connect("id_pressed", self, "_menu_file")
_e = popup_file.connect("index_pressed", self, "_menu_file")
# view
menu_view.add_font_override("font", FONT_R)
@ -188,10 +189,19 @@ func _ready():
# tab control
_e = tab_parent.connect("tab_changed", self, "_tab_changed")
# word wrap
_e = word_wrap.connect("pressed", self, "_toggle_word_wrap")
word_wrap.add_font_override("font", FONT_R)
load_state()
update_checks()
set_directory()
func _toggle_word_wrap():
tab_prefab.set_wrap_enabled(word_wrap.pressed)
for tab in get_all_tabs():
tab.set_wrap_enabled(word_wrap.pressed)
func update_checks():
# Directories
popup_view_dir.set_item_checked(0, show.dir.hidden)
@ -217,6 +227,7 @@ func save_state():
var state:Dictionary = {
"save_version": "1",
"font_size": FONT.size,
"font_size_ui": FONT_R.size,
"tabs": {},
"selected": get_selected_file(),
"show": show,
@ -228,8 +239,13 @@ func save_state():
"file_list": file_list,
"div1": $c/div1.split_offset,
"div2": $c/div1/div2.split_offset
"div2": $c/div1/div2.split_offset,
"div3": $c/div1/div2/c/c.split_offset,
"div4": $c/div1/div2/c2/c.split_offset
}
var ws = OS.get_window_size()
state["window_size"] = [ws.x, ws.y]
for tab in get_all_tabs():
state.tabs[tab.file_path] = tab.get_state()
@ -252,13 +268,27 @@ func load_state():
update_checks()
FONT.size = state.get("font_size", FONT.size)
var font_size_ui = state.get("font_size_ui", FONT_R.size)
for f in [FONT_R, FONT_B, FONT_I, FONT_BI]:
f.size = font_size_ui
_load_property(state, "file_list")
_load_property(state, "tag_counts")
_load_property(state, "tags_enabled")
_load_property(state, "exts_enabled")
# dividers
$c/div1.split_offset = state.get("div1", $c/div1.split_offset)
$c/div1/div2.split_offset = state.get("div2", $c/div1/div2.split_offset)
$c/div1/div2/c/c.split_offset = state.get("div3", $c/div1/div2/c/c.split_offset)
$c/div1/div2/c2/c.split_offset = state.get("div4", $c/div1/div2/c2/c.split_offset)
# window size
if "window_size" in state:
var ws = state.window_size
OS.set_window_size(Vector2(ws[0], ws[1]))
emit_signal("state_loaded")
@ -295,25 +325,67 @@ func _input(e):
if not is_plugin_active():
return
if e is InputEventMouseButton and e.control:
if e.button_index == BUTTON_WHEEL_DOWN:
FONT.size = int(max(8, FONT.size - 1))
if e is InputEventKey and e.pressed and e.control:
# tab to next
if e.scancode == KEY_TAB:
if e.shift:
tab_parent.prev()
else:
tab_parent.next()
get_tree().set_input_as_handled()
elif e.button_index == BUTTON_WHEEL_UP:
FONT.size = int(min(64, FONT.size + 1))
# save files
elif e.scancode == KEY_S:
save_files()
get_tree().set_input_as_handled()
# close file
elif e.scancode == KEY_W:
if e.shift:
open_last_file()
else:
get_selected_tab().close()
get_tree().set_input_as_handled()
# create new file
elif e.scancode == KEY_N:
open_file("", true)
get_tree().set_input_as_handled()
if e is InputEventMouseButton and e.control:
# ui font
if e.shift:
if e.button_index == BUTTON_WHEEL_DOWN:
for f in [FONT_B, FONT_BI, FONT_R, FONT_I]:
f.size = int(max(8, f.size - 1))
get_tree().set_input_as_handled()
elif e.button_index == BUTTON_WHEEL_UP:
for f in [FONT_B, FONT_BI, FONT_R, FONT_I]:
f.size = int(min(64, f.size + 1))
get_tree().set_input_as_handled()
# text font
else:
if e.button_index == BUTTON_WHEEL_DOWN:
FONT.size = int(max(8, FONT.size - 1))
get_tree().set_input_as_handled()
elif e.button_index == BUTTON_WHEEL_UP:
FONT.size = int(min(64, FONT.size + 1))
get_tree().set_input_as_handled()
func _apply_fonts(n:Node):
if n is Control:
if n.has_font("font"):
n.add_font_override("font", FONT_R)
func _menu_file(id):
match id:
100: popup_create_file() # "New File"
200: popup_create_dir() # "New Folder"
300: open_last_file() # "Open last closed"
func _menu_file(index:int):
var text = popup_file.get_item_text(index)
match text:
"New File": popup_create_file() # "New File"
"Open last closed": open_last_file() # "Open last closed"
func _menu_view_dir(index:int):
var text = popup_view_dir.get_item_text(index)
@ -365,8 +437,12 @@ func _menu_view_file(index:int):
func _file_dialog_file(file_path:String):
match file_dialog.get_meta("mode"):
"create_file": create_file(file_path)
"create_dir": create_dir(file_path)
"create_file":
var text = file_dialog.get_meta("text")
create_file(file_path, text)
"create_dir":
create_dir(file_path)
var tab_index:int = -1
func _tab_changed(index:int):
@ -411,35 +487,40 @@ func is_tagged(file_path:String) -> bool:
func is_tagging() -> bool:
return len(tags) > 0
func popup_create_file(dir:String=current_directory):
func popup_create_file(dir:String=current_directory, text:String="", callback:FuncRef=null):
file_dialog.mode = FileDialog.MODE_SAVE_FILE
file_dialog.current_dir = dir
file_dialog.window_title = "Create File"
file_dialog.current_path = "new_file.txt"
file_dialog.current_path = "new_file.md"
file_dialog.filters = FILE_FILTERS
file_dialog.set_meta("mode", "create_file")
file_dialog.set_meta("text", text)
file_dialog.set_meta("callback", callback)
file_dialog.show()
yield(get_tree(), "idle_frame")
file_dialog.get_line_edit().grab_click_focus()
file_dialog.get_line_edit().grab_focus()
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"
file_dialog.current_path = "New Folder"
file_dialog.set_meta("mode", "create_dir")
file_dialog.show()
func create_file(file_path:String):
func create_file(file_path:String, text:String=""):
var f:File = File.new()
if f.open(file_path, File.WRITE) == OK:
f.store_string("")
f.store_string(text)
f.close()
refresh_files()
if file_dialog.has_meta("callback"):
var fr:FuncRef = file_dialog.get_meta("callback")
fr.call_func(file_path)
file_dialog.set_meta("callback", null)
open_file(file_path)
select_file(file_path)
return true
else:
var err_msg = "couldnt create %s" % file_path
console.err(err_msg)
push_error(err_msg)
return false
func create_dir(file_path:String):
var d:Directory = Directory.new()
@ -460,7 +541,7 @@ func get_selected_file() -> String:
func get_tab(file_path:String) -> TextEdit:
for child in tab_parent.get_children():
if child.file_path == file_path:
if child is TextEdit and child.file_path == file_path:
return child
return null
@ -502,16 +583,25 @@ func close_file(file_path:String):
tab.close()
func _close_file(file_path, remember:bool=true):
if remember:
if remember and file_path:
closed.append(file_path)
var tab = get_tab(file_path)
var tab:Node = get_tab(file_path)
tab_parent.remove_child(tab)
tab.queue_free()
emit_signal("file_closed", file_path)
if file_path:
emit_signal("file_closed", file_path)
# force select a file
yield(get_tree(), "idle_frame")
var fp = get_selected_file()
if fp:
select_file(fp)
func _open_file(file_path:String):
var tab = tab_prefab.duplicate()
tab.name = "tab"
tab.visible = true
tab.editor = self
tab_parent.add_child(tab)
@ -528,11 +618,11 @@ func open_file(file_path:String, temporary:bool=false):
if tab:
return tab
elif not File.new().file_exists(file_path):
elif not File.new().file_exists(file_path) and not file_path == "":
push_error("no file %s" % file_path)
return null
elif not is_allowed_extension(file_path):
elif not is_allowed_extension(file_path) and not file_path == "":
push_error("can't open %s" % file_path)
return null
@ -542,6 +632,10 @@ func open_file(file_path:String, temporary:bool=false):
tab.temporary = true
else:
opened.append(file_path)
# select it
tab_parent.current_tab = tab.get_index()
emit_signal("file_opened", file_path)
return tab
@ -564,11 +658,15 @@ func unrecycle(file_path:String):
d.remove(file_path)
refresh_files()
else:
print("can't unrecyle")
var err_msg = "can't unrecyle %s" % file_path
push_error(err_msg)
console.err(err_msg)
func recycle(file_path:String):
if file_path.begins_with(PATH_TRASH):
push_error("can't recycle recycled.")
var err_msg = "can't recycle recycled %s" % file_path
push_error(err_msg)
console.err(err_msg)
return
var tab = get_tab(file_path)
@ -640,10 +738,6 @@ 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()
console.msg("Set " + path)
current_directory = path
file_dialog.current_dir = path
refresh_files()
@ -722,7 +816,6 @@ 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):
@ -779,9 +872,8 @@ static func get_extension(file_path:String) -> String:
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
var script = load(ext_path)
if script:
return script.new()
if ext in ["cfg", "csv", "ini", "json", "md", "yaml"]:
return load(ext_path).new()
console.err("no helper %s" % ext_path)
return load("res://addons/text_editor/ext/TE_ExtensionHelper.gd").new()

View File

@ -1,7 +1,7 @@
tool
extends TextEdit
var editor:TE_TextEditor
var editor:TE_Editor
var _hscroll:HScrollBar
var _vscroll:VScrollBar
@ -22,6 +22,12 @@ var vscroll:int = 0
var in_focus:bool = false
func _ready():
# prefab?
if name == "file_editor":
set_process(false)
set_process_input(false)
return
var _e
if not editor:
editor = owner
@ -39,6 +45,10 @@ func _ready():
add_font_override("font", editor.FONT)
get_menu().add_font_override("font", editor.FONT)
# hint
theme = Theme.new()
theme.set_font("font", "TooltipLabel", editor.FONT_R)
TE_Util.dig(self, self, "_node")
func _node(n):
@ -59,24 +69,31 @@ func _scroll_v(v:VScrollBar):
func _tab_changed(index:int):
var myindex = get_index()
if index == myindex and visible:
grab_focus()
grab_click_focus()
# grab_focus()
# grab_click_focus()
yield(get_tree(), "idle_frame")
set_h_scroll(hscroll)
set_v_scroll(vscroll)
func get_state() -> Dictionary:
return {
hscroll=scroll_horizontal,
vscroll=scroll_vertical
}
var state = { hscroll=scroll_horizontal, vscroll=scroll_vertical }
# unsaved
if file_path == "":
state.text = text
return state
func set_state(state:Dictionary):
yield(get_tree(), "idle_frame")
hscroll = state.hscroll
vscroll = state.vscroll
set_h_scroll(state.hscroll)
set_v_scroll(state.vscroll)
if "text" in state:
if state.text.strip_edges():
text = state.text
else:
editor._close_file(file_path)
func _file_renamed(old_path:String, new_path:String):
if old_path == file_path:
@ -105,29 +122,6 @@ func _input(e):
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:
get_tree().set_input_as_handled()
if e.shift:
get_parent().prev()
else:
get_parent().next()
# save files
elif e.scancode == KEY_S:
get_tree().set_input_as_handled()
editor.save_files()
# close file
elif e.scancode == KEY_W:
get_tree().set_input_as_handled()
if e.shift:
editor.open_last_file()
else:
close()
# remember last selection
if e is InputEventKey and e.pressed:
@ -184,12 +178,38 @@ func _file_selected(p:String):
return
if p == file_path:
grab_focus()
grab_click_focus()
update_symbols()
update_heading()
var cl = cursor_get_line()
var cc = cursor_get_column()
var fl
var fc
var tl
var tc
var had_selection = false
if is_selection_active():
had_selection = true
fl = get_selection_from_line()
fc = get_selection_from_column()
tl = get_selection_to_line()
tc = get_selection_to_column()
grab_focus()
grab_click_focus()
yield(get_tree(), "idle_frame")
cursor_set_line(cl)
cursor_set_column(cc)
if had_selection:
select(fl, fc, tl, tc)
func goto_line(line:int):
prints("goto ", line)
# force scroll to bottom so selected line will be at top
cursor_set_line(get_line_count())
cursor_set_line(line)
@ -239,56 +259,80 @@ func update_symbols():
else:
tags[tag] += 1
# var _e = TE_Util.sort(tags, true)
editor._file_symbols_updated(file_path)
func close():
if modified:
var _e
_e = editor.popup_unsaved.connect("confirmed", self, "_popup", ["close"], CONNECT_ONESHOT)
_e = editor.popup_unsaved.connect("custom_action", self, "_popup", [], CONNECT_ONESHOT)
editor.popup_unsaved.show()
if not editor.popup_unsaved.visible:
var _e
_e = editor.popup_unsaved.connect("confirmed", self, "_popup", ["confirm_close"], CONNECT_ONESHOT)
_e = editor.popup_unsaved.connect("custom_action", self, "_popup", [], CONNECT_ONESHOT)
# _e = editor.popup_unsaved.connect("hide", self, "_popup", ["cancel"], CONNECT_ONESHOT)
editor.popup_unsaved.show()
else:
editor._close_file(file_path)
func _popup(msg):
match msg:
"close":
"confirm_close":
editor._close_file(file_path)
"save_and_close":
save_file()
editor._close_file(file_path)
editor.popup_unsaved.disconnect("confirmed", self, "_popup")
editor.popup_unsaved.disconnect("custom_action", self, "_popup")
func load_file(path:String):
file_path = path
text = TE_Util.load_text(path)
update_name()
if path != "":
text = TE_Util.load_text(path)
update_colors()
update_name()
func update_colors():
clear_colors()
helper = editor.get_extension_helper(file_path)
helper.apply_colors(editor, self)
func _created_nonexisting(fp:String):
file_path = fp
modified = false
update_name()
update_symbols()
func save_file():
if modified:
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
editor.save_file(file_path, text)
update_name()
update_symbols()
if file_path == "":
editor.popup_create_file(editor.current_directory, text, funcref(self, "_created_nonexisting"))
else:
if modified:
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
editor.save_file(file_path, text)
update_name()
update_symbols()
func update_name():
var n = file_path.get_file().split(".", true, 1)[0]
if temporary: n = "?" + n
if modified: n = "*" + n
var n:String
if file_path == "":
n = "*UNSAVED"
else:
n = file_path.get_file().split(".", true, 1)[0]
if temporary: n = "?" + n
if modified: n = "*" + n
if len(n) > 9:
n = n.substr(0, 6) + "..."
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():

View File

@ -1,6 +1,6 @@
extends TabContainer
onready var editor:TE_TextEditor = owner
onready var editor:TE_Editor = owner
var mouse:bool = false
func _ready():

View File

@ -33,7 +33,6 @@ func _ready():
dir_popup.clear()
dir_popup.rect_size = Vector2.ZERO
dir_popup.add_item("New File")
dir_popup.add_item("New Folder")
dir_popup.add_separator()
dir_popup.add_item("Remove")
_e = dir_popup.connect("index_pressed", self, "_dir_popup")
@ -52,7 +51,6 @@ func _dir_popup(index:int):
match dir_popup.get_item_text(index):
"New File": editor.popup_create_file(file)
"New Folder": editor.popup_create_dir(file)
"Remove": editor.recycle(file)
func _file_popup(index:int):

View File

@ -1,7 +1,7 @@
tool
extends LineEdit
onready var editor:TE_TextEditor = owner
onready var editor:TE_Editor = owner
var fr:FuncRef
func _ready():

View File

@ -1,7 +1,7 @@
tool
extends TabContainer
onready var editor:TE_TextEditor = owner
onready var editor:TE_Editor = owner
func _ready():
if not editor.is_plugin_active():

View File

@ -1,6 +1,6 @@
extends RichTextLabel
onready var editor:TE_TextEditor = owner
onready var editor:TE_Editor = owner
var meta_items:Array = []
var meta_hovered:Array = []

View File

@ -3,17 +3,15 @@ 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 }
var sort_reverse:Dictionary = { id=false, words=false, chaps=false }
func _ready():
var _e
_e = editor.connect("file_opened", self, "_update")
_e = editor.connect("file_saved", self, "_update")
var btn = get_parent().get_node("update")
btn.add_font_override("font", editor.FONT_R)
var _e = btn.connect("pressed", self, "_update")
func _update(f):
set_process(true)
func _process(_delta):
func _update():
chapter_info.clear()
for path in editor.file_paths:
@ -22,21 +20,30 @@ func _process(_delta):
match ext:
"md": _process_md(path)
# clear empty
for i in range(len(chapter_info)-1, -1, -1):
var info = chapter_info[i]
if not info.words:
chapter_info.remove(i)
_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 })
if not id:
id = "???"
chapter_info.append({ path=path, line=line, id=id, words=0, chaps=0 })
func _process_md(path:String):
var lines = TE_Util.load_text(path).split("\n")
var is_entire_file:bool = false
_chapter(path, 0, "NOH")
var i = 0
while i < len(lines):
# skip head meta
if i == 0 and lines[i].begins_with("---"):
is_entire_file = true
i += 1
while i < len(lines) and not lines[i].begins_with("---"):
i += 1
@ -51,29 +58,20 @@ func _process_md(path:String):
# 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)
var id = lines[i].split(" ", true, 1)
var deep = len(id[0])
id = "???" if len(id) == 1 else id[1].strip_edges()
if deep == 1 and not is_entire_file:
_chapter(path, i, id)
else:
chapter_info[-1].chaps += 1
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":
@ -87,35 +85,41 @@ func _clicked(args):
_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")
else:
chapter_info.sort_custom(self, "_sort_chapters")
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 _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)
var cols = ["id", "words", "chaps"]
push_align(RichTextLabel.ALIGN_CENTER)
push_table(3)
for id in ["id", "words", "unique"]:
push_table(len(cols))
for id in cols:
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))
push_color(Color.greenyellow.darkened(.25))
add_text("" if sort_reverse[id] else "")
pop()
else:
push_color(Color.white.darkened(.7))
add_text("" if sort_reverse[id] else "")
pop()
pop()
@ -124,10 +128,6 @@ func _redraw():
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
@ -140,10 +140,10 @@ func _redraw():
pop()
# word cound
for w in ["words", "unique"]:
for x in ["words", "chaps"]:
push_cell()
push_color(clr)
add_text(TE_Util.commas(item[w]))
add_text(TE_Util.commas(item[x]))
pop()
pop()

View File

@ -21,7 +21,7 @@ func _unhandled_key_input(e):
line_edit.grab_focus()
line_edit.grab_click_focus()
get_parent().get_parent().show()
get_parent().get_parent().current_tab = get_index()
get_parent().get_parent().current_tab = get_parent().get_index()
get_tree().set_input_as_handled()
func _clicked(args):

View File

@ -1,10 +1,14 @@
tool
extends "res://addons/text_editor/TE_RichTextLabel.gd"
var hscrolls:Dictionary = {}
func _ready():
var _e
_e = editor.connect("symbols_updated", self, "_redraw")
_e = editor.connect("tags_updated", self, "_redraw")
_e = editor.connect("file_selected", self, "_file_selected")
_e = get_v_scroll().connect("value_changed", self, "_scrolling")
add_font_override("normal_font", editor.FONT_R)
add_font_override("bold_font", editor.FONT_B)
@ -13,6 +17,13 @@ func _ready():
call_deferred("_redraw")
func _file_selected(file_path:String):
yield(get_tree(), "idle_frame")
get_v_scroll().value = hscrolls.get(file_path, 0)
func _scrolling(v):
hscrolls[editor.get_selected_file()] = get_v_scroll().value
func _clicked(args:Array):
var te:TextEdit = editor.get_selected_tab()
te.goto_line(args[1])
@ -44,7 +55,14 @@ func _redraw():
var symbol_info = symbols[line_index]
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
var cl = Color.white
if deep == 0:
cl = editor.color_symbol
if symbol_info.name.begins_with("*") and symbol_info.name.ends_with("*"):
cl = TE_Util.hue_shift(cl, -.33)
elif symbol_info.name.begins_with('"') and symbol_info.name.ends_with('"'):
cl = TE_Util.hue_shift(cl, .33)
if not editor.is_tagged_or_visible(symbol_info.tags):
cl = cl.darkened(.7)

View File

@ -1,7 +1,7 @@
tool
extends TabContainer
onready var editor:TE_TextEditor = owner
onready var editor:TE_Editor = owner
var mouse_over:bool = false

View File

@ -1,7 +1,7 @@
[gd_scene load_steps=24 format=2]
[gd_scene load_steps=25 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_Editor.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]
[ext_resource path="res://addons/text_editor/TE_SymbolsList.gd" type="Script" id=5]
@ -36,6 +36,9 @@ TooltipLabel/fonts/font = ExtResource( 12 )
[sub_resource type="Theme" id=6]
TooltipLabel/fonts/font = ExtResource( 12 )
[sub_resource type="Theme" id=7]
TooltipLabel/fonts/font = ExtResource( 12 )
[node name="text_editor" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
@ -76,23 +79,23 @@ __meta__ = {
[node name="c" type="PanelContainer" parent="c"]
margin_right = 1024.0
margin_bottom = 34.0
margin_bottom = 38.0
[node name="c" type="HBoxContainer" parent="c/c"]
margin_left = 7.0
margin_top = 7.0
margin_right = 1017.0
margin_bottom = 27.0
margin_bottom = 31.0
[node name="test" type="Button" parent="c/c/c"]
margin_right = 12.0
margin_bottom = 20.0
margin_bottom = 24.0
text = "⟳"
[node name="file_button" type="MenuButton" parent="c/c/c"]
margin_left = 16.0
margin_right = 48.0
margin_bottom = 20.0
margin_bottom = 24.0
text = "file"
items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "Extensions", null, 0, false, false, 1, 0, null, "Extensions", false, "New File", null, 0, false, false, 2, 0, null, "", false, "Extensions", null, 0, false, false, 3, 0, null, "Extensions", false ]
__meta__ = {
@ -102,7 +105,7 @@ __meta__ = {
[node name="view_button" type="MenuButton" parent="c/c/c"]
margin_left = 52.0
margin_right = 93.0
margin_bottom = 20.0
margin_bottom = 24.0
focus_mode = 2
text = "view"
items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "Extensions", null, 0, false, false, 1, 0, null, "Extensions", false, "New File", null, 0, false, false, 2, 0, null, "", false, "Extensions", null, 0, false, false, 3, 0, null, "Extensions", false ]
@ -110,8 +113,14 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="word_wrap" type="CheckBox" parent="c/c/c"]
margin_left = 97.0
margin_right = 155.0
margin_bottom = 24.0
text = "wrap"
[node name="div1" type="HSplitContainer" parent="c"]
margin_top = 34.0
margin_top = 38.0
margin_right = 1024.0
margin_bottom = 600.0
size_flags_vertical = 3
@ -122,7 +131,7 @@ __meta__ = {
[node name="c2" type="PanelContainer" parent="c/div1"]
margin_right = 206.0
margin_bottom = 566.0
margin_bottom = 562.0
rect_min_size = Vector2( 200, 0 )
size_flags_horizontal = 3
size_flags_vertical = 3
@ -131,7 +140,7 @@ size_flags_vertical = 3
margin_left = 7.0
margin_top = 7.0
margin_right = 199.0
margin_bottom = 559.0
margin_bottom = 555.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -167,7 +176,7 @@ items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "New Folder"
[node name="div2" type="HSplitContainer" parent="c/div1"]
margin_left = 218.0
margin_right = 1024.0
margin_bottom = 566.0
margin_bottom = 562.0
size_flags_horizontal = 3
size_flags_vertical = 3
split_offset = -80
@ -177,7 +186,7 @@ __meta__ = {
[node name="c" type="VBoxContainer" parent="c/div1/div2"]
margin_right = 614.0
margin_bottom = 566.0
margin_bottom = 562.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -190,14 +199,14 @@ script = ExtResource( 8 )
[node name="c" type="VSplitContainer" parent="c/div1/div2/c"]
margin_right = 614.0
margin_bottom = 566.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 = 566.0
margin_bottom = 562.0
size_flags_horizontal = 3
size_flags_vertical = 3
custom_fonts/font = ExtResource( 12 )
@ -224,10 +233,36 @@ margin_right = -4.0
margin_bottom = -4.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
text = "active: False
"
script = ExtResource( 1 )
[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
script = ExtResource( 9 )
[node name="search" type="VBoxContainer" parent="c/div1/div2/c/c/meta_tabs"]
visible = false
anchor_right = 1.0
@ -251,7 +286,7 @@ margin_right = 58.0
margin_bottom = 28.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 2 )
theme = SubResource( 4 )
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )
@ -260,7 +295,7 @@ bbcode_enabled = true
meta_underlined = false
script = ExtResource( 15 )
[node name="meta" type="RichTextLabel" parent="c/div1/div2/c/c/meta_tabs"]
[node name="sys" type="VBoxContainer" parent="c/div1/div2/c/c/meta_tabs"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
@ -268,28 +303,22 @@ 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
script = ExtResource( 9 )
[node name="sys" type="RichTextLabel" parent="c/div1/div2/c/c/meta_tabs"]
visible = false
[node name="update" type="Button" parent="c/div1/div2/c/c/meta_tabs/sys"]
margin_right = 12.0
margin_bottom = 20.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"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 32.0
margin_right = -4.0
margin_bottom = -4.0
margin_right = -8.0
margin_bottom = -36.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 4 )
theme = SubResource( 5 )
custom_constants/table_hseparation = 101
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
@ -303,7 +332,7 @@ script = ExtResource( 17 )
[node name="c2" type="PanelContainer" parent="c/div1/div2"]
margin_left = 626.0
margin_right = 806.0
margin_bottom = 566.0
margin_bottom = 562.0
rect_min_size = Vector2( 100, 0 )
size_flags_vertical = 3
@ -311,12 +340,13 @@ size_flags_vertical = 3
margin_left = 7.0
margin_top = 7.0
margin_right = 173.0
margin_bottom = 559.0
margin_bottom = 555.0
custom_constants/autohide = 0
split_offset = 180
[node name="c" type="Panel" parent="c/div1/div2/c2/c"]
margin_right = 166.0
margin_bottom = 270.0
margin_bottom = 448.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -324,7 +354,7 @@ size_flags_vertical = 3
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_vertical = 3
theme = SubResource( 5 )
theme = SubResource( 6 )
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )
@ -339,9 +369,9 @@ __meta__ = {
}
[node name="c2" type="Panel" parent="c/div1/div2/c2/c"]
margin_top = 282.0
margin_top = 460.0
margin_right = 166.0
margin_bottom = 552.0
margin_bottom = 548.0
size_flags_horizontal = 3
size_flags_vertical = 3
@ -350,7 +380,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 6 )
theme = SubResource( 7 )
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )

View File

@ -1,7 +1,7 @@
tool
extends TE_ExtensionHelper
func apply_colors(e:TE_TextEditor, t:TextEdit):
func apply_colors(e:TE_Editor, t:TextEdit):
.apply_colors(e, t)
# symbols
t.add_color_region("[", "]", e.color_symbol, false)
@ -27,6 +27,7 @@ func get_symbols(t:String) -> Dictionary:
# tags
elif lines[i].begins_with(";") and "#" in lines[i]:
for t in lines[i].substr(1).split("#"):
t = t.strip_edges()
if t:
last.tags.append(t)

View File

@ -34,7 +34,7 @@ func get_symbols(t:String):
return out
func apply_colors(e:TE_TextEditor, t:TextEdit):
func apply_colors(e:TE_Editor, t:TextEdit):
.apply_colors(e, t)
# vars

View File

@ -18,7 +18,7 @@ func apply_colors(e:TE_TextEditor, t:TextEdit):
t.add_color_region("*", "*", Color.tomato.lightened(.3), false)
# quote
t.add_color_region("> ", "", e.color_text.darkened(.6), true)
t.add_color_region("> ", "", lerp(e.color_text, e.color_symbol, .5), true)
# comment
t.add_color_region("<!--", "-->", e.color_comment, false)
@ -66,11 +66,23 @@ func get_symbols(t:String) -> Dictionary:
var i = 0
while i < len(lines):
# initial meta data
if i == 0 and lines[i].begins_with("---"):
i += 1
while i < len(lines) and not lines[i].begins_with("---"):
if "tags: " in lines[i]:
for tag in lines[i].split("tags: ", true, 1)[1].split("#"):
tag = tag.strip_edges()
if tag:
last.tags.append(tag)
i += 1
i += 1
# symbols
if lines[i].begins_with("#"):
elif lines[i].begins_with("#"):
var p = lines[i].split(" ", true, 1)
var deep = len(p[0])-1
var name = p[1].strip_edges()
var name = "???" if len(p) == 1 else p[1].strip_edges()
last = add_symbol(i, deep, name)
# tags

View File

@ -43,7 +43,7 @@ func toggle_comment(t:TextEdit, head:String="", tail:String=""):
return [old, new]
func apply_colors(e:TE_TextEditor, t:TextEdit):
func apply_colors(e:TE_Editor, t:TextEdit):
.apply_colors(e, t)
# strings

View File

@ -5,6 +5,7 @@
[ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3]
[resource]
use_filter = true
font_data = ExtResource( 1 )
fallback/0 = ExtResource( 3 )
fallback/1 = ExtResource( 2 )

View File

@ -5,6 +5,7 @@
[ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3]
[resource]
use_filter = true
font_data = ExtResource( 1 )
fallback/0 = ExtResource( 3 )
fallback/1 = ExtResource( 2 )

View File

@ -5,6 +5,7 @@
[ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3]
[resource]
use_filter = true
font_data = ExtResource( 1 )
fallback/0 = ExtResource( 3 )
fallback/1 = ExtResource( 2 )

View File

@ -5,6 +5,7 @@
[ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3]
[resource]
use_filter = true
font_data = ExtResource( 1 )
fallback/0 = ExtResource( 3 )
fallback/1 = ExtResource( 2 )

View File

@ -5,6 +5,7 @@
[ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3]
[resource]
use_filter = true
font_data = ExtResource( 1 )
fallback/0 = ExtResource( 3 )
fallback/1 = ExtResource( 2 )

View File

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