Compare commits

...

12 Commits
v1.4 ... main

Author SHA1 Message Date
teebarjunk
25d4f161cf 1.12 2022-02-03 07:34:34 -05:00
teebarjunk
4225903a92 1.11 2021-12-19 10:43:24 -05:00
teebarjunk
dfe30486d2 1.10 2021-11-27 05:35:18 -05:00
teebarjunk
40beef4690 1.9 2021-11-24 11:09:48 -05:00
teebarjunk
498fb79e89 1.8 2021-11-20 08:53:02 -05:00
teebarjunk
baeeb0a808 1.7 2021-10-24 11:28:40 -04:00
teebarjunk
06e8d176c4 1.7 2021-10-24 11:27:27 -04:00
teebarjunk
4f09def7ef 1.6 2021-10-23 00:00:42 -04:00
teebarjunk
96c064c2b9 1.6 2021-10-22 23:51:34 -04:00
teebarjunk
c8ce103df4 1.5 2021-10-18 19:52:40 -04:00
teebarjunk
5bcd5a47b0 1.5 2021-10-18 19:50:21 -04:00
teebarjunk
f2ae9db115 1.4.1 2021-10-18 15:29:57 -04:00
48 changed files with 2736 additions and 588 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ test_files/
.trash/
.trash.json
.text_editor_state.json
word_skip_list.txt

View File

@ -1,3 +1,119 @@
# 1.12
- Changed icon.
- Added tabs popup menu:
- Options for closing many tabs.
- Options for selecting tabs.
- Console is hidden on start.
- Fixed `yaml` tabs not working.
- Fixed `tab` + `shift + tab`ing when multiple lines are selected.
# 1.11
- Toggled `Low Processor Mode` to keep cpu/gpu usage down.
- Simplified *File List* filter display.
- *File List* filter now scans closed folders as well.
- Folder icon in *File List* changes when open/closed.
- *File Editor* now saves states of:
- Cursor position.
- Selection.
- Scroll position.
- Enabled hiding in *File Editor*.
- *Tag List* tags are sorted.
- Added `.rpy` *Renpy* file support.
- Added tab/spaces toggle.
- Fixed files with `.` in their name not showing up.
- Fixed error caused by clicking *File List* symbol for unopened file.
# 1.10
- Added cursor panel at bottom of Text Editor.
- Word counter.
- Symbol path.
- Added `insert` menu, for inserting Date.
- `ctrl + shift + u` and `ctrl + shift + l` will toggle uppercase and lowercase.
- `ctrl + shift + o` and `ctrl + shift + p` will toggle capitalize and variablize.
- Fixed `ctrl + f` not bringing up search pannel.
- Fixed error when creating new file.
- Removed Text Editor hints.
- Color tweaks.
# 1.9
- 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.
- Added `.md` highlighting for `{}`. (Not official Markdown.)
- Fixed unsaved files asking for a save path if no text entered.
- Fixed file wiping if hitting undo after loading a file.
- Fixed *no word_skip_list.txt* error.
- Folders colorized in file list.
- Display version at top right.
# 1.7
- Added option to view `Extensionless` files.
- Added Symbol path heirarchy to hint popup so you know where you are in big files:
![](README/changes_hint_toc.png)
- `ctrl + shift +`
- `U` Make selection uppercase.
- `L` Make selection lowercase.
- `O` Make selection capitalized.
- `P` Make selection variable: `My text -> my_text`
- Select file shorctut:
- `ctrl + shift + 0-9` Remember file.
- `ctrl + 0-9` Swap to file.
- Selected Symbol is now highlighted.
- Improved meta data for `.md` files.
- `search` will autoselect term when clicked.
- `search` `all` toggle added to allow only searching in the selected file.
- `search` `case` toggle added to allow searching based on upper/lower case.
- `sys` panel shows unique word list.
- `sys` panel shows time since modified.
- Can create a `word_skip_list.txt` in main folder for ignoring certain words from showing in `sys` word list.
- File List panel hint paths are localized.
- Removed `.md` function color.
- Fixed `trash` not working in exported binaries.
- Fixed dragging files into directory bug.
- Fixed temporary files not closing properly.
- Fixed close non existing tab bug.
- Fixed symbol list not redrawing after file closed.
- Fixed symbol list not redrawing after file type changed.
- Fixed focus not being grabbed when tab selected.
# 1.6
- Added `Uppercase` `Lowercase` and `Capitalize` option to popup menu for selected text.
- `ctrl + click` in Symbol View selects entire "chapter" and sub "chapters". `ctrl + shift + click` selects only one "chapter".
- `ctrl + click` in editor will auto scroll symbol view.
- Folders can be tinted.
- `word_wrap` state is saved/loaded.
- Fixed error that occured when folder containing binary was moved.
- Markdown can have a `progress` field in meta data which can be sorted in `sys`.
- Markdown meta info taken into account for `sys`
- Markdown meta info colourized.
- Markdown code color based on variable color.
- JSON comments like YAML: `"#": "comment"`
- JSON color tweaks.
# 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)

145
README.md
View File

@ -1,48 +1,62 @@
# Text Editor
Version `1.4`
Version `1.12`
![](README/readme_preview.png)
***Warning: Use at your own risk. Backup your files before testing.***
# Features
- Tabs with scroll
- File filtering
- Highlighting for common file formats (`md` `json`...)
- Tag filtering system
- Multi file tab system.
- File browser filtering.
- Highlighting for common formats (`md` `json` `ini`...)
- Tag [System](#mini-features-tags).
- File Management:
- Creation
- Renaming
- Recycling
- Auto save/load settings
- Many little *Ease of life* functions:
- Folder open/close
- Comment toggling for:
- `.md`: `<!-- -->`
- `.json`: `/* */`
- `.ini`: `; `
- `.cfg`: `; `
- `.yaml`: `# `
- Creation.
- Renaming.
- Recycling.
- Moving.
- Search files.
- Image previews.
- Auto save/load settings.
- Many little *Ease of Life* [features](#mini-features).
# Controls
- `ctrl + W` Close file
- `ctrl + shift + W` Open last closed file
- `ctrl + tab` Select next open file
- `ctrl + shift + tab` Select last open file
- `ctrl + mouse wheel` Adjust font size
- `ctrl + up` `ctrl + down` Move selected lines
- `ctrl + /` Toggle line comments
- `ctrl + M` Toggle file meta info
- `ctrl + N` New file.
- `ctrl + W` Close file.
- `ctrl + shift + W` Open last closed file .
- `ctrl + tab` Select next open file.
- `ctrl + shift + tab` Select last open file.
- `ctrl + mouse wheel` Adjust font size.
- `ctrl + shift + mouse wheel` Adjust ui font size.
- `ctrl + up` & `ctrl + down` Move selected lines.
- `ctrl + /` Toggle line comments.
- `ctrl + M` Toggle file meta info.
- `ctrl + F` Search for text in all files.
- `ctrl + shift + 0-9` Create hotkey for selected file.
- `ctrl + 0-9` Load hotkeyed file.
## Symbol View
- `ctrl + click` Select entire block + children.
- `ctrl + shift + click` Select block without children.
## Editor View
- `ctrl + click` anywhere: Scroll to nearest symbol in symbol view.
- `ctrl + click` inside brackets: Goto local file.
- `ctrl + shift +`
- `U` Make selection uppercase.
- `L` Make selection lowercase.
- `O` Make selection capitalized.
- `P` Make selection variable: `My text -> my_text`
# Symbols and Tags
To make it easier to find stuff there is a *Symbol* viewer.
*Symbols* are like *Table of Contents* for a file.
- `Markdown` uses headings `# Heading`
- `JSON` uses Dictionaries `"object": {`
- `YAML` uses Dictionaries `object: `
- `ini` `cfg` use headings `[heading]`
Symbols can have tags. Tags are added with comments.
Symbols can have *Tags*. Tags are added with comments.
- `Markdown` uses `<!-- #tag1 #tag2 -->`
- `JSON` uses `"#": "#tag1 #tag2"`
@ -59,10 +73,81 @@ This will then highlight *Files* and *Symbols* that have that tag.
# Todo
- [x] `1.1` Preserve folders open/close state.
- [x] `1.3` Search all files.
- [ ] Search file.
- [x] `1.7` Search file.
- [ ] Find and replace.
- [ ] Improve meta data based on format.
- [x] `1.7` Improve meta data based on format.
- [x] `1.2` Recycle folders.
- [x] `1.2` Unrecylce. (Toggle `view/directories/.trash` and press green arrow.
- [x] `1.2` Unrecylce. (Toggle `view/directories/.trash` and press green arrow.)
- [ ] JSON formatting.
- [ ] JSON error testing.
- [ ] Color themes.
# Mini features
## File List
### Colorize Folder
You can colorize files in a folder for easier identification. Right click a folder and select a color.
The `tab colors` toggle at the top will toggle tabs colorized by folder.
### Content Preview
You can preview the contents of a file by `ctrl + click`ing it.
The list is clickable, so you can go straight to a section of the file.
When using the filter, contents will be scanned.
## Content List (Symbols)
### Selecting Sections
`ctrl + click`ing on a symbol will select all lines contained in it, and it's childrens.
`ctrl + shift + click` a symbol will only select it's lines, not it's childrens.
## File Editor
### Follow Link
You can follow Markdown links by `ctrl + click`ing on them.
## Tags
The tag list displays all tags throughout the files.
To add a tag to a file, include a comment, with a hashtag:
- `.md`: `<!-- #tag1 #tag2 -->`
- `.json`: `{ "#": "#tag1 #tag2 }`
- `.ini` `.cfg`: `; #tag1 #tag2`
- `.yaml`: `# #tag1 #tag2`
`click` a tag to select it.
All files in the File List and symbols in the Symbol List containing the tag, will be highlighted.
`ctrl + click` to select multiple tags at once.
## Meta Panel
Toggle the meta panel with `ctrl + M`.
### Meta
The meta tab updates whenever you make a save.
It lists some information on the contents of your file.
Currently it mostly only works for Markdown.
### Search
todo
### System
Hitting refrsh will list all files in a table with sortable columns.
Select a column to sort on:
- Chapter count.
- Word count.
- Unique words.
- Progress.
- Time since modified.
### Image
In Markdown files (`.md`) you can `ctrl + click` an image to preview it.
Images look like: `![](image_url.png)` in Markdown.
# Icon credit
<a href="https://www.flaticon.com/free-icons/files-and-folders" title="files and folders icons">Files and folders icons created by Uniconlabs - Flaticon</a>

BIN
README/changes_hint_toc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
README/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 97 KiB

View File

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

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,7 +1,7 @@
tool
extends TextEdit
var editor:TE_TextEditor
var editor:TE_Editor
var _hscroll:HScrollBar
var _vscroll:VScrollBar
@ -9,6 +9,7 @@ var helper:TE_ExtensionHelper
var temporary:bool = false setget set_temporary
var modified:bool = false
var file_path:String = ""
var mouse_inside:bool = false
var symbols:Dictionary = {}
var tags:Dictionary = {}
@ -17,30 +18,130 @@ 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
func _ready():
# prefab?
if name == "file_editor":
set_process(false)
set_process_input(false)
return
var _e
if not editor:
editor = owner
_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])
_e = connect("focus_entered", self, "_focus_entered")
_e = connect("focus_exited", self, "_focus_exited")
_e = connect("mouse_entered", self, "set", ["mouse_inside", true])
_e = connect("mouse_exited", self, "set", ["mouse_inside", false])
# _e = connect("cursor_changed", self, "_cursor_changed")
if get_parent() is TabContainer:
get_parent().connect("tab_changed", self, "_tab_changed")
get_parent().connect("tab_selected", self, "_tab_changed")
# if get_parent() is TabContainer:
# get_parent().connect("tab_changed", self, "_tab_changed")
# get_parent().connect("tab_selected", self, "_tab_changed")
add_font_override("font", editor.FONT)
get_menu().add_font_override("font", editor.FONT)
var popup = get_menu()
popup.add_font_override("font", editor.FONT)
popup.add_separator()
popup.add_item("Uppercase", 1000)
# var sc = ShortCut.new()
# sc.shortcut = InputEventKey.new()
# sc.shortcut.shift = true
# sc.shortcut.control = true
# sc.shortcut.scancode = KEY_U
# popup.add_item_shortcut(sc, 1000)
popup.add_item("Lowercase")
popup.add_item("Capitalize")
popup.add_item("Variable")
# popup.add_shortcut()
_e = popup.connect("index_pressed", self, "_popup_menu")
# hint
theme = Theme.new()
theme.set_font("font", "TooltipLabel", editor.FONT_R)
# var sb = StyleBoxFlat.new()
# sb.bg_color.a = .75
# theme.set_color("font_color", "TooltipLabel", Color(0,0,0,.5))
# theme.set_stylebox("panel", "TooltipPanel", sb)
# print(theme.get_color_list("TooltipLabel"))
# print(theme.get_color_types())
TE_Util.dig(self, self, "_node")
func set_visible(v):
prints(file_path, v)
.set_visible(v)
func _focus_entered():
if not in_focus:
in_focus = true
func _focus_exited():
if in_focus:
in_focus = false
func set_cursor_state(s:Array):
cursor_set_line(s[0], s[1])
if len(s) > 2:
select(s[2], s[3], s[4], s[5])
func get_cursor_state() -> Array:
if is_selection_active():
return [
cursor_get_line(),
cursor_get_column(),
get_selection_from_line(),
get_selection_from_column(),
get_selection_to_line(),
get_selection_to_column()]
else:
return [
cursor_get_line(),
cursor_get_column()]
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()
"Lowercase": selection_lowercase()
"Capitalize": selection_capitalize()
"Variable": selection_variable()
func selection_uppercase():
var s = get_cursor_state()
insert_text_at_cursor(get_selection_text().to_upper())
set_cursor_state(s)
func selection_lowercase():
var s = get_cursor_state()
insert_text_at_cursor(get_selection_text().to_lower())
set_cursor_state(s)
func selection_variable():
var s = get_cursor_state()
insert_text_at_cursor(TE_Util.to_var(get_selection_text()))
set_cursor_state(s)
func selection_capitalize():
var s = get_cursor_state()
insert_text_at_cursor(get_selection_text().capitalize())
set_cursor_state(s)
func _node(n):
var _e
if n is HScrollBar:
@ -56,43 +157,96 @@ func _scroll_h(h:HScrollBar):
func _scroll_v(v:VScrollBar):
vscroll = v.value
func _tab_changed(index:int):
var myindex = get_index()
if index == myindex and visible:
grab_focus()
grab_click_focus()
yield(get_tree(), "idle_frame")
set_h_scroll(hscroll)
set_v_scroll(vscroll)
func get_state() -> Dictionary:
return {
var state = {
hscroll=scroll_horizontal,
vscroll=scroll_vertical
vscroll=scroll_vertical,
cursor=get_cursor_state()
}
# unsaved
if file_path == "":
state.text = text
return state
func set_state(state:Dictionary):
yield(get_tree(), "idle_frame")
if "hscroll" in state:
hscroll = state.hscroll
vscroll = state.vscroll
set_h_scroll(state.hscroll)
set_v_scroll(state.vscroll)
func _file_renamed(old_path:String, new_path:String):
if old_path == file_path:
file_path = new_path
update_name()
update_colors()
if "text" in state:
if state.text.strip_edges():
text = state.text
else:
editor._close_file(file_path)
if "cursor" in state:
set_cursor_state(state.cursor)
func _update_selected_line():
var l = cursor_get_line()
editor.select_symbol_line(0)
for i in len(symbols):
var sindex = clamp(i, 0, len(symbols))
var symbol = symbols.values()[sindex]
if i == len(symbols)-1 or symbols.keys()[i+1] > l:
editor.select_symbol_line(sindex)
break
func get_line_symbols(line:int) -> PoolStringArray:
var depth:PoolStringArray = PoolStringArray()
for i in len(symbols):
var sindex = clamp(i, 0, len(symbols))
var symbol = symbols.values()[sindex]
while len(depth) <= symbol.deep:
depth.append("")
depth[symbol.deep] = symbol.name
if i == len(symbols)-1 or symbols.keys()[i+1] > line:
depth.resize(symbol.deep+1)
break
return depth
func _input(e):
if not editor.is_plugin_active():
return
if not visible or not in_focus:
# custom tab system
if visible and in_focus and e is InputEventKey and e.pressed and e.scancode == KEY_TAB:
if is_selection_active():
var a = get_selection_from_line()
var b = get_selection_to_line()
var lines = get_selection_text().split("\n")
if e.shift:
for i in len(lines):
lines[i] = lines[i].trim_prefix(helper.get_tab())
else:
for i in len(lines):
lines[i] = helper.get_tab() + lines[i]
insert_text_at_cursor(lines.join("\n"))
select(a, 0, b, len(get_line(b)))
else:
insert_text_at_cursor(helper.get_tab())
get_tree().set_input_as_handled()
if not visible or not in_focus or not mouse_inside:
return
# show current position in heirarchy as editor hint
if e is InputEventMouseButton and not e.pressed:
_update_selected_line()
if e is InputEventMouseButton and not e.pressed and e.control:
var line:String = get_line(cursor_get_line())
# click link
var ca = line.find("(")
var cb = line.find_last(")")
if ca != -1 and cb != -1:
@ -105,29 +259,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:
@ -170,6 +301,30 @@ func _input(e):
select(f+1, 0, t+1, len(get_line(t+1)))
cursor_set_line(cursor_get_line()+1, false)
if e.scancode == KEY_U:
if get_selection_text() == get_selection_text().to_upper():
selection_lowercase()
else:
selection_uppercase()
if e.scancode == KEY_L:
if get_selection_text() == get_selection_text().to_lower():
selection_uppercase()
else:
selection_lowercase()
if e.scancode == KEY_O:
if get_selection_text() == get_selection_text().capitalize():
selection_variable()
else:
selection_capitalize()
if e.scancode == KEY_P:
if get_selection_text() == TE_Util.to_var(get_selection_text()):
selection_capitalize()
else:
selection_variable()
func _unhandled_key_input(e):
if not visible:
return
@ -179,20 +334,35 @@ func _unhandled_key_input(e):
helper.toggle_comment(self)
get_tree().set_input_as_handled()
func _file_renamed(old_path:String, new_path:String):
if old_path == file_path:
file_path = new_path
update_name()
update_colors()
func _file_selected(p:String):
if not p:
if p != file_path:
return
if p == file_path:
grab_focus()
grab_click_focus()
update_symbols()
update_heading()
func goto_line(line:int):
# yield(get_tree(), "idle_frame")
#
# 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, bottom:bool=true):
# force scroll to bottom so selected line will be at top
if bottom:
cursor_set_line(get_line_count())
cursor_set_line(line)
_update_selected_line()
func text_changed():
if last_selected:
@ -224,6 +394,8 @@ func set_temporary(t):
update_name()
func update_symbols():
update_helper()
symbols.clear()
tags.clear()
@ -239,38 +411,56 @@ func update_symbols():
else:
tags[tag] += 1
# var _e = TE_Util.sort(tags, true)
editor._file_symbols_updated(file_path)
func close():
if modified:
if not editor.popup_unsaved.visible:
var _e
_e = editor.popup_unsaved.connect("confirmed", self, "_popup", ["close"], CONNECT_ONESHOT)
_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 = editor.load_file(path)
clear_undo_history()
update_colors()
update_name()
func update_colors():
clear_colors()
func update_helper():
helper = editor.get_extension_helper(file_path)
helper.apply_colors(editor, self)
func update_colors():
clear_colors()
update_helper()
func _created_nonexisting(fp:String):
file_path = fp
modified = false
update_name()
update_symbols()
func save_file():
if file_path == "" and text:
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
@ -284,12 +474,35 @@ func save_file():
update_symbols()
func update_name():
var n = file_path.get_file().split(".", true, 1)[0]
var n:String
if file_path == "":
n = "UNSAVED"
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)
update_heading()
name = n
func update_heading():
if Engine.editor_hint:
@ -306,5 +519,5 @@ func update_heading():
OS.set_window_title("%s - Text Editor" % f)
func needs_save() -> bool:
return modified or not File.new().file_exists(file_path)
return modified or (not File.new().file_exists(file_path) and text)

View File

@ -0,0 +1,101 @@
tool
extends Node
const DIM:Color = Color.webgray
const CLR:Color = Color.white
onready var editor:TE_Editor = owner
var tab:TextEdit = null
var typed:String = ""
var word_count:int = 0
func _ready():
var _e
yield(get_tree(), "idle_frame")
_e = editor.tab_parent.connect("tab_changed", self, "_tab_changed")
editor.override_fonts($l)
editor.override_fonts($m)
editor.override_fonts($r)
func _tab_changed(index:int):
if tab and is_instance_valid(tab) and not tab.is_queued_for_deletion():
tab.disconnect("cursor_changed", self, "_cursor_changed")
tab = null
var new_tab = editor.tab_parent.get_child(index)
if tab == new_tab:
return
tab = new_tab
var _e
_e = tab.connect("cursor_changed", self, "_cursor_changed")
# _e = tab.connect("text_changed", self, "_text_changed")
#
#func _text_changed():
## print("text changed")
# pass
func _input(event):
if event is InputEventKey and event.pressed and tab and is_instance_valid(tab) and tab.has_focus():
if not event.scancode == KEY_BACKSPACE:
if char(event.scancode) in " .?!-":
word_count += 1
typed = ""
else:
typed += char(event.scancode)
_cursor_changed()
func _cursor_changed():
var l_lines:PoolStringArray = PoolStringArray()
var m_lines:PoolStringArray = PoolStringArray()
var r_lines:PoolStringArray = PoolStringArray()
var l:RichTextLabel
if tab.is_selection_active():
var seltext:String = tab.get_selection_text()
var words = {}
var word_count:int = TE_Util.count_words(seltext, words, null, false)
m_lines.append(kv("chars", len(seltext)))
m_lines.append(kv("words", word_count))
var l1 = tab.get_selection_from_line() + 1
var l2 = tab.get_selection_to_line() + 1
var c1 = tab.get_selection_from_column()
var c2 = tab.get_selection_to_column()
if l1 == l2:
l_lines.append(kv("line", l1))
l_lines.append(kv("char", "%s - %s" % [c1, c2]))
else:
l_lines.append(clr("line: ", DIM) + clr(str(l1), CLR) + clr(":", DIM) + clr(str(c1), CLR))
l_lines.append(clr("->", Color.webgray))
l_lines.append(clr("line: ", DIM) + clr(str(l2), CLR) + clr(":", DIM) + clr(str(c2), CLR))
m_lines.append(kv("lines", abs(l2 - l1) + 1))
else:
l_lines.append(kv("line", tab.cursor_get_line() + 1))
l_lines.append(kv("char", tab.cursor_get_column()))
var depth = tab.get_line_symbols(tab.cursor_get_line())
for i in len(depth):
depth[i] = b(depth[i])
r_lines.append(depth.join(clr("/", DIM)))
m_lines.append(kv("typed", word_count))
$l.set_bbcode(l_lines.join(" "))
$m.set_bbcode("[center]" + m_lines.join(" "))
$r.set_bbcode("[right]" +r_lines.join(" "))
func kv(k:String, v) -> String:
var clr2 = Color.white
if v is int:
v = TE_Util.commas(v)
return clr(k + ": ", DIM) + clr(str(v), clr2)
func b(t:String) -> String: return "[b]%s[/b]" % t
func i(t:String) -> String: return "[i]%s[/i]" % t
func u(t:String) -> String: return "[u]%s[/u]" % t
func clr(t:String, c:Color) -> String: return "[color=#%s]%s[/color]" % [c.to_html(), t]

View File

@ -1,7 +1,9 @@
extends TabContainer
onready var editor:TE_TextEditor = owner
onready var editor:TE_Editor = owner
var mouse:bool = false
var last_tab_index:int = -1
var tab_menu:PopupMenu
func _ready():
if not editor.is_plugin_active():
@ -10,9 +12,72 @@ func _ready():
var _e
_e = connect("mouse_entered", self, "set", ["mouse", true])
_e = connect("mouse_exited", self, "set", ["mouse", false])
_e = connect("tab_changed", self, "_tab_changed")
_e = connect("pre_popup_pressed", self, "update_popup")
add_font_override("font", editor.FONT_R)
tab_menu = owner.get_node("popup_tab_menu")
tab_menu.connect("index_pressed", self, "_popup_selected")
func _tab_changed(index):
var tab = get_child(index)
tab.grab_focus()
last_tab_index = index
func _popup_selected(index:int):
var tindex := tab_menu.get_item_id(index)
if tindex >= 100:
current_tab = tindex - 100
return
match tindex:
0: # close
get_child(hovered_tab_index).close()
1: # close others
var all_tabs = owner.get_tabs()
var hovered = get_child(hovered_tab_index)
for tab in all_tabs:
if tab != hovered:
tab.close()
2: # close left
var all_tabs = owner.get_tabs()
for i in range(0, hovered_tab_index):
all_tabs[i].close()
current_tab = 0
3: # close right
var all_tabs = owner.get_tabs()
for i in range(hovered_tab_index+1, len(all_tabs)):
all_tabs[i].close()
var hovered_tab_index:int
func update_popup(index:int=current_tab):
var all_tabs = owner.get_tabs()
hovered_tab_index = index
tab_menu.clear()
tab_menu.rect_size = Vector2.ZERO
tab_menu.add_item("Close", 0)
tab_menu.add_item("Close others", 1)
if index > 0:
tab_menu.add_item("Close all to left", 2)
if index < len(all_tabs)-1:
tab_menu.add_item("Close all to right", 3)
tab_menu.add_separator()
var i = 0
for tab in owner.get_tabs():
tab_menu.add_item(tab.name, 100+i)
i += 1
func _input(e):
if not editor.is_plugin_active():
return
@ -26,6 +91,14 @@ func _input(e):
next()
get_tree().set_input_as_handled()
elif e.button_index == BUTTON_RIGHT:
var index := get_tab_idx_at_point(get_local_mouse_position())
if index != -1:
update_popup(index)
tab_menu.rect_global_position = get_global_mouse_position()
tab_menu.popup()
get_tree().set_input_as_handled()
if e is InputEventKey and e.pressed and e.control and e.scancode == KEY_TAB:
if e.shift:
prev()

View File

@ -7,6 +7,8 @@ onready var dir_popup:PopupMenu = $dir_popup
const DragLabel = preload("res://addons/text_editor/TE_DragLabel.gd")
var drag_label:RichTextLabel
export var p_filter:NodePath
var filter:String = ""
var selected:Array = []
var dragging:Array = []
var drag_start:Vector2
@ -20,6 +22,10 @@ func _ready():
_e = editor.connect("file_selected", self, "_file_selected")
_e = editor.connect("file_renamed", self, "_file_renamed")
var le:LineEdit = get_node(p_filter)
_e = le.connect("text_changed", self, "_filter_changed")
le.add_font_override("font", editor.FONT_R)
# file popup
file_popup.clear()
file_popup.rect_size = Vector2.ZERO
@ -33,9 +39,14 @@ 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")
dir_popup.add_separator()
dir_popup.add_item("Tint Yellow")
dir_popup.add_item("Tint Red")
dir_popup.add_item("Tint Blue")
dir_popup.add_item("Tint Green")
dir_popup.add_item("Reset Tint")
_e = dir_popup.connect("index_pressed", self, "_dir_popup")
dir_popup.add_font_override("font", editor.FONT)
@ -44,6 +55,10 @@ func _ready():
add_font_override("italics_font", editor.FONT_I)
add_font_override("bold_italics_font", editor.FONT_BI)
func _filter_changed(t:String):
filter = t
_redraw()
func _dir_popup(index:int):
var type = selected[0]
var file = selected[1]
@ -51,9 +66,32 @@ func _dir_popup(index:int):
file = file.file_path
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)
"New File":
editor.popup_create_file(file)
"Remove":
editor.recycle(file, type == "f")
"Tint Yellow":
selected[1].tint = "yellow"#Color.gold
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
"Tint Red":
selected[1].tint = "red"#Color.tomato
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
"Tint Blue":
selected[1].tint = "blue"#Color.deepskyblue
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
"Tint Green":
selected[1].tint = "green"#Color.chartreuse
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
"Reset Tint":
selected[1].tint = ""#Color.white
editor.emit_signal("dir_tint_changed", selected[1].file_path)
_redraw()
func _file_popup(index:int):
var type = selected[0]
@ -70,7 +108,7 @@ func _file_popup(index:int):
"Remove":
if type == "f":
editor.recycle(file)
editor.recycle(file, true)
_:
selected = []
@ -95,14 +133,21 @@ func _input(e:InputEvent):
var file = meta_hovered[1]
if e.button_index == BUTTON_LEFT:
if e.pressed:
if type in ["f", "d"]:
if type == "f" and Input.is_key_pressed(KEY_CONTROL):
editor.file_data[file].open = not editor.file_data[file].open
_redraw()
else:
var file_path = file if type == "f" else file.file_path
if file_path.begins_with(editor.PATH_TRASH):
return # can't move recycling
# can't move recycling
if editor.is_trash_path(file_path):
return
# select for drag
else:
dragging = meta_hovered
@ -110,14 +155,19 @@ func _input(e:InputEvent):
drag_label.editor = editor
editor.add_child(drag_label)
else:
if type == "f" and Input.is_key_pressed(KEY_CONTROL):
pass
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
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)
@ -132,12 +182,19 @@ func _input(e:InputEvent):
# unrecycle
"unrecycle":
editor.unrecycle(file)
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()
elif e.button_index == BUTTON_RIGHT:
@ -162,69 +219,139 @@ var lines:PoolStringArray = PoolStringArray()
func _redraw():
lines = PoolStringArray()
_draw_dir(editor.file_list[""], 0)
lines.append_array(_draw_dir(editor.file_list[""], 0))
set_bbcode(lines.join("\n"))
const FOLDER:String = "🗀" # not visible in godot
func _draw_dir(dir:Dictionary, deep:int):
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_CLOSED:String = "🗀" # not visible in Godot.
const FOLDER_OPEN:String = "🗁" # not visible in Godot.
func _draw_dir(dir:Dictionary, deep:int) -> Array:
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 space = ""
var file:String = dir.file_path
var head:String = "" if dir.open else ""
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 += " " + meta(clr("", Color.yellowgreen), ["unrecycle", dir], file)
lines.append(clr(link, Color.white.darkened(dimmest)))
space = clr("".repeat(deep), Color.white.darkened(.8))
var head:String = "" if dir.open else ""
var fold:String = FOLDER_OPEN if dir.open else FOLDER_CLOSED
var dname = b(_dull_nonwords(file.get_file(), tint.darkened(0 if editor.is_dir_tagged(dir) else 0.5), dull))
dname = clr("", dull) + dname + clr("", dull)
head = clr(space+fold, Color.gold) + clr(head, Color.white.darkened(.5))
head += " %s" % dname
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)
var out = []
var sel = editor.get_selected_tab()
sel = sel.file_path if sel else ""
if dir.open:
if dir.open or filter:
# draw dirs
for path in dir.dirs:
var file_path = dir.all[path]
if file_path is Dictionary and file_path.show:
_draw_dir(file_path, deep+1)
if file_path is Dictionary and (file_path.show or filter):
out.append_array(_draw_dir(file_path, deep+1))
# draw files
var last = len(dir.files)-1
for i in len(dir.files):
var file_path = dir.files[i]
file = file_path.get_file()
var p = file.split(".", true, 1)
var fname = file_path.get_file()
file = fname
var p = [file, ""] if not "." in file else file.split(".", true, 1)
file = p[0]
var ext = p[1]
var is_selected = file_path == sel
var is_opened = editor.is_opened(file_path)
var color = Color.white
head = "┣╸" if i != last else "┗╸"
var color = tint
head = "" if filter else "┣╸" if i != last else "┗╸"
if "readme" in file.to_lower():
var fname_lower = fname.to_lower()
if "readme" in fname_lower:
head = "🛈"
if is_selected:
head = ""
elif is_opened:
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 = clr("." + ext, Color.white.darkened(.65))
var line = space + head + file + ext
lines.append(meta(line, ["f", file_path], file_path))
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)
var hint_path = editor.get_localized_path(file_path)
var file_lines = []
if not editor._scanning:
var fdata = editor.get_file_data(file_path)
var symbols = fdata.symbols.values()
for j in range(1, len(symbols)):
if fdata.open or filter:
var sdata:Dictionary = symbols[j]
var sname:String = sdata.name
var index = sname.to_lower().find(filter)
if filter and index == -1:
continue
var sname_highlighted = TE_Util.highlight(sname, index, len(filter), TE_Util.hue_shift(dull_tint, -.075), Color.white)
var s = clr(" @ " + "-".repeat(sdata.deep), dull) + sname_highlighted
var h = hint_path + " @" + sname
file_lines.append(meta(space + s, ["fs", file_path, j], h))
if filter:
var index = fname_lower.find(filter)
if index != -1:
line = TE_Util.highlight(fname, index, len(filter), dull_tint, Color.white)
# show file name if not filtering, or if
if not filter or file_lines:
file_lines.push_front(meta(space + head + line, ["f", file_path], hint_path))
# file_lines.push_front(space + head + line)
out.append_array(file_lines)
# show folder name if not filtering, or if filter catches a sub file or subsymbol
if not filter or out:
out.push_front(link)
return out

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():
@ -33,6 +33,5 @@ func _lost_focus():
func _enter(t:String):
if fr:
print("calling %s with %s" % [fr, t])
fr.call_func(t)
hide()

View File

@ -17,6 +17,9 @@ func _file_saved(_file_path:String):
_redraw()
func _redraw():
if not visible:
return
var tab = editor.get_selected_tab()
if tab:
tab.helper.generate_meta(tab, self)

View File

@ -1,19 +1,39 @@
tool
extends TabContainer
onready var editor:TE_TextEditor = owner
onready var editor:TE_Editor = owner
func _ready():
if not editor.is_plugin_active():
return
set_visible(false)
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
if e.control and e.pressed:
match e.scancode:
# show this menu
KEY_M:
set_visible(not get_parent().visible)
get_tree().set_input_as_handled()
# find menu
KEY_F:
set_visible(true)
select_tab($search)
$search/rte.select()
func set_visible(v:bool):
get_parent().visible = v
func select_tab(tab:Node):
current_tab = tab.get_index()
func show_image(file_path:String):
get_parent().visible = true
select_tab($image)
$image/image.texture = TE_Util.load_image(file_path)

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 = []
@ -97,6 +97,7 @@ func table(rows) -> String:
func b(t:String) -> String: return "[b]%s[/b]" % t
func i(t:String) -> String: return "[i]%s[/i]" % t
func u(t:String) -> String: return "[u]%s[/u]" % t
func clr(t:String, c:Color) -> String: return "[color=#%s]%s[/color]" % [c.to_html(), t]
func center(t:String): return "[center]%s[/center]" % t

View File

@ -3,44 +3,97 @@ 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_on_index:int = 1
var sort_reverse:Dictionary = { id=true, chaps=true, words=true, uwords=true, "%":true, modified=true }
var skip_words:PoolStringArray
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)
func _update(f):
set_process(true)
var _e = btn.connect("pressed", self, "_update")
func _process(_delta):
func _update():
chapter_info.clear()
# load block list
var skip_list = editor.current_directory.plus_file("word_skip_list.txt")
if File.new().file_exists(skip_list):
skip_words = TE_Util.load_text(skip_list).replace("\n", " ").strip_edges().to_lower().split(" ")
else:
skip_words = PoolStringArray()
for path in editor.file_paths:
var file = path.get_file()
var ext = file.get_extension()
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)
const WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
const MONTHS = ["Januaray", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
func _chapter(path:String, line:int, id:String):
chapter_info.append({ path=path, line=line, id=id, words=0, chars=0, unique=0 })
const TIMES:Dictionary = {
"second": 60,
"minute": 60,
"hour": 24,
"day": INF
}
func get_time(t:int) -> String:
for k in TIMES:
if t < TIMES[k]:
return "%s %s ago" % [t, k + ("" if t == 1 else "s")]
t /= TIMES[k]
return "???"
func _process_md(path:String):
var lines = TE_Util.load_text(path).split("\n")
_chapter(path, 0, "NOH")
var file_time = File.new().get_modified_time(path)
var curr_time = OS.get_unix_time()
var diff_time = curr_time - file_time
var time_nice = get_time(diff_time)
if false and diff_time > 9999999:
time_nice = OS.get_datetime_from_unix_time(file_time)
time_nice.weekday = WEEKDAYS[time_nice.weekday-1].substr(0, 3).to_lower()
time_nice.month = MONTHS[time_nice.month-1].substr(0, 3).to_lower()
time_nice.hour12 = str(time_nice.hour % 12)
time_nice.ampm = "am" if time_nice.hour > 12 else "pm"
time_nice = "{weekday} {month} {day}, {year} {hour12}:{minute}:{second}{ampm}".format(time_nice)
var out = { path=path, line=0, id=editor.get_localized_path(path), modified=file_time, time_nice=time_nice, words=0, uwords={}, chaps=0, "%":0.0 }
chapter_info.append(out)
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("---"):
if ":" in lines[i]:
var p = lines[i].split(":", true, 1)
var k = p[0].strip_edges()
var v = p[1].strip_edges()
match k:
"name":
out.id = v
"prog", "progress":
out["%"] = float(v.replace("%", ""))
i += 1
# skip comments
elif "<!--" in lines[i]:
pass
# skip code blocks
elif lines[i].begins_with("~~~") or lines[i].begins_with("```"):
var head = lines[i].substr(0, 3)
@ -51,28 +104,32 @@ 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()
out.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)
out.words += TE_Util.count_words(lines[i], out.uwords, skip_words)
i += 1
func clean_word(w:String):
var out = ""
for c in w:
if c in "abcdefghijklmnopqrstuvwxyz":
out += c
return out
# sort word counts
TE_Util.sort_vals(out.uwords)
var words = PoolStringArray(out.uwords.keys())
var words_top = words
if len(words_top) > 16:
words_top.resize(16)
out.uwords = words_top.join(" ")
var word_lines = [""]
for word in words:
if len(word_lines[-1]) >= 64:
word_lines.append("")
if word_lines[-1]:
word_lines[-1] += " "
word_lines[-1] += word
out.uwords_all = PoolStringArray(word_lines).join("\n")
func _clicked(args):
match args[0]:
@ -80,6 +137,7 @@ func _clicked(args):
var key = args[1]
if sort_on != key:
sort_on = key
sort_on_index = sort_reverse.keys().find(sort_on)
else:
sort_reverse[key] = not sort_reverse[key]
@ -87,35 +145,46 @@ 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 ch1 = lerp(c1, Color.yellowgreen, .5)
var ch2 = lerp(c2, Color.yellowgreen, .5)
var cols = ["id", "chaps", "words", "uwords", "%", "modified"]
push_align(RichTextLabel.ALIGN_CENTER)
push_table(3)
for id in ["id", "words", "unique"]:
push_table(len(cols))
add_constant_override("table_hseparation", 8)
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,26 +193,50 @@ 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
var clrh = ch1 if i%2==0 else ch2
# id
push_cell()
push_color(clr)
push_meta(add_meta(["goto", item.path, item.line], item.path))
push_color(clrh if sort_on_index == 0 else clr)
push_meta(add_meta(["goto", item.path, item.line], item.path + "\n" + item.uwords_all))
add_text(item.id)
pop()
pop()
pop()
# word cound
for w in ["words", "unique"]:
# chapters
push_cell()
push_color(clr)
add_text(TE_Util.commas(item[w]))
push_color(clrh if sort_on_index == 1 else clr)
add_text(TE_Util.commas(item.chaps))
pop()
pop()
# word cound
push_cell()
push_color(clrh if sort_on_index == 2 else clr)
add_text(TE_Util.commas(item.words))
pop()
pop()
# unique words
push_cell()
push_color(clrh if sort_on_index == 3 else clr)
add_text(item.uwords)
pop()
pop()
# percent
push_cell()
push_color(clrh if sort_on_index == 4 else clr)
add_text(str(int(item["%"])))
pop()
pop()
# time
push_cell()
push_color(clrh if sort_on_index == 5 else clr)
add_text(item.time_nice)
pop()
pop()

View File

@ -1,7 +1,9 @@
tool
extends "res://addons/text_editor/TE_RichTextLabel.gd"
onready var line_edit:LineEdit = get_parent().get_node("le")
onready var line_edit:LineEdit = get_parent().get_node("c/le")
onready var all_toggle:CheckBox = get_parent().get_node("c/all")
onready var case_toggle:CheckBox = get_parent().get_node("c/case")
var console_urls:Array = []
var last_search:String = ""
@ -10,26 +12,33 @@ func _ready():
var _e
_e = line_edit.connect("text_entered", self, "_text_entered")
# fix fonts
line_edit.add_font_override("font", editor.FONT_R)
all_toggle.add_font_override("font", editor.FONT_R)
case_toggle.add_font_override("font", editor.FONT_R)
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:
func select():
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()
line_edit.select_all()
func _clicked(args):
match args[0]:
"goto":
var tab = editor.open_file(args[1])
var tab:TextEdit = editor.open_file(args[1])
editor.select_file(args[1])
tab.goto_line(int(args[2]))
yield(get_tree(), "idle_frame")
# goto line
var hfrom = int(args[2])
var line = int(args[3])
tab.goto_line(hfrom)
tab.goto_line(line, false)
# select area
var from = int(args[4])
var lenn = int(args[5])
tab.select(line, from, line, from + lenn)
tab.cursor_set_line(line)
tab.cursor_set_column(from)
func _text_entered(search_for:String):
last_search = search_for
@ -44,61 +53,111 @@ func _text_entered(search_for:String):
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)
l = meta(l, ["goto", file_path, 0, 0, 0], file_path)
bbcode.append(l)
for j in len(found[file_path]):
var all_found = found[file_path]
for j in len(all_found):
var result = found[file_path][j]
var got_lines = result[0]
var line_index = result[1]
var char_index = result[2]
var highlight_from = result[1]
var line_index = result[2]
var char_index = result[3]
if j != 0:
bbcode.append("\t" + clr("...", Color.gray))
bbcode.append(clr(" %s/%s" % [j+1, len(all_found)], Color.orange))
for i in len(got_lines):
l = ""
var highlight = got_lines[i][0]
var lindex = got_lines[i][1]
var ltext = got_lines[i][2]
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)
if highlight:
# var line:String = ltext
# var head:String = line.substr(0, char_index)
# var midd:String = line.substr(char_index, len(search_for))
# var tail:String = line.substr(char_index+len(search_for))
# head = clr(head, Color.white.darkened(.25))
# midd = b(clr(midd, Color.white))
# tail = clr(tail, Color.white.darkened(.25))
elif line_index-2+i >= 0:
l = "\t" + clr(str(line_index-2+i+1) + ": ", Color.gray) + got_lines[i]
var h = TE_Util.highlight(ltext, char_index, len(search_for), Color.white.darkened(.25), Color.white)
l = "\t" + clr(str(lindex) + ": ", Color.white.darkened(.25)) + h
else:
l = "\t" + clr(str(lindex) + ": ", Color.white.darkened(.65)) + clr(ltext, Color.white.darkened(.5))
if l:
l = meta(l, ["goto", file_path, line_index])
l = meta(l, ["goto", file_path, highlight_from, line_index, char_index, len(search_for)])
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 out = {}
var search_for_l:String
if case_toggle.pressed:
search_for_l = search_for
else:
search_for_l = search_for.to_lower()
var paths:Array
# search all
if all_toggle.pressed:
paths = editor.file_paths
# only search selected
else:
var sel = editor.get_selected_file()
if not sel:
var err_msg = "no file open to search"
editor.console.err(err_msg)
push_error(err_msg)
return out
else:
paths = [sel]
for path in paths:
var lines = TE_Util.load_text(path).split("\n")
for line_index in len(lines):
var line:String = lines[line_index].to_lower()
var line:String = lines[line_index]
# make lowercase, if case doesn't matter
if not case_toggle.pressed:
line = line.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()
if not path in out:
out[path] = []
var preview_lines = [[true, line_index, lines[line_index]]]
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("")
# previous few lines before a blank
for i in range(1, 3):
if line_index-i >= 0:
if not lines[line_index-i].strip_edges():
break
highlight_from = line_index-i
preview_lines.push_front([false, line_index-i, lines[line_index-i]])
# next few lines before a blank
for i in range(1, 3):
if line_index+i < len(lines):
if not lines[line_index+i].strip_edges():
break
preview_lines.push_back([false, line_index+i, lines[line_index+i]])
# lines, index in file, index in line
found[path].append([preview_lines, line_index, char_index])
return found
out[path].append([preview_lines, highlight_from, line_index, char_index])
return out

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,26 @@
tool
extends "res://addons/text_editor/TE_RichTextLabel.gd"
var hscrolls:Dictionary = {}
var selected_line:int = 0
var current_file:String = ""
var filter:String = ""
export var p_filter:NodePath
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 = editor.connect("file_closed", self, "_file_closed")
_e = editor.connect("file_renamed", self, "_file_renamed")
_e = editor.connect("selected_symbol_line", self, "_selected_symbol_line")
_e = get_v_scroll().connect("value_changed", self, "_scrolling")
var le:LineEdit = get_node(p_filter)
_e = le.connect("text_changed", self, "_filter_changed")
le.add_font_override("font", editor.FONT_R)
add_font_override("normal_font", editor.FONT_R)
add_font_override("bold_font", editor.FONT_B)
@ -13,8 +29,61 @@ func _ready():
call_deferred("_redraw")
func _filter_changed(t:String):
filter = t.to_lower()
_redraw()
func _selected_symbol_line(line:int):
selected_line = clamp(line, 0, get_line_count())
scroll_to_line(clamp(line-1, 0, get_line_count()-1))
_redraw()
func _file_selected(file_path:String):
current_file = file_path
yield(get_tree(), "idle_frame")
get_v_scroll().value = hscrolls.get(file_path, 0)
func _file_renamed(old:String, new:String):
current_file = new
yield(get_tree(), "idle_frame")
_redraw()
func _file_closed(file_path:String):
if file_path == current_file:
current_file = ""
_redraw()
func _scrolling(v):
hscrolls[editor.get_selected_file()] = get_v_scroll().value
func _clicked(args:Array):
var te:TextEdit = editor.get_selected_tab()
# select entire symbol block?
if Input.is_key_pressed(KEY_CONTROL):
var tab = editor.get_selected_tab()
var symbols = {} if not tab else tab.symbols
var line_index:int = args[1]
var symbol_index:int = symbols.keys().find(line_index)
var next_line:int
# select sub symbol blocks?
if not Input.is_key_pressed(KEY_SHIFT):
var deep = symbols[line_index].deep
while symbol_index < len(symbols)-1 and symbols.values()[symbol_index+1].deep > deep:
symbol_index += 1
if symbol_index == len(symbols)-1:
next_line = tab.get_line_count()-1
else:
next_line = symbols.keys()[symbol_index+1]-1
tab.select(line_index, 0, next_line, len(tab.get_line(next_line)))
te.goto_line(line_index)
else:
te.goto_line(args[1])
func _redraw():
@ -37,22 +106,37 @@ func _redraw():
else:
var t = PoolStringArray()
var i = -1
for line_index in symbols:
i += 1
if line_index == -1:
continue # special file chapter
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 filter and not filter in symbol_info.name.to_lower():
continue
if symbol_info.name.begins_with("*") and symbol_info.name.ends_with("*"):
cl = editor.get_symbol_color(deep, -.33)
elif symbol_info.name.begins_with('"') and symbol_info.name.ends_with('"'):
cl = editor.get_symbol_color(deep, .33)
else:
cl = editor.get_symbol_color(deep)
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))
var text = clr(meta(space + symbol_info.name, [symbol_info, line_index], tags), cl)
if i == selected_line:
text = b(u(text))
t.append(text)
set_bbcode(t.join("\n"))

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

@ -16,40 +16,37 @@ 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)
func sort_tags(tags:Dictionary):
var sorter:Array = []
for tag in tags:
sorter.append([tag, tags[tag]])
if not Input.is_key_pressed(KEY_CONTROL):
editor.tags_enabled.clear()
sorter.sort_custom(self, "_sort_tags")
editor.enable_tag(tag, not was_enabled)
tags.clear()
for item in sorter:
tags[item[0]] = item[1]
return tags
func _sort_tags(a, b):
return a[0] < b[0]
#func sort_tags(tags:Dictionary):
# var sorter:Array = []
# for tag in tags:
# sorter.append([tag, tags[tag]])
#
# sorter.sort_custom(self, "_sort_tags")
#
# tags.clear()
# for item in sorter:
# tags[item[0]] = item[1]
# return tags
#
#func _sort_tags(a, b):
# return a[0] < b[0]
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)
# sort_tags(tags)
if not tags:
set_bbcode("[color=#%s][i][center]*No tags*" % [Color.webgray.to_html()])
@ -59,7 +56,7 @@ func _redraw():
var count_color1 = Color.tomato.to_html()
var count_color2 = Color.tomato.darkened(.75).to_html()
for tag in tags:
var count = editor.tag_counts[tag]
var count = editor.tags[tag]
var enabled = editor.is_tag_enabled(tag)
var x = tag

View File

@ -1,5 +1,77 @@
class_name TE_Util
class Sorter:
var d:Dictionary
var a:Array = []
func _init(dict:Dictionary):
d = dict
for k in d:
a.append([k, d[k]])
func on_keys(reverse:bool=false):
a.sort_custom(self, "_sort_keys_rev" if reverse else "_sort_keys")
return _out()
func on_vals(reverse:bool=false):
a.sort_custom(self, "_sort_vals_rev" if reverse else "_sort_vals")
return _out()
func _sort_keys(a, b): return a[0] > b[0]
func _sort_keys_rev(a, b): return a[0] < b[0]
func _sort_vals(a, b): return a[1] > b[1]
func _sort_vals_rev(a, b): return a[1] < b[1]
func _out() -> Dictionary:
d.clear()
for item in a:
d[item[0]] = item[1]
return d
static func sort_keys(d:Dictionary, reverse:bool=false): return Sorter.new(d).on_keys(reverse)
static func sort_vals(d:Dictionary, reverse:bool=false): return Sorter.new(d).on_vals(reverse)
static func count_words(text:String, counter:Dictionary, skip_words=null, stop_words:bool=true):
var word_count:int = 0
for sentence in text.split("."):
for word in sentence.split(" "):
word = _sanitize_word(word)
if not word: continue
if stop_words and word in TE_StopWords.STOP_WORDS: continue
if skip_words and word in skip_words: continue
word_count += 1
if not word in counter:
counter[word] = 1
else:
counter[word] += 1
return word_count
static func _sanitize_word(word:String):
var out = ""
var has_letter = false
for c in word.to_lower():
if c in "abcdefghijklmnopqrstuvwxyz":
out += c
has_letter = true
elif c in "-'0123456789":
out += c
if not has_letter:
return ""
if out.ends_with("'s"):
return out.substr(0, len(out)-2)
return out
static func to_var(s:String) -> String:
return s.to_lower().replace(" ", "_")
static func load_text(path:String) -> String:
var f:File = File.new()
if f.file_exists(path):
@ -21,6 +93,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)
@ -57,23 +139,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()
@ -86,6 +200,21 @@ static func file_size(path:String) -> String:
static func hue_shift(c:Color, h:float) -> Color:
return c.from_hsv(wrapf(c.h + h, 0.0, 1.0), c.s, c.v, c.a)
static func highlight(line:String, start:int, length:int, default_color:Color, highlight_color:Color) -> String:
var head:String = line.substr(0, start)
var midd:String = line.substr(start, length)
var tail:String = line.substr(start + length)
head = clr(head, default_color)
midd = b(clr(midd, highlight_color))
tail = clr(tail, default_color)
return head + midd + tail
static func b(t:String) -> String: return "[b]%s[/b]" % t
static func clr(t:String, c:Color) -> String: return "[color=#%s]%s[/color]" % [c.to_html(), t]
#static func saturate(c:Color, s:float=1.0, v:float=1.0) -> Color:
# return c.from_hsv(c.h, c.s * s, c.v * v, c.a)
#static func sort(d, reverse:bool=false):
# return Dict.new(d).sort(reverse)
#

View File

@ -1,7 +1,7 @@
[gd_scene load_steps=24 format=2]
[gd_scene load_steps=29 format=2]
[ext_resource path="res://addons/text_editor/TE_Console.gd" type="Script" id=1]
[ext_resource path="res://addons/text_editor/TE_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]
@ -17,26 +17,34 @@
[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]
[ext_resource path="res://addons/text_editor/TE_FileInfoLabel.gd" type="Script" id=18]
[ext_resource path="res://addons/text_editor/TE_RichTextLabel.gd" type="Script" id=19]
[ext_resource path="res://addons/text_editor/te_empty_style.tres" type="StyleBox" id=20]
[sub_resource type="Theme" id=1]
[sub_resource type="Theme" id=8]
[sub_resource type="Theme" id=9]
TooltipLabel/fonts/font = ExtResource( 12 )
[sub_resource type="Theme" id=2]
[sub_resource type="Theme" id=10]
TooltipLabel/fonts/font = ExtResource( 12 )
[sub_resource type="Theme" id=3]
[sub_resource type="Theme" id=11]
TooltipLabel/fonts/font = ExtResource( 12 )
[sub_resource type="Theme" id=4]
[sub_resource type="Theme" id=12]
TooltipLabel/fonts/font = ExtResource( 12 )
[sub_resource type="Theme" id=5]
[sub_resource type="Theme" id=13]
TooltipLabel/fonts/font = ExtResource( 12 )
[sub_resource type="Theme" id=6]
[sub_resource type="Theme" id=14]
TooltipLabel/fonts/font = ExtResource( 12 )
[node name="text_editor" type="Control"]
[sub_resource type="Theme" id=15]
TooltipLabel/fonts/font = ExtResource( 12 )
[node name="editor" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
@ -45,6 +53,13 @@ script = ExtResource( 2 )
__meta__ = {
"_edit_use_anchors_": false
}
p_tab_parent = NodePath("c/div1/div2/c/c/c2/tab_container")
p_tab_prefab = NodePath("file_editor")
p_console = NodePath("c/div1/div2/c/c/c/meta_tabs/console")
p_progress_bar = NodePath("c/c/c/progress")
p_menu_file = NodePath("c/c/c/file")
p_menu_view = NodePath("c/c/c/view")
p_menu_insert = NodePath("c/c/c/insert")
[node name="file_editor" type="TextEdit" parent="."]
visible = false
@ -56,6 +71,7 @@ margin_right = 214.0
margin_bottom = 30.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 8 )
custom_fonts/font = ExtResource( 14 )
highlight_current_line = true
syntax_highlighting = true
@ -63,6 +79,7 @@ show_line_numbers = true
draw_tabs = true
fold_gutter = true
highlight_all_occurrences = true
hiding_enabled = true
minimap_draw = true
script = ExtResource( 4 )
@ -76,33 +93,33 @@ __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"]
[node name="file" 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__ = {
"_edit_use_anchors_": false
}
[node name="view_button" type="MenuButton" parent="c/c/c"]
[node name="view" type="MenuButton" parent="c/c/c"]
margin_left = 52.0
margin_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 +127,56 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="insert" type="MenuButton" parent="c/c/c"]
margin_left = 97.0
margin_right = 146.0
margin_bottom = 24.0
focus_mode = 2
text = "insert"
items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "Extensions", null, 0, false, false, 1, 0, null, "Extensions", false, "New File", null, 0, false, false, 2, 0, null, "", false, "Extensions", null, 0, false, false, 3, 0, null, "Extensions", false ]
__meta__ = {
"_edit_use_anchors_": false
}
[node name="word_wrap" type="CheckBox" parent="c/c/c"]
margin_left = 150.0
margin_right = 208.0
margin_bottom = 24.0
text = "wrap"
[node name="tab_colors" type="CheckBox" parent="c/c/c"]
margin_left = 212.0
margin_right = 303.0
margin_bottom = 24.0
text = "tab colors"
[node name="space" type="Control" parent="c/c/c"]
margin_left = 307.0
margin_right = 971.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 = 975.0
margin_top = 3.0
margin_right = 1010.0
margin_bottom = 20.0
custom_fonts/font = ExtResource( 12 )
text = "v1.12"
align = 2
[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 +187,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,16 +196,31 @@ 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
[node name="list_files" type="RichTextLabel" parent="c/div1/c2/c"]
[node name="c" type="VBoxContainer" parent="c/div1/c2/c"]
anchor_right = 1.0
anchor_bottom = 1.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="filter" type="LineEdit" parent="c/div1/c2/c/c"]
margin_right = 192.0
margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 )
clear_button_enabled = true
placeholder_text = "Filter"
[node name="list_files" type="RichTextLabel" parent="c/div1/c2/c/c"]
margin_top = 31.0
margin_right = 192.0
margin_bottom = 548.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 1 )
theme = SubResource( 9 )
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )
@ -151,23 +231,24 @@ script = ExtResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
p_filter = NodePath("../filter")
[node name="file_popup" type="PopupMenu" parent="c/div1/c2/c/list_files"]
[node name="file_popup" type="PopupMenu" parent="c/div1/c2/c/c/list_files"]
margin_right = 20.0
margin_bottom = 20.0
custom_fonts/font = ExtResource( 14 )
items = [ "Rename", null, 0, false, false, 0, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Remove", null, 0, false, false, 2, 0, null, "", false ]
[node name="dir_popup" type="PopupMenu" parent="c/div1/c2/c/list_files"]
[node name="dir_popup" type="PopupMenu" parent="c/div1/c2/c/c/list_files"]
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, "", null, 0, false, false, -1, 0, null, "", true, "Remove", null, 0, false, false, 3, 0, null, "", false ]
items = [ "New File", null, 0, false, false, 0, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Remove", null, 0, false, false, 2, 0, null, "", false, "", null, 0, false, false, -1, 0, null, "", true, "Tint Yellow", null, 0, false, false, 4, 0, null, "", false, "Tint Red", null, 0, false, false, 5, 0, null, "", false, "Tint Blue", null, 0, false, false, 6, 0, null, "", false, "Tint Green", null, 0, false, false, 7, 0, null, "", false, "Reset Tint", null, 0, false, false, 8, 0, null, "", false ]
[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 +258,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,16 +271,24 @@ 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
split_offset = 100
[node name="tab_container" type="TabContainer" parent="c/div1/div2/c/c"]
[node name="c2" type="VBoxContainer" parent="c/div1/div2/c/c"]
margin_right = 614.0
margin_bottom = 566.0
margin_bottom = 375.0
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="tab_container" type="TabContainer" parent="c/div1/div2/c/c/c2"]
margin_right = 614.0
margin_bottom = 353.0
size_flags_horizontal = 3
size_flags_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
@ -208,28 +297,78 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="meta_tabs" type="TabContainer" parent="c/div1/div2/c/c"]
visible = false
margin_top = 288.0
[node name="c" type="HBoxContainer" parent="c/div1/div2/c/c/c2"]
margin_top = 357.0
margin_right = 614.0
margin_bottom = 566.0
script = ExtResource( 16 )
margin_bottom = 375.0
size_flags_horizontal = 3
script = ExtResource( 18 )
[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
[node name="l" type="RichTextLabel" parent="c/div1/div2/c/c/c2/c"]
margin_right = 202.0
margin_bottom = 18.0
size_flags_horizontal = 3
size_flags_vertical = 3
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )
custom_fonts/normal_font = ExtResource( 12 )
custom_styles/focus = ExtResource( 20 )
custom_styles/normal = ExtResource( 20 )
bbcode_enabled = true
meta_underlined = false
script = ExtResource( 1 )
fit_content_height = true
script = ExtResource( 19 )
[node name="search" type="VBoxContainer" parent="c/div1/div2/c/c/meta_tabs"]
visible = false
[node name="m" type="RichTextLabel" parent="c/div1/div2/c/c/c2/c"]
margin_left = 206.0
margin_right = 408.0
margin_bottom = 18.0
size_flags_horizontal = 3
size_flags_vertical = 3
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )
custom_fonts/normal_font = ExtResource( 12 )
custom_styles/focus = ExtResource( 20 )
custom_styles/normal = ExtResource( 20 )
bbcode_enabled = true
fit_content_height = true
script = ExtResource( 19 )
[node name="r" type="RichTextLabel" parent="c/div1/div2/c/c/c2/c"]
margin_left = 412.0
margin_right = 614.0
margin_bottom = 18.0
size_flags_horizontal = 3
size_flags_vertical = 3
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )
custom_fonts/normal_font = ExtResource( 12 )
custom_styles/focus = ExtResource( 20 )
custom_styles/normal = ExtResource( 20 )
bbcode_enabled = true
fit_content_height = true
script = ExtResource( 19 )
[node name="c" type="Control" parent="c/div1/div2/c/c"]
margin_top = 387.0
margin_right = 614.0
margin_bottom = 562.0
size_flags_horizontal = 3
size_flags_vertical = 3
[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"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
@ -238,29 +377,18 @@ 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 )
theme = SubResource( 10 )
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 )
text = "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
@ -270,7 +398,7 @@ margin_right = -4.0
margin_bottom = -4.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 3 )
theme = SubResource( 11 )
custom_constants/table_hseparation = 16
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
@ -279,7 +407,7 @@ 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"]
[node name="search" type="VBoxContainer" parent="c/div1/div2/c/c/c/meta_tabs"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
@ -289,7 +417,69 @@ margin_right = -4.0
margin_bottom = -4.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 4 )
[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/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/c/meta_tabs/search/c"]
margin_left = 413.0
margin_right = 504.0
margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 )
text = "all files"
[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/c/meta_tabs/search"]
margin_top = 31.0
margin_right = 606.0
margin_bottom = 139.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 12 )
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="sys" type="VBoxContainer" parent="c/div1/div2/c/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
[node name="update" type="Button" parent="c/div1/div2/c/c/c/meta_tabs/sys"]
margin_right = 606.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/c/meta_tabs/sys"]
margin_top = 27.0
margin_right = 606.0
margin_bottom = 239.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 13 )
custom_constants/table_hseparation = 101
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
@ -300,10 +490,27 @@ meta_underlined = false
text = "idwords ⯆unique"
script = ExtResource( 17 )
[node name="image" type="VBoxContainer" parent="c/div1/div2/c/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
[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
margin_bottom = 566.0
margin_bottom = 562.0
rect_min_size = Vector2( 100, 0 )
size_flags_vertical = 3
@ -311,20 +518,38 @@ 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
[node name="list_symbols" type="RichTextLabel" parent="c/div1/div2/c2/c/c"]
[node name="c" type="VBoxContainer" parent="c/div1/div2/c2/c/c"]
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="filter" type="LineEdit" parent="c/div1/div2/c2/c/c/c"]
margin_right = 166.0
margin_bottom = 27.0
custom_fonts/font = ExtResource( 12 )
clear_button_enabled = true
placeholder_text = "Symbol Filter"
[node name="list_symbols" type="RichTextLabel" parent="c/div1/div2/c2/c/c/c"]
margin_top = 31.0
margin_right = 166.0
margin_bottom = 448.0
size_flags_vertical = 3
theme = SubResource( 14 )
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )
@ -337,11 +562,12 @@ script = ExtResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
p_filter = NodePath("../filter")
[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 +576,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme = SubResource( 6 )
theme = SubResource( 15 )
custom_fonts/bold_italics_font = ExtResource( 13 )
custom_fonts/italics_font = ExtResource( 10 )
custom_fonts/bold_font = ExtResource( 11 )
@ -400,3 +626,7 @@ current_path = "res://test_files/"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="popup_tab_menu" type="PopupMenu" parent="."]
margin_right = 124.0
margin_bottom = 112.0

View File

@ -4,12 +4,15 @@ class_name TE_ExtensionHelper
var symbols:Dictionary = {}
func get_tab() -> String:
return " "
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.set_bbcode(r.table([
["chars", "words", "lines", "bytes"],
[chars, words, lines, bytes]
@ -68,6 +71,23 @@ func get_symbols(t:String) -> Dictionary:
symbols = {}
return symbols
#func get_symbol_names(s:Dictionary):
# var out = []
# for k in s:
# if k != -1:
# out.append(s[k].name)
# return out
func get_tag_counts(s:Dictionary) -> Dictionary:
var out = {}
for k in s:
for tag in s[k].tags:
if not tag in out:
out[tag] = 1
else:
out[tag] += 1
return out
func apply_colors(e, t:TextEdit):
t.add_color_override("font_color", e.color_text)
t.add_color_override("number_color", e.color_var)

View File

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

@ -17,33 +17,32 @@ func get_symbols(t:String):
var deep = max(0, len(lines[i]) - len(lines[i].strip_edges(true, false)) - 1)
last = add_symbol(i, deep, key)
# tags
# elif "/* #" in lines[i]:
# for tag in lines[i].split("/* #", true, 1)[1].split("*/", true, 1)[0].split("#"):
# tag = tag.strip_edges()
# if tag:
# last.tags.append(tag)
elif '"#": "' in lines[i]:
for tag in lines[i].split('"#": "', true, 1)[1].split('"', true, 1)[0].split("#"):
tag = tag.strip_edges()
if tag:
last.tags.append(tag)
elif '"tags": "' in lines[i]:
for tag in lines[i].split('"tags": "', true, 1)[1].split('"', true, 1)[0].split("#"):
tag = tag.strip_edges()
if tag:
last.tags.append(tag)
i += 1
return out
func apply_colors(e:TE_TextEditor, t:TextEdit):
func apply_colors(e:TE_Editor, t:TextEdit):
.apply_colors(e, t)
# vars
t.add_color_region(' "', '"', e.color_var)
t.add_color_region(' "', '"', e.color_varname)
t.add_color_region('"', '"', e.color_varname)
t.add_keyword_color("true", e.color_var)
t.add_keyword_color("false", e.color_var)
t.add_keyword_color("null", e.color_var)
# comments
t.add_color_region("/*", "*/", e.color_comment)
t.add_color_region("//", "", e.color_comment, true)
# t.add_color_region("/*", "*/", e.color_comment)
t.add_color_region('\t"#"', ",", e.color_comment, false)

View File

@ -1,14 +1,137 @@
tool
extends TE_ExtensionHelper
func generate_meta(t:TextEdit, r:RichTextLabel):
.generate_meta(t, r)
var i = 0
var meta = {}
var words = {}
var word_count = 0
var chaps = [{i=0, id="???", words={}, word_count=0 }]
while i < t.get_line_count():
var line = t.get_line(i)
# get meta
if i == 0 and line.begins_with("---"):
i += 1
while i < t.get_line_count() and not t.get_line(i).begins_with("---"):
if ":" in t.get_line(i):
var p = t.get_line(i).split(":", true, 1)
var k = p[0].strip_edges()
var v = p[1].strip_edges()
meta[k] = v
if k == "name":
chaps[-1].id = v
i += 1
# ignore comments
elif "<!--" in line:
pass
# ignore tables
elif "|" in line:
pass
# ignore code
elif line.begins_with("```") or line.begins_with("~~~"):
var head = line.substr(0, 3)
i += 1
while i < t.get_line_count() and not t.get_line(i).begins_with(head):
i += 1
# get chapter info
elif line.begins_with("#"):
var id = line.split(" ", true, 1)[1].strip_edges()
chaps.append({i=i, id=id, words={}, word_count=0 })
else:
var last = chaps[-1]
last.word_count += TE_Util.count_words(line, last.words)
i += 1
# total words
for chap in chaps:
word_count += chap.word_count
for word in chap.words:
if not word in words:
words[word] = chap.words[word]
else:
words[word] += chap.words[word]
# sort
TE_Util.sort_vals(chap.words)
r.push_align(RichTextLabel.ALIGN_CENTER)
r.push_table(4)
for x in ["#", "id", "word %s" % word_count, "words"]:
r.push_cell()
r.push_bold()
r.add_text(x)
r.pop()
r.pop()
var index:int = 0
for chap in chaps:
if chap.id == "???" and not chap.word_count:
continue
index += 1
r.push_cell()
r.push_color(Color.webgray)
r.add_text(str(index))
r.pop()
r.pop()
r.push_cell()
r.push_color(Color.webgray)
r.add_text(chap.id)
r.pop()
r.pop()
var div = 0 if not chap.word_count or not word_count else chap.word_count / float(word_count)
div *= 100.0
div = "%" + str(stepify(div, .1))
r.push_cell()
r.push_color(Color.webgray)
r.add_text(str(chap.word_count))
r.pop()
r.push_color(Color.gray)
r.add_text(" %s" % div)
r.pop()
r.pop()
r.push_cell()
r.push_color(Color.webgray)
r.add_text(PoolStringArray(chap.words.keys()).join(" "))
r.pop()
r.pop()
r.pop()
r.pop()
func _sort(a, b):
return a[1] > b[1]
func toggle_comment(t:TextEdit, head:String="<!-- ", tail:String=" -->"):
return .toggle_comment(t, head, tail)
func apply_colors(e:TE_TextEditor, t:TextEdit):
func apply_colors(e:TE_Editor, t:TextEdit):
.apply_colors(e, t)
t.add_keyword_color("true", e.color_var)
t.add_keyword_color("false", e.color_var)
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)
t.add_color_override("number_color", e.color_text)
# t.add_keyword_color("true", e.color_var)
# t.add_keyword_color("false", e.color_var)
# bold italic
t.add_color_region("***", "***", Color.tomato.darkened(.3), false)
@ -18,33 +141,40 @@ 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("> ", "", quote, true)
# comment
t.add_color_region("<!--", "-->", e.color_comment, false)
# headings
var head = e.color_symbol
var tint1 = TE_Util.hue_shift(head, -.33)
var tint2 = TE_Util.hue_shift(head, .33)
for i in range(1, 6):
var h = "#".repeat(i)
t.add_color_region("%s *" % h, "*", tint1, true)
t.add_color_region("%s \"" % h, "\"", tint2, true)
t.add_color_region("%s " % h, "*", head, true)
# non official markdown:
# formatted
t.add_color_region("{", "}", lerp(e.color_text, e.color_var, .5).darkened(.25), false)
# t.add_color_region("[", "]", lerp(e.color_text, e.color_var, .5).darkened(.25), false)
# t.add_color_region("(", ")", lerp(e.color_text, e.color_var, .5).darkened(.25), false)
if false:
# quote
t.add_color_region('"', '"', quote, false)
# brackets
t.add_color_region('(', ')', quote, false)
else:
# url links
# t.add_color_region("[]", ")", e.color_var.lightened(.5))
t.add_color_region("![", ")", e.color_var.lightened(.5))
# headings
for i in range(1, 7):
var h = "#".repeat(i)
t.add_color_region("%s *" % h, "*", e.get_symbol_color(i-1, -.33), true)
t.add_color_region("%s \"" % h, "\"", e.get_symbol_color(i-1, .33), true)
t.add_color_region("%s " % h, "*", e.get_symbol_color(i-1), true)
# lists
t.add_color_region("- [x", "]", Color.yellowgreen, false)
t.add_color_region("- [", " ]", e.color_text.darkened(.6), false)
# code blocks
var code:Color = lerp(e.color_text.darkened(.5), Color.yellowgreen, .5)
t.add_color_region("```", "```", code, false)
t.add_color_region("~~~", "~~~", code, false)
t.add_color_region("---", "---", code, false)
# strikeout
t.add_color_region("~~", "~~", Color.tomato, false)
@ -58,7 +188,6 @@ func apply_colors(e:TE_TextEditor, t:TextEdit):
# tables
t.add_color_region("|", "", Color.tan, true)
func get_symbols(t:String) -> Dictionary:
var out = .get_symbols(t)
var last = add_symbol()
@ -66,11 +195,33 @@ 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)
# elif "name: " in lines[i]:
# last.name = lines[i].split("name: ", true, 1)[1]
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
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

@ -0,0 +1,50 @@
tool
extends TE_ExtensionHelper
func get_tab() -> String:
return " "
func apply_colors(e:TE_Editor, t:TextEdit):
.apply_colors(e, t)
for k in "label menu define default scene show with play return jump call".split(" "):
t.add_keyword_color(k, e.color_symbol)
# strings
t.add_color_region('"', '"', e.color_var)
# bools
t.add_keyword_color("True", e.color_var)
t.add_keyword_color("False", e.color_var)
# comments
t.add_color_region("#", "", e.color_comment, true)
t.add_color_region("$ ", "", e.color_comment, true)
func get_symbols(t:String):
var out = .get_symbols(t)
var last = add_symbol()
var lines = t.split("\n")
var i = 0
while i < len(lines):
# symbols
if lines[i].begins_with("label "):
var key = lines[i].substr(len("label ")).strip_edges()
key = key.substr(0, len(key)-1)
last = add_symbol(i, 0, key)
elif lines[i].begins_with("menu "):
var key = lines[i].substr(len("menu ")).strip_edges()
key = key.substr(0, len(key)-1)
last = add_symbol(i, 0, key)
# tags
elif "#" in lines[i]:
var p = lines[i].rsplit("#", true, 1)[1]
if "#" in p:
for tag in p.split("#"):
last.tags.append(tag)
i += 1
return out

View File

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

View File

@ -1,6 +1,9 @@
tool
extends TE_ExtensionHelper
func get_tab() -> String:
return " "
func _is_commented(lines) -> bool:
for i in len(lines):
if not lines[i].strip_edges():
@ -43,7 +46,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,8 @@
[ext_resource path="res://addons/text_editor/fonts/unifont-13.0.01.ttf" type="DynamicFontData" id=3]
[resource]
size = 12
use_filter = true
font_data = ExtResource( 1 )
fallback/0 = ExtResource( 3 )
fallback/1 = ExtResource( 2 )

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

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

View File

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

View File

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

3
default_bus_layout.tres Normal file
View File

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