Compare commits
23 Commits
17f4306fc3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20d71722ea | ||
|
|
cf383c9772 | ||
|
|
82dceaca68 | ||
|
|
4f4940bcd3 | ||
|
|
aff3403404 | ||
|
|
b04b566681 | ||
|
|
aa85d9420a | ||
|
|
4c21026842 | ||
|
|
cab882de60 | ||
|
|
fadf4cd698 | ||
|
|
94ee03800d | ||
|
|
207fc65fec | ||
|
|
4ad9e6bf20 | ||
|
|
edb461bde8 | ||
|
|
3c6153380d | ||
|
|
7cfae9af92 | ||
|
|
e1149680d9 | ||
|
|
9b2c8626d4 | ||
|
|
52c55e27d9 | ||
|
|
56a729b617 | ||
|
|
fde4e463ad | ||
|
|
65ba886ddf | ||
|
|
84fa04e1db |
121
README.md
121
README.md
@@ -1,9 +1,118 @@
|
|||||||
# te, a text editor
|
# te
|
||||||
|
|
||||||

|
A from-scratch text editor that aims to stay fast, hackable, and practical for day-to-day coding.
|
||||||
|
|
||||||
In order to build on windows you need to call build.bat from
|

|
||||||
the x64 Native Command Tools prompt that ships with Visual Studio.
|
|
||||||
|
|
||||||
For Linux you will need clang, SDL3 and libbacktrace libraries to be installed and
|
## What this project is
|
||||||
available on your system. Just call build.sh when these are available.
|
|
||||||
|
`te` is a native desktop editor written as a single C++ executable (SDL3 + OpenGL + custom editor core).
|
||||||
|
It is built around a straightforward single-threaded architecture, with coroutines used for asynchronous workflows (searching, UI flows, process jobs) so behavior stays easy to reason about and debug.
|
||||||
|
|
||||||
|
The codebase includes its own:
|
||||||
|
|
||||||
|
- text buffer + undo/redo engine
|
||||||
|
- window/view layout system
|
||||||
|
- command system + keybinding parser
|
||||||
|
- fuzzy selection UI
|
||||||
|
- process execution and output streaming
|
||||||
|
- built-in font fallback (baked into the binary)
|
||||||
|
|
||||||
|
## Highlights
|
||||||
|
|
||||||
|
- VS Code-style keybindings and command palette (`Ctrl+Shift+P`)
|
||||||
|
- Multi-cursor editing (keyboard and mouse workflows)
|
||||||
|
- Fuzzy-open patterns for commands, files, and open buffers
|
||||||
|
- Project-wide search (`Ctrl+Shift+F`) and replace-all workflow
|
||||||
|
- Shell integration directly from editor input:
|
||||||
|
- `:Command` to run editor commands
|
||||||
|
- `:Set ...` to configure options and keybindings
|
||||||
|
- `!cmd` / `!!cmd` to execute shell commands
|
||||||
|
- `py:...` to execute Python snippets via discovered Python interpreter
|
||||||
|
- Build panel integration (`Ctrl+B`, `Alt+B`, etc.) with configurable build commands
|
||||||
|
- Config-driven behavior (font, colors, project commands, keymaps, paths)
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- `clang`
|
||||||
|
- `cmake`
|
||||||
|
- `libbacktrace`
|
||||||
|
- SDL3 (the build script can clone and install SDL when missing)
|
||||||
|
|
||||||
|
Build commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build.sh # debug build (default)
|
||||||
|
./build.sh release # optimized build
|
||||||
|
./build.sh slow # extra asserts/instrumentation path
|
||||||
|
```
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build/te
|
||||||
|
./build/te path/to/file.cpp
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
Use the **x64 Native Tools Command Prompt for Visual Studio**.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
- Visual Studio C++ toolchain (`cl`, `msbuild`)
|
||||||
|
- `cmake`
|
||||||
|
|
||||||
|
Build commands:
|
||||||
|
|
||||||
|
```bat
|
||||||
|
build.bat
|
||||||
|
build.bat release
|
||||||
|
build.bat slow
|
||||||
|
```
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bat
|
||||||
|
build\te.exe
|
||||||
|
build\te.exe path\to\file.cpp
|
||||||
|
```
|
||||||
|
|
||||||
|
## First steps in the editor
|
||||||
|
|
||||||
|
- `Ctrl+N`: new buffer
|
||||||
|
- `Ctrl+O`: open current file's folder / directory navigation view
|
||||||
|
- `Ctrl+P`: fuzzy list of open buffers
|
||||||
|
- `Ctrl+Shift+P`: all commands
|
||||||
|
- `Ctrl+Q` or `F12`: open thing under caret (path / link / command)
|
||||||
|
- `Ctrl+F`, `F3`, `Shift+F3`: in-buffer search flow
|
||||||
|
- `Ctrl+Shift+F`: interactive search across open project buffers
|
||||||
|
- `Alt+Shift+Up/Down`: add cursors vertically
|
||||||
|
- `Ctrl+B`: run Build1 command (configurable)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
On startup, `te` loads a config file from SDL's app preference directory (`config.te`).
|
||||||
|
You can also pass additional `.te` files as CLI arguments.
|
||||||
|
|
||||||
|
Useful examples:
|
||||||
|
|
||||||
|
```text
|
||||||
|
:Set FontSize 16
|
||||||
|
:Set PathToFont '/path/to/font.ttf'
|
||||||
|
:Set Build1OnUnix 'sh build.sh release'
|
||||||
|
:Set Build1OnWindows 'build.bat release'
|
||||||
|
:Set TextColor ff202020
|
||||||
|
:Set BackgroundColor fffdf6e3
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes on architecture
|
||||||
|
|
||||||
|
- Single-threaded main loop (event/update/render)
|
||||||
|
- Coroutines for async editor tasks instead of multi-threaded complexity
|
||||||
|
- "Plugin" modules are integrated in the source tree and compiled in
|
||||||
|
- Focus on predictable behavior and low-latency interaction
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ if "%slow%"=="1" set flags=%flags% -DSLOW_BUILD=1
|
|||||||
|
|
||||||
set libs=%sdllib%/SDL3-static.lib %sdllib%/SDL_uclibc.lib kernel32.lib gdi32.lib user32.lib Imm32.lib ole32.lib Shell32.lib OleAut32.lib Cfgmgr32.lib Setupapi.lib Advapi32.lib version.lib winmm.lib
|
set libs=%sdllib%/SDL3-static.lib %sdllib%/SDL_uclibc.lib kernel32.lib gdi32.lib user32.lib Imm32.lib ole32.lib Shell32.lib OleAut32.lib Cfgmgr32.lib Setupapi.lib Advapi32.lib version.lib winmm.lib
|
||||||
rem rc ..\data\icon.rc
|
rem rc ..\data\icon.rc
|
||||||
cl %flags% ../src/text_editor/text_editor.cpp -Fe:te.exe -I%sdl%/include -I../src/external/glad -I../src/ %libs% -link /SUBSYSTEM:WINDOWS /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:MSVCRTD ..\data\icon.res
|
cl %flags% ../src/text_editor.cpp -Fe:te.exe -I%sdl%/include -I../src/external/glad %libs% -link /SUBSYSTEM:WINDOWS /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:MSVCRTD ..\data\icon.res
|
||||||
|
|
||||||
:: small util when working on the editor using the editor
|
:: small util when working on the editor using the editor
|
||||||
copy te.exe te2.exe
|
copy te.exe te2.exe
|
||||||
|
|||||||
23
build.sh
23
build.sh
@@ -5,17 +5,34 @@ if [ ! -v release ]; then debug=1; fi
|
|||||||
if [ -v debug ]; then echo "[debug build]"; fi
|
if [ -v debug ]; then echo "[debug build]"; fi
|
||||||
if [ -v release ]; then echo "[release build]"; fi
|
if [ -v release ]; then echo "[release build]"; fi
|
||||||
if [ -v slow ]; then echo "[slow build]"; fi
|
if [ -v slow ]; then echo "[slow build]"; fi
|
||||||
|
if [ -v addr ]; then echo "[address sanitizer build]"; fi
|
||||||
|
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
|
|
||||||
|
if [ ! -e "src/external/SDL" ]; then
|
||||||
|
cd src/external
|
||||||
|
git clone https://github.com/libsdl-org/SDL.git
|
||||||
|
cd SDL
|
||||||
|
git checkout release-3.2.30
|
||||||
|
# We need older version of SDL3 because there is a bug on wayland that
|
||||||
|
# doubles click events and it's kind of unusable
|
||||||
|
cmake -S . -B build_linux -DSDL_PIPEWIRE=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
|
||||||
|
cd build_linux
|
||||||
|
sudo make -j16 install
|
||||||
|
cd ../../../..
|
||||||
|
fi
|
||||||
|
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
I="-I../src/external/SDL/include -I../src/external/lua/src -I../src/external/glad -I../src"
|
I="-I../src/external/SDL/include -I../src/external/glad"
|
||||||
flags="-Wall -Wextra -Werror -Wformat=2 -Wundef -Wshadow -Wno-missing-field-initializers -Wno-missing-braces -Wno-writable-strings \
|
flags="-Wall -Wextra -Werror -Wformat=2 -Wundef -Wshadow -Wno-missing-field-initializers -Wno-missing-braces -Wno-writable-strings \
|
||||||
-g -fdiagnostics-absolute-paths \
|
-g -fdiagnostics-absolute-paths \
|
||||||
-nostdlib++ -fno-exceptions"
|
-nostdlib++ -fno-exceptions"
|
||||||
|
|
||||||
if [ -v debug ]; then flags="$flags -fsanitize=address,undefined -fno-omit-frame-pointer -DDEBUG_BUILD=1"; fi
|
if [ -v debug ]; then flags="$flags -fsanitize=undefined -fno-omit-frame-pointer -DDEBUG_BUILD=1"; fi
|
||||||
if [ -v release ]; then flags="$flags -DDEBUG_BUILD=0 -O2"; fi
|
if [ -v release ]; then flags="$flags -DDEBUG_BUILD=0 -O2"; fi
|
||||||
if [ -v slow ]; then flags="$flags -DSLOW_BUILD=1"; fi
|
if [ -v slow ]; then flags="$flags -DSLOW_BUILD=1"; fi
|
||||||
|
if [ -v addr ]; then flags="$flags -fsanitize=address"; fi
|
||||||
|
|
||||||
time clang -o te $flags ../src/text_editor/text_editor.cpp $I -lSDL3 -lm -lbacktrace
|
time clang -o te $flags ../src/text_editor.cpp $I -lSDL3 -lm -lbacktrace
|
||||||
|
./te :RunTests
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
! What precise workflow do I need for me to be viable to use this?
|
|
||||||
! From a user (novice) point of view, how does it look like?
|
|
||||||
|
|
||||||
- Buffer edit history separate from caret history (tagging history blocks with carets???)
|
|
||||||
- We need regex for: [FormatCode matching, IsCode matching,
|
|
||||||
- Macros
|
|
||||||
- Window position: vscode opens in fullscreen and then remembers what position it was close in (could be a config option)
|
|
||||||
- On Linux: Try to implement is_debugger_present()
|
|
||||||
- Maybe IPC for te.exe when it's already open and file arguments are passed it should perhaps open a buffer in current window??
|
|
||||||
- Add <<File>> <<ProjectFolder>> template strings to Open (Then remove SEtWorkdirhere)
|
|
||||||
- :Set Filename to name current buffer ??? :O and others like that!!
|
|
||||||
- Make a fuzzy command !> grep and fuzzy over it??? (doesn't seem very useful for grep)
|
|
||||||
- Make the equivalent of SearchOpenBuffers but for cmds like !@git grep -n "@>"
|
|
||||||
- Add Bool variable
|
|
||||||
- Guide on the first page for new users with links to configs, tutorials
|
|
||||||
|
|
||||||
Debug session:
|
|
||||||
- Report errorf - use coroutine dialogs
|
|
||||||
- Replace in render layer also
|
|
||||||
- BlockAllocator something is not working there which only showed after executing OpenCode on many files
|
|
||||||
- Some bad allocating happening in Clipboard for sure OR MAYBE BLOCK ALLOCATOR ACTION
|
|
||||||
|
|
||||||
New UI Session
|
|
||||||
- Uneditable buffers ?
|
|
||||||
- Maybe marked allocations??? So that we can associate allocations with a buffer or view and then dealloc all at the same time
|
|
||||||
|
|
||||||
- Open with seek string (open at pattern) filename:32 filename:/^Window$/
|
|
||||||
- Show what process/coroutines are running and allow to kill (active process buffer?)
|
|
||||||
- Database idea: use special buffers to store information
|
|
||||||
- Editing the buffer doesn't seem to be the slow part rather, accessing the data and putting it into the buffer (potentially hitting many different memory locations) I have a crazy idea to use buffers in order to store the names in a serialized format
|
|
||||||
- non editable buffers (raw ops ok, non-raw no op)
|
|
||||||
- DBBuffer
|
|
||||||
|
|
||||||
- Try to add Tracking Allocator and rewrite the app, free all memory at the end of the app and check all is well
|
|
||||||
|
|
||||||
FEATURE Some decl/function indexing in fuzzy format
|
|
||||||
FEATURE dump text editor state to file, restore state
|
|
||||||
- word complete
|
|
||||||
- escapeing multiple cursor after ctrl + d should put the cursor where it was (probably will need to swap secondary and primary cursor for new cursor
|
|
||||||
- draw indentation levels like in sublime (those lines) - we render chars one by one so seems relatively easy to figure out if whitespace belongs to beginning of line (make sure to add max value like 40 because of big files)
|
|
||||||
- code sections, visual demarkation if beginning of line has a very specific text + goto next / goto prev section hotkey!
|
|
||||||
- combine glyph and selection rendering
|
|
||||||
|
|
||||||
- Test stdin writing code
|
|
||||||
- Implement shell interaction (the valid cmd lines should start with '>' or '$', user can add more lines like this to expand the command size maybe?, if we have a case where we have a line with '>' but the last line doesn't have (just a space) then it should execute?)
|
|
||||||
- drop text into window
|
|
||||||
- I think the way sublime text and we display line highlights is confusing with multiple cursors (line highlight can be confused with selection)
|
|
||||||
- make the editor replayable, store events and then replay, be careful about globals
|
|
||||||
- maybe open should return multiple options if there are many more? (like in sublime if many symbols you get a window and you choose and it automatically jumps you to the symbol in the background)
|
|
||||||
- I want a way to assign flags to buffers/views/windows from user perspective so that console window concept can be created from user space
|
|
||||||
- font cache and on demand unicode loads
|
|
||||||
- color parens, braces
|
|
||||||
- gap buffer
|
|
||||||
- optimize rendering - command buffer, and vertice buffer instead of vertice buffer with scissor
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WORD COMPLETE
|
|
||||||
1. Tokenize the file (or maybe couple last viewed files)
|
|
||||||
2. Match the tokens (identifiers) with prefix string and produce a list
|
|
||||||
3. Remove duplicates
|
|
||||||
4. Sort by proximity to cursor
|
|
||||||
|
|
||||||
We save the iterator, it's enough for it to be global with unique for it arena
|
|
||||||
If prefix ask is the same - reuse the iterator go to next word, if there are none go to next buffer ...
|
|
||||||
else - dump old, create new
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
Basic Latin
|
|
||||||
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
|
|
||||||
Latin-1 Supplement
|
|
||||||
¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
|
|
||||||
Latin Extended-A
|
|
||||||
Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĩ ĩ Ī ī Ĭ ĭ Į į İ ı IJ ij Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ʼn Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ œ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş ş Š š Ţ ţ Ť ť Ŧ ŧ Ũ ũ Ū ū Ŭ ŭ Ů ů Ű ű Ų ų Ŵ ŵ Ŷ ŷ Ÿ Ź ź Ż ż Ž ž ſ
|
|
||||||
Latin Extended-B
|
|
||||||
ƀ Ɓ Ƃ ƃ Ƅ ƅ Ɔ Ƈ ƈ Ɖ Ɗ Ƌ ƌ ƍ Ǝ Ə Ɛ Ƒ ƒ Ɠ Ɣ ƕ Ɩ Ɨ Ƙ ƙ ƚ ƛ Ɯ Ɲ ƞ Ɵ Ơ ơ Ƣ ƣ Ƥ ƥ Ʀ Ƨ ƨ Ʃ ƪ ƫ Ƭ ƭ Ʈ Ư ư Ʊ Ʋ Ƴ ƴ Ƶ ƶ Ʒ Ƹ ƹ ƺ ƻ Ƽ ƽ ƾ ƿ ǀ ǁ ǂ ǃ DŽ Dž dž LJ Lj lj NJ Nj nj Ǎ ǎ Ǐ ǐ Ǒ ǒ Ǔ ǔ Ǖ ǖ Ǘ ǘ Ǚ ǚ Ǜ ǜ ǝ Ǟ ǟ Ǡ ǡ Ǣ ǣ Ǥ ǥ Ǧ ǧ Ǩ ǩ Ǫ ǫ Ǭ ǭ Ǯ ǯ ǰ DZ Dz dz Ǵ ǵ Ǻ ǻ Ǽ ǽ Ǿ ǿ Ȁ ȁ Ȃ ȃ ...
|
|
||||||
IPA Extensions
|
|
||||||
ɐ ɑ ɒ ɓ ɔ ɕ ɖ ɗ ɘ ə ɚ ɛ ɜ ɝ ɞ ɟ ɠ ɡ ɢ ɣ ɤ ɥ ɦ ɧ ɨ ɩ ɪ ɫ ɬ ɭ ɮ ɯ ɰ ɱ ɲ ɳ ɴ ɵ ɶ ɷ ɸ ɹ ɺ ɻ ɼ ɽ ɾ ɿ ʀ ʁ ʂ ʃ ʄ ʅ ʆ ʇ ʈ ʉ ʊ ʋ ʌ ʍ ʎ ʏ ʐ ʑ ʒ ʓ ʔ ʕ ʖ ʗ ʘ ʙ ʚ ʛ ʜ ʝ ʞ ʟ ʠ ʡ ʢ ʣ ʤ ʥ ʦ ʧ ʨ
|
|
||||||
Spacing Modifier Letters
|
|
||||||
ʰ ʱ ʲ ʳ ʴ ʵ ʶ ʷ ʸ ʹ ʺ ʻ ʼ ʽ ʾ ʿ ˀ ˁ ˂ ˃ ˄ ˅ ˆ ˇ ˈ ˉ ˊ ˋ ˌ ˍ ˎ ˏ ː ˑ ˒ ˓ ˔ ˕ ˖ ˗ ˘ ˙ ˚ ˛ ˜ ˝ ˞ ˠ ˡ ˢ ˣ ˤ ˥ ˦ ˧ ˨ ˩
|
|
||||||
Combining Diacritical Marks
|
|
||||||
̀ ́ ̂ ̃ ̄ ̅ ̆ ̇ ̈ ̉ ̊ ̋ ̌ ̍ ̎ ̏ ̐ ̑ ̒ ̓ ̔ ̕ ̖ ̗ ̘ ̙ ̚ ̛ ̜ ̝ ̞ ̟ ̠ ̡ ̢ ̣ ̤ ̥ ̦ ̧ ̨ ̩ ̪ ̫ ̬ ̭ ̮ ̯ ̰ ̱ ̲ ̳ ̴ ̵ ̶ ̷ ̸ ̹ ̺ ̻ ̼ ̽ ̾ ̿ ̀ ́ ͂ ̓ ̈́ ͅ ͠ ͡
|
|
||||||
Greek
|
|
||||||
ʹ ͵ ͺ ; ΄ ΅ Ά · Έ Ή Ί Ό Ύ Ώ ΐ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω Ϊ Ϋ ά έ ή ί ΰ α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω ϊ ϋ ό ύ ώ ϐ ϑ ϒ ϓ ϔ ϕ ϖ Ϛ Ϝ Ϟ Ϡ Ϣ ϣ Ϥ ϥ Ϧ ϧ Ϩ ϩ Ϫ ϫ Ϭ ϭ Ϯ ϯ ϰ ϱ ϲ ϳ
|
|
||||||
Cyrillic
|
|
||||||
Ё Ђ Ѓ Є Ѕ І Ї Ј Љ Њ Ћ Ќ Ў Џ А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я ё ђ ѓ є ѕ і ї ј љ њ ћ ќ ў џ Ѡ ѡ Ѣ ѣ Ѥ ѥ Ѧ ѧ Ѩ ѩ Ѫ ѫ Ѭ ѭ Ѯ ѯ Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ Ѹ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ Ҁ ҁ ҂ ҃ ...
|
|
||||||
Armenian
|
|
||||||
Ա Բ Գ Դ Ե Զ Է Ը Թ Ժ Ի Լ Խ Ծ Կ Հ Ձ Ղ Ճ Մ Յ Ն Շ Ո Չ Պ Ջ Ռ Ս Վ Տ Ր Ց Ւ Փ Ք Օ Ֆ ՙ ՚ ՛ ՜ ՝ ՞ ՟ ա բ գ դ ե զ է ը թ ժ ի լ խ ծ կ հ ձ ղ ճ մ յ ն շ ո չ պ ջ ռ ս վ տ ր ց ւ փ ք օ ֆ և ։
|
|
||||||
Hebrew
|
|
||||||
֑ ֒ ֓ ֔ ֕ ֖ ֗ ֘ ֙ ֚ ֛ ֜ ֝ ֞ ֟ ֠ ֡ ֣ ֤ ֥ ֦ ֧ ֨ ֩ ֪ ֫ ֬ ֭ ֮ ֯ ְ ֱ ֲ ֳ ִ ֵ ֶ ַ ָ ֹ ֻ ּ ֽ ־ ֿ ׀ ׁ ׂ ׃ ׄ א ב ג ד ה ו ז ח ט י ך כ ל ם מ ן נ ס ע ף פ ץ צ ק ר ש ת װ ױ ײ ׳ ״
|
|
||||||
Arabic
|
|
||||||
، ؛ ؟ ء آ أ ؤ إ ئ ا ب ة ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ـ ف ق ك ل م ن ه و ى ي ً ٌ ٍ َ ُ ِ ّ ْ ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ٪ ٫ ٬ ٭ ٰ ٱ ٲ ٳ ٴ ٵ ٶ ٷ ٸ ٹ ٺ ٻ ټ ٽ پ ٿ ڀ ځ ڂ ڃ ڄ څ چ ڇ ڈ ډ ڊ ڋ ڌ ڍ ڎ ڏ ڐ ڑ ڒ ړ ڔ ڕ ږ ڗ ژ ڙ ښ ڛ ڜ ڝ ڞ ڟ ڠ ڡ ڢ ڣ ڤ ڥ ڦ ڧ ڨ ک ڪ ګ ڬ ڭ ڮ گ ڰ ڱ ...
|
|
||||||
Devanagari
|
|
||||||
ँ ं ः अ आ इ ई उ ऊ ऋ ऌ ऍ ऎ ए ऐ ऑ ऒ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न ऩ प फ ब भ म य र ऱ ल ळ ऴ व श ष स ह ़ ऽ ा ि ी ु ू ृ ॄ ॅ ॆ े ै ॉ ॊ ो ौ ् ॐ ॑ ॒ ॓ ॔ क़ ख़ ग़ ज़ ड़ ढ़ फ़ य़ ॠ ॡ ॢ ॣ । ॥ ० १ २ ३ ४ ५ ६ ७ ८ ९ ॰
|
|
||||||
Bengali
|
|
||||||
ঁ ং ঃ অ আ ই ঈ উ ঊ ঋ ঌ এ ঐ ও ঔ ক খ গ ঘ ঙ চ ছ জ ঝ ঞ ট ঠ ড ঢ ণ ত থ দ ধ ন প ফ ব ভ ম য র ল শ ষ স হ ় া ি ী ু ূ ৃ ৄ ে ৈ ো ৌ ্ ৗ ড় ঢ় য় ৠ ৡ ৢ ৣ ০ ১ ২ ৩ ৪ ৫ ৬ ৭ ৮ ৯ ৰ ৱ ৲ ৳ ৴ ৵ ৶ ৷ ৸ ৹ ৺
|
|
||||||
Gurmukhi
|
|
||||||
ਂ ਅ ਆ ਇ ਈ ਉ ਊ ਏ ਐ ਓ ਔ ਕ ਖ ਗ ਘ ਙ ਚ ਛ ਜ ਝ ਞ ਟ ਠ ਡ ਢ ਣ ਤ ਥ ਦ ਧ ਨ ਪ ਫ ਬ ਭ ਮ ਯ ਰ ਲ ਲ਼ ਵ ਸ਼ ਸ ਹ ਼ ਾ ਿ ੀ ੁ ੂ ੇ ੈ ੋ ੌ ੍ ਖ਼ ਗ਼ ਜ਼ ੜ ਫ਼ ੦ ੧ ੨ ੩ ੪ ੫ ੬ ੭ ੮ ੯ ੰ ੱ ੲ ੳ ੴ
|
|
||||||
Gujarati
|
|
||||||
ઁ ં ઃ અ આ ઇ ઈ ઉ ઊ ઋ ઍ એ ઐ ઑ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ ળ વ શ ષ સ હ ઼ ઽ ા િ ી ુ ૂ ૃ ૄ ૅ ે ૈ ૉ ો ૌ ્ ૐ ૠ ૦ ૧ ૨ ૩ ૪ ૫ ૬ ૭ ૮ ૯
|
|
||||||
Oriya
|
|
||||||
ଁ ଂ ଃ ଅ ଆ ଇ ଈ ଉ ଊ ଋ ଌ ଏ ଐ ଓ ଔ କ ଖ ଗ ଘ ଙ ଚ ଛ ଜ ଝ ଞ ଟ ଠ ଡ ଢ ଣ ତ ଥ ଦ ଧ ନ ପ ଫ ବ ଭ ମ ଯ ର ଲ ଳ ଶ ଷ ସ ହ ଼ ଽ ା ି ୀ ୁ ୂ ୃ େ ୈ ୋ ୌ ୍ ୖ ୗ ଡ଼ ଢ଼ ୟ ୠ ୡ ୦ ୧ ୨ ୩ ୪ ୫ ୬ ୭ ୮ ୯ ୰
|
|
||||||
Tamil
|
|
||||||
ஂ ஃ அ ஆ இ ஈ உ ஊ எ ஏ ஐ ஒ ஓ ஔ க ங ச ஜ ஞ ட ண த ந ன ப ம ய ர ற ல ள ழ வ ஷ ஸ ஹ ா ி ீ ு ூ ெ ே ை ொ ோ ௌ ் ௗ ௧ ௨ ௩ ௪ ௫ ௬ ௭ ௮ ௯ ௰ ௱ ௲
|
|
||||||
Telugu
|
|
||||||
ఁ ం ః అ ఆ ఇ ఈ ఉ ఊ ఋ ఌ ఎ ఏ ఐ ఒ ఓ ఔ క ఖ గ ఘ ఙ చ ఛ జ ఝ ఞ ట ఠ డ ఢ ణ త థ ద ధ న ప ఫ బ భ మ య ర ఱ ల ళ వ శ ష స హ ా ి ీ ు ూ ృ ౄ ె ే ై ొ ో ౌ ్ ౕ ౖ ౠ ౡ ౦ ౧ ౨ ౩ ౪ ౫ ౬ ౭ ౮ ౯
|
|
||||||
Kannada
|
|
||||||
ಂ ಃ ಅ ಆ ಇ ಈ ಉ ಊ ಋ ಌ ಎ ಏ ಐ ಒ ಓ ಔ ಕ ಖ ಗ ಘ ಙ ಚ ಛ ಜ ಝ ಞ ಟ ಠ ಡ ಢ ಣ ತ ಥ ದ ಧ ನ ಪ ಫ ಬ ಭ ಮ ಯ ರ ಱ ಲ ಳ ವ ಶ ಷ ಸ ಹ ಾ ಿ ೀ ು ೂ ೃ ೄ ೆ ೇ ೈ ೊ ೋ ೌ ್ ೕ ೖ ೞ ೠ ೡ ೦ ೧ ೨ ೩ ೪ ೫ ೬ ೭ ೮ ೯
|
|
||||||
Malayalam
|
|
||||||
ം ഃ അ ആ ഇ ഈ ഉ ഊ ഋ ഌ എ ഏ ഐ ഒ ഓ ഔ ക ഖ ഗ ഘ ങ ച ഛ ജ ഝ ഞ ട ഠ ഡ ഢ ണ ത ഥ ദ ധ ന പ ഫ ബ ഭ മ യ ര റ ല ള ഴ വ ശ ഷ സ ഹ ാ ി ീ ു ൂ ൃ െ േ ൈ ൊ ോ ൌ ് ൗ ൠ ൡ ൦ ൧ ൨ ൩ ൪ ൫ ൬ ൭ ൮ ൯
|
|
||||||
Thai
|
|
||||||
ก ข ฃ ค ฅ ฆ ง จ ฉ ช ซ ฌ ญ ฎ ฏ ฐ ฑ ฒ ณ ด ต ถ ท ธ น บ ป ผ ฝ พ ฟ ภ ม ย ร ฤ ล ฦ ว ศ ษ ส ห ฬ อ ฮ ฯ ะ ั า ำ ิ ี ึ ื ุ ู ฺ ฿ เ แ โ ใ ไ ๅ ๆ ็ ่ ้ ๊ ๋ ์ ํ ๎ ๏ ๐ ๑ ๒ ๓ ๔ ๕ ๖ ๗ ๘ ๙ ๚ ๛
|
|
||||||
Lao
|
|
||||||
ກ ຂ ຄ ງ ຈ ຊ ຍ ດ ຕ ຖ ທ ນ ບ ປ ຜ ຝ ພ ຟ ມ ຢ ຣ ລ ວ ສ ຫ ອ ຮ ຯ ະ ັ າ ຳ ິ ີ ຶ ື ຸ ູ ົ ຼ ຽ ເ ແ ໂ ໃ ໄ ໆ ່ ້ ໊ ໋ ໌ ໍ ໐ ໑ ໒ ໓ ໔ ໕ ໖ ໗ ໘ ໙ ໜ ໝ
|
|
||||||
Tibetan
|
|
||||||
ༀ ༁ ༂ ༃ ༄ ༅ ༆ ༇ ༈ ༉ ༊ ་ ༌ ། ༎ ༏ ༐ ༑ ༒ ༓ ༔ ༕ ༖ ༗ ༘ ༙ ༚ ༛ ༜ ༝ ༞ ༟ ༠ ༡ ༢ ༣ ༤ ༥ ༦ ༧ ༨ ༩ ༪ ༫ ༬ ༭ ༮ ༯ ༰ ༱ ༲ ༳ ༴ ༵ ༶ ༷ ༸ ༹ ༺ ༻ ༼ ༽ ༾ ༿ ཀ ཁ ག གྷ ང ཅ ཆ ཇ ཉ ཊ ཋ ཌ ཌྷ ཎ ཏ ཐ ད དྷ ན པ ཕ བ བྷ མ ཙ ཚ ཛ ཛྷ ཝ ཞ ཟ འ ཡ ར ལ ཤ ཥ ས ཧ ཨ ཀྵ ཱ ི ཱི ུ ཱུ ྲྀ ཷ ླྀ ཹ ེ ཻ ོ ཽ ཾ ཿ ྀ ཱྀ ྂ ྃ ྄ ྅ ྆ ྇ ...
|
|
||||||
Georgian
|
|
||||||
Ⴀ Ⴁ Ⴂ Ⴃ Ⴄ Ⴅ Ⴆ Ⴇ Ⴈ Ⴉ Ⴊ Ⴋ Ⴌ Ⴍ Ⴎ Ⴏ Ⴐ Ⴑ Ⴒ Ⴓ Ⴔ Ⴕ Ⴖ Ⴗ Ⴘ Ⴙ Ⴚ Ⴛ Ⴜ Ⴝ Ⴞ Ⴟ Ⴠ Ⴡ Ⴢ Ⴣ Ⴤ Ⴥ ა ბ გ დ ე ვ ზ თ ი კ ლ მ ნ ო პ ჟ რ ს ტ უ ფ ქ ღ ყ შ ჩ ც ძ წ ჭ ხ ჯ ჰ ჱ ჲ ჳ ჴ ჵ ჶ ჻
|
|
||||||
Hangul Jamo
|
|
||||||
ᄀ ᄁ ᄂ ᄃ ᄄ ᄅ ᄆ ᄇ ᄈ ᄉ ᄊ ᄋ ᄌ ᄍ ᄎ ᄏ ᄐ ᄑ ᄒ ᄓ ᄔ ᄕ ᄖ ᄗ ᄘ ᄙ ᄚ ᄛ ᄜ ᄝ ᄞ ᄟ ᄠ ᄡ ᄢ ᄣ ᄤ ᄥ ᄦ ᄧ ᄨ ᄩ ᄪ ᄫ ᄬ ᄭ ᄮ ᄯ ᄰ ᄱ ᄲ ᄳ ᄴ ᄵ ᄶ ᄷ ᄸ ᄹ ᄺ ᄻ ᄼ ᄽ ᄾ ᄿ ᅀ ᅁ ᅂ ᅃ ᅄ ᅅ ᅆ ᅇ ᅈ ᅉ ᅊ ᅋ ᅌ ᅍ ᅎ ᅏ ᅐ ᅑ ᅒ ᅓ ᅔ ᅕ ᅖ ᅗ ᅘ ᅙ ᅟ ᅠ ᅡ ᅢ ᅣ ᅤ ᅥ ᅦ ᅧ ᅨ ᅩ ᅪ ᅫ ᅬ ᅭ ᅮ ᅯ ᅰ ᅱ ᅲ ᅳ ᅴ ᅵ ᅶ ᅷ ᅸ ᅹ ᅺ ᅻ ᅼ ᅽ ᅾ ᅿ ᆀ ᆁ ᆂ ᆃ ᆄ ...
|
|
||||||
Latin Extended Additional
|
|
||||||
Ḁ ḁ Ḃ ḃ Ḅ ḅ Ḇ ḇ Ḉ ḉ Ḋ ḋ Ḍ ḍ Ḏ ḏ Ḑ ḑ Ḓ ḓ Ḕ ḕ Ḗ ḗ Ḙ ḙ Ḛ ḛ Ḝ ḝ Ḟ ḟ Ḡ ḡ Ḣ ḣ Ḥ ḥ Ḧ ḧ Ḩ ḩ Ḫ ḫ Ḭ ḭ Ḯ ḯ Ḱ ḱ Ḳ ḳ Ḵ ḵ Ḷ ḷ Ḹ ḹ Ḻ ḻ Ḽ ḽ Ḿ ḿ Ṁ ṁ Ṃ ṃ Ṅ ṅ Ṇ ṇ Ṉ ṉ Ṋ ṋ Ṍ ṍ Ṏ ṏ Ṑ ṑ Ṓ ṓ Ṕ ṕ Ṗ ṗ Ṙ ṙ Ṛ ṛ Ṝ ṝ Ṟ ṟ Ṡ ṡ Ṣ ṣ Ṥ ṥ Ṧ ṧ Ṩ ṩ Ṫ ṫ Ṭ ṭ Ṯ ṯ Ṱ ṱ Ṳ ṳ Ṵ ṵ Ṷ ṷ Ṹ ṹ Ṻ ṻ Ṽ ṽ Ṿ ṿ ...
|
|
||||||
Greek Extended
|
|
||||||
ἀ ἁ ἂ ἃ ἄ ἅ ἆ ἇ Ἀ Ἁ Ἂ Ἃ Ἄ Ἅ Ἆ Ἇ ἐ ἑ ἒ ἓ ἔ ἕ Ἐ Ἑ Ἒ Ἓ Ἔ Ἕ ἠ ἡ ἢ ἣ ἤ ἥ ἦ ἧ Ἠ Ἡ Ἢ Ἣ Ἤ Ἥ Ἦ Ἧ ἰ ἱ ἲ ἳ ἴ ἵ ἶ ἷ Ἰ Ἱ Ἲ Ἳ Ἴ Ἵ Ἶ Ἷ ὀ ὁ ὂ ὃ ὄ ὅ Ὀ Ὁ Ὂ Ὃ Ὄ Ὅ ὐ ὑ ὒ ὓ ὔ ὕ ὖ ὗ Ὑ Ὓ Ὕ Ὗ ὠ ὡ ὢ ὣ ὤ ὥ ὦ ὧ Ὠ Ὡ Ὢ Ὣ Ὤ Ὥ Ὦ Ὧ ὰ ά ὲ έ ὴ ή ὶ ί ὸ ό ὺ ύ ὼ ώ ᾀ ᾁ ᾂ ᾃ ᾄ ᾅ ᾆ ᾇ ᾈ ᾉ ᾊ ᾋ ᾌ ᾍ ...
|
|
||||||
General Punctuation
|
|
||||||
‐ ‑ ‒ – — ― ‖ ‗ ‘ ’ ‚ ‛ “ ” „ ‟ † ‡ • ‣ ․ ‥ … ‧
‰ ‱ ′ ″ ‴ ‵ ‶ ‷ ‸ ‹ › ※ ‼ ‽ ‾ ‿ ⁀ ⁁ ⁂ ⁃ ⁄ ⁅ ⁆
|
|
||||||
Superscripts and Subscripts
|
|
||||||
⁰ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ⁺ ⁻ ⁼ ⁽ ⁾ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₊ ₋ ₌ ₍ ₎
|
|
||||||
Currency Symbols
|
|
||||||
₠ ₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫
|
|
||||||
Combining Marks for Symbols
|
|
||||||
⃐ ⃑ ⃒ ⃓ ⃔ ⃕ ⃖ ⃗ ⃘ ⃙ ⃚ ⃛ ⃜ ⃝ ⃞ ⃟ ⃠ ⃡
|
|
||||||
Letterlike Symbols
|
|
||||||
℀ ℁ ℂ ℃ ℄ ℅ ℆ ℇ ℈ ℉ ℊ ℋ ℌ ℍ ℎ ℏ ℐ ℑ ℒ ℓ ℔ ℕ № ℗ ℘ ℙ ℚ ℛ ℜ ℝ ℞ ℟ ℠ ℡ ™ ℣ ℤ ℥ Ω ℧ ℨ ℩ K Å ℬ ℭ ℮ ℯ ℰ ℱ Ⅎ ℳ ℴ ℵ ℶ ℷ ℸ
|
|
||||||
Number Forms
|
|
||||||
⅓ ⅔ ⅕ ⅖ ⅗ ⅘ ⅙ ⅚ ⅛ ⅜ ⅝ ⅞ ⅟ Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ Ⅺ Ⅻ Ⅼ Ⅽ Ⅾ Ⅿ ⅰ ⅱ ⅲ ⅳ ⅴ ⅵ ⅶ ⅷ ⅸ ⅹ ⅺ ⅻ ⅼ ⅽ ⅾ ⅿ ↀ ↁ ↂ
|
|
||||||
Arrows
|
|
||||||
← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↚ ↛ ↜ ↝ ↞ ↟ ↠ ↡ ↢ ↣ ↤ ↥ ↦ ↧ ↨ ↩ ↪ ↫ ↬ ↭ ↮ ↯ ↰ ↱ ↲ ↳ ↴ ↵ ↶ ↷ ↸ ↹ ↺ ↻ ↼ ↽ ↾ ↿ ⇀ ⇁ ⇂ ⇃ ⇄ ⇅ ⇆ ⇇ ⇈ ⇉ ⇊ ⇋ ⇌ ⇍ ⇎ ⇏ ⇐ ⇑ ⇒ ⇓ ⇔ ⇕ ⇖ ⇗ ⇘ ⇙ ⇚ ⇛ ⇜ ⇝ ⇞ ⇟ ⇠ ⇡ ⇢ ⇣ ⇤ ⇥ ⇦ ⇧ ⇨ ⇩ ⇪
|
|
||||||
Mathematical Operators
|
|
||||||
∀ ∁ ∂ ∃ ∄ ∅ ∆ ∇ ∈ ∉ ∊ ∋ ∌ ∍ ∎ ∏ ∐ ∑ − ∓ ∔ ∕ ∖ ∗ ∘ ∙ √ ∛ ∜ ∝ ∞ ∟ ∠ ∡ ∢ ∣ ∤ ∥ ∦ ∧ ∨ ∩ ∪ ∫ ∬ ∭ ∮ ∯ ∰ ∱ ∲ ∳ ∴ ∵ ∶ ∷ ∸ ∹ ∺ ∻ ∼ ∽ ∾ ∿ ≀ ≁ ≂ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≏ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≠ ≡ ≢ ≣ ≤ ≥ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ...
|
|
||||||
Miscellaneous Technical
|
|
||||||
⌀ ⌂ ⌃ ⌄ ⌅ ⌆ ⌇ ⌈ ⌉ ⌊ ⌋ ⌌ ⌍ ⌎ ⌏ ⌐ ⌑ ⌒ ⌓ ⌔ ⌕ ⌖ ⌗ ⌘ ⌙ ⌚ ⌛ ⌜ ⌝ ⌞ ⌟ ⌠ ⌡ ⌢ ⌣ ⌤ ⌥ ⌦ ⌧ ⌨ 〈 〉 ⌫ ⌬ ⌭ ⌮ ⌯ ⌰ ⌱ ⌲ ⌳ ⌴ ⌵ ⌶ ⌷ ⌸ ⌹ ⌺ ⌻ ⌼ ⌽ ⌾ ⌿ ⍀ ⍁ ⍂ ⍃ ⍄ ⍅ ⍆ ⍇ ⍈ ⍉ ⍊ ⍋ ⍌ ⍍ ⍎ ⍏ ⍐ ⍑ ⍒ ⍓ ⍔ ⍕ ⍖ ⍗ ⍘ ⍙ ⍚ ⍛ ⍜ ⍝ ⍞ ⍟ ⍠ ⍡ ⍢ ⍣ ⍤ ⍥ ⍦ ⍧ ⍨ ⍩ ⍪ ⍫ ⍬ ⍭ ⍮ ⍯ ⍰ ⍱ ⍲ ⍳ ⍴ ⍵ ⍶ ⍷ ⍸ ⍹ ⍺
|
|
||||||
Control Pictures
|
|
||||||
␀ ␁ ␂ ␃ ␄ ␅ ␆ ␇ ␈ ␉ ␊ ␋ ␌ ␍ ␎ ␏ ␐ ␑ ␒ ␓ ␔ ␕ ␖ ␗ ␘ ␙ ␚ ␛ ␜ ␝ ␞ ␟ ␠ ␡ ␢ ␣ 
|
|
||||||
Optical Character Recognition
|
|
||||||
⑀ ⑁ ⑂ ⑃ ⑄ ⑅ ⑆ ⑇ ⑈ ⑉ ⑊
|
|
||||||
Enclosed Alphanumerics
|
|
||||||
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ...
|
|
||||||
Box Drawing
|
|
||||||
─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏ ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟ ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯ ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿ ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏ ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯ ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿
|
|
||||||
Block Elements
|
|
||||||
▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏ ▐ ░ ▒ ▓ ▔ ▕
|
|
||||||
Geometric Shapes
|
|
||||||
■ □ ▢ ▣ ▤ ▥ ▦ ▧ ▨ ▩ ▪ ▫ ▬ ▭ ▮ ▯ ▰ ▱ ▲ △ ▴ ▵ ▶ ▷ ▸ ▹ ► ▻ ▼ ▽ ▾ ▿ ◀ ◁ ◂ ◃ ◄ ◅ ◆ ◇ ◈ ◉ ◊ ○ ◌ ◍ ◎ ● ◐ ◑ ◒ ◓ ◔ ◕ ◖ ◗ ◘ ◙ ◚ ◛ ◜ ◝ ◞ ◟ ◠ ◡ ◢ ◣ ◤ ◥ ◦ ◧ ◨ ◩ ◪ ◫ ◬ ◭ ◮ ◯
|
|
||||||
Miscellaneous Symbols
|
|
||||||
☀ ☁ ☂ ☃ ☄ ★ ☆ ☇ ☈ ☉ ☊ ☋ ☌ ☍ ☎ ☏ ☐ ☑ ☒ ☓ ☚ ☛ ☜ ☝ ☞ ☟ ☠ ☡ ☢ ☣ ☤ ☥ ☦ ☧ ☨ ☩ ☪ ☫ ☬ ☭ ☮ ☯ ☰ ☱ ☲ ☳ ☴ ☵ ☶ ☷ ☸ ☹ ☺ ☻ ☼ ☽ ☾ ☿ ♀ ♁ ♂ ♃ ♄ ♅ ♆ ♇ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ ♔ ♕ ♖ ♗ ♘ ♙ ♚ ♛ ♜ ♝ ♞ ♟ ♠ ♡ ♢ ♣ ♤ ♥ ♦ ♧ ♨ ♩ ♪ ♫ ♬ ♭ ♮ ♯
|
|
||||||
Dingbats
|
|
||||||
✁ ✂ ✃ ✄ ✆ ✇ ✈ ✉ ✌ ✍ ✎ ✏ ✐ ✑ ✒ ✓ ✔ ✕ ✖ ✗ ✘ ✙ ✚ ✛ ✜ ✝ ✞ ✟ ✠ ✡ ✢ ✣ ✤ ✥ ✦ ✧ ✩ ✪ ✫ ✬ ✭ ✮ ✯ ✰ ✱ ✲ ✳ ✴ ✵ ✶ ✷ ✸ ✹ ✺ ✻ ✼ ✽ ✾ ✿ ❀ ❁ ❂ ❃ ❄ ❅ ❆ ❇ ❈ ❉ ❊ ❋ ❍ ❏ ❐ ❑ ❒ ❖ ❘ ❙ ❚ ❛ ❜ ❝ ❞ ❡ ❢ ❣ ❤ ❥ ❦ ❧ ❶ ❷ ❸ ❹ ❺ ❻ ❼ ❽ ❾ ❿ ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ ➓ ➔ ➘ ➙ ➚ ➛ ➜ ➝ ...
|
|
||||||
CJK Symbols and Punctuation
|
|
||||||
、 。 〃 〄 々 〆 〇 〈 〉 《 》 「 」 『 』 【 】 〒 〓 〔 〕 〖 〗 〘 〙 〚 〛 〜 〝 〞 〟 〠 〡 〢 〣 〤 〥 〦 〧 〨 〩 〪 〫 〬 〭 〮 〯 〰 〱 〲 〳 〴 〵 〶 〷 〿
|
|
||||||
Hiragana
|
|
||||||
ぁ あ ぃ い ぅ う ぇ え ぉ お か が き ぎ く ぐ け げ こ ご さ ざ し じ す ず せ ぜ そ ぞ た だ ち ぢ っ つ づ て で と ど な に ぬ ね の は ば ぱ ひ び ぴ ふ ぶ ぷ へ べ ぺ ほ ぼ ぽ ま み む め も ゃ や ゅ ゆ ょ よ ら り る れ ろ ゎ わ ゐ ゑ を ん ゔ ゙ ゚ ゛ ゜ ゝ ゞ
|
|
||||||
Katakana
|
|
||||||
ァ ア ィ イ ゥ ウ ェ エ ォ オ カ ガ キ ギ ク グ ケ ゲ コ ゴ サ ザ シ ジ ス ズ セ ゼ ソ ゾ タ ダ チ ヂ ッ ツ ヅ テ デ ト ド ナ ニ ヌ ネ ノ ハ バ パ ヒ ビ ピ フ ブ プ ヘ ベ ペ ホ ボ ポ マ ミ ム メ モ ャ ヤ ュ ユ ョ ヨ ラ リ ル レ ロ ヮ ワ ヰ ヱ ヲ ン ヴ ヵ ヶ ヷ ヸ ヹ ヺ ・ ー ヽ ヾ
|
|
||||||
Bopomofo
|
|
||||||
ㄅ ㄆ ㄇ ㄈ ㄉ ㄊ ㄋ ㄌ ㄍ ㄎ ㄏ ㄐ ㄑ ㄒ ㄓ ㄔ ㄕ ㄖ ㄗ ㄘ ㄙ ㄚ ㄛ ㄜ ㄝ ㄞ ㄟ ㄠ ㄡ ㄢ ㄣ ㄤ ㄥ ㄦ ㄧ ㄨ ㄩ ㄪ ㄫ ㄬ
|
|
||||||
@@ -18,6 +18,8 @@ typedef void OSErrorReport(const char *, ...);
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <backtrace.h>
|
#include <backtrace.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
|
||||||
API void (*Error)(const char *, ...);
|
API void (*Error)(const char *, ...);
|
||||||
|
|
||||||
@@ -1152,6 +1152,7 @@ API void InitBuffer(Allocator allocator, Buffer *buffer, BufferID id = {}, Strin
|
|||||||
if (!buffer->no_line_starts) {
|
if (!buffer->no_line_starts) {
|
||||||
Add(&buffer->line_starts, (Int)0);
|
Add(&buffer->line_starts, (Int)0);
|
||||||
}
|
}
|
||||||
|
if (DebugTraceBufferInits) printf("InitBuffer %.*s %p\n", (int)name.len, name.data, buffer->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
API void DeinitBuffer(Buffer *buffer) {
|
API void DeinitBuffer(Buffer *buffer) {
|
||||||
@@ -1161,6 +1162,7 @@ API void DeinitBuffer(Buffer *buffer) {
|
|||||||
Dealloc(&buffer->line_starts);
|
Dealloc(&buffer->line_starts);
|
||||||
DeallocHistoryArray(&buffer->undo_stack);
|
DeallocHistoryArray(&buffer->undo_stack);
|
||||||
DeallocHistoryArray(&buffer->redo_stack);
|
DeallocHistoryArray(&buffer->redo_stack);
|
||||||
|
if (DebugTraceBufferInits) printf("DeinitBuffer %.*s %p\n", (int)buffer->name.len, buffer->name.data, buffer->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indexing starts from 0 not 1 because this routine creates also the zero buffer
|
// Indexing starts from 0 not 1 because this routine creates also the zero buffer
|
||||||
@@ -256,4 +256,4 @@ void CMD_SelectComment() {
|
|||||||
}
|
}
|
||||||
MergeCarets(active.buffer, &active.view->carets);
|
MergeCarets(active.buffer, &active.view->carets);
|
||||||
|
|
||||||
} RegisterCommand(CMD_SelectComment, "ctrl-shift-l", "Find /* and */ and select the content in between");
|
} RegisterCommand(CMD_SelectComment, "ctrl-semicolon", "Find /* and */ and select the content in between");
|
||||||
@@ -80,7 +80,8 @@ void UpdateCoroutines(Event *event) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
double took = GetTimeSeconds() - start;
|
double took = GetTimeSeconds() - start;
|
||||||
if (took > (0.016666 / 3.0)) {
|
bool dont_loop_on_coroutines_when_budget_is_ok_exit_immediately = Testing;
|
||||||
|
if (dont_loop_on_coroutines_when_budget_is_ok_exit_immediately || (took > (0.016666 / 3.0))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -487,6 +487,7 @@ void GetEventsForFrame(Array<Event> *events) {
|
|||||||
For (EventPlayback) {
|
For (EventPlayback) {
|
||||||
Add(events, it);
|
Add(events, it);
|
||||||
}
|
}
|
||||||
|
EventPlayback.len = 0;
|
||||||
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
if (WaitForEventsState) {
|
if (WaitForEventsState) {
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
SDL_Window *SDLWindow;
|
SDL_Window *SDLWindow;
|
||||||
|
SDL_GLContext SDL_WindowGLContext;
|
||||||
|
SDL_Cursor *SDL_MouseCursor;
|
||||||
|
SDL_SystemCursor SDL_MouseCursorLastID;
|
||||||
bool IsInFullscreen;
|
bool IsInFullscreen;
|
||||||
int FullScreenSizeX, FullScreenSizeY;
|
int FullScreenSizeX, FullScreenSizeY;
|
||||||
int FullScreenPositionX, FullScreenPositionY;
|
int FullScreenPositionX, FullScreenPositionY;
|
||||||
bool Testing = false;
|
|
||||||
bool AppIsRunning = true;
|
bool AppIsRunning = true;
|
||||||
bool WaitForEventsState = true;
|
bool WaitForEventsState = true;
|
||||||
bool RunGCThisFrame;
|
bool RunGCThisFrame;
|
||||||
@@ -10,6 +12,8 @@ bool SearchCaseSensitive = false;
|
|||||||
bool SearchWordBoundary = false;
|
bool SearchWordBoundary = false;
|
||||||
bool BreakOnError = false;
|
bool BreakOnError = false;
|
||||||
Int ErrorCount;
|
Int ErrorCount;
|
||||||
|
bool DebugTraceBufferInits = false;
|
||||||
|
bool Testing = false;
|
||||||
|
|
||||||
Allocator SysAllocator = {SystemAllocatorProc};
|
Allocator SysAllocator = {SystemAllocatorProc};
|
||||||
float DPIScale = 1.0f;
|
float DPIScale = 1.0f;
|
||||||
@@ -61,6 +65,8 @@ Vec2I MouseMiddleAnchor;
|
|||||||
|
|
||||||
RandomSeed UniqueBufferNameSeed = {};
|
RandomSeed UniqueBufferNameSeed = {};
|
||||||
Array<Event> EventPlayback;
|
Array<Event> EventPlayback;
|
||||||
|
Array<Event> MacroPlayback;
|
||||||
|
bool RecordingMacro = false;
|
||||||
BlockArena Perm;
|
BlockArena Perm;
|
||||||
|
|
||||||
// clipboard
|
// clipboard
|
||||||
@@ -37,7 +37,7 @@ void CMD_DedentSelectedLines() {
|
|||||||
void CMD_DuplicateLineDown() {
|
void CMD_DuplicateLineDown() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
DuplicateLine(active.view, DIR_DOWN);
|
DuplicateLine(active.view, DIR_DOWN);
|
||||||
} RegisterCommand(CMD_DuplicateLineDown, "ctrl-alt-down", "");
|
} RegisterCommand(CMD_DuplicateLineDown, "ctrl-shift-alt-down", "");
|
||||||
|
|
||||||
void CMD_CreateCursorDown() {
|
void CMD_CreateCursorDown() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
@@ -72,7 +72,7 @@ void CMD_MoveDown() {
|
|||||||
void CMD_DuplicateLineUp() {
|
void CMD_DuplicateLineUp() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
DuplicateLine(active.view, DIR_UP);
|
DuplicateLine(active.view, DIR_UP);
|
||||||
} RegisterCommand(CMD_DuplicateLineUp, "ctrl-alt-up", "");
|
} RegisterCommand(CMD_DuplicateLineUp, "ctrl-shift-alt-up", "");
|
||||||
|
|
||||||
void CMD_CreateCursorUp() {
|
void CMD_CreateCursorUp() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
@@ -234,6 +234,12 @@ void CMD_NewLine() {
|
|||||||
IndentedNewLine(active.view);
|
IndentedNewLine(active.view);
|
||||||
} RegisterCommand(CMD_NewLine, "enter | shift-enter", "");
|
} RegisterCommand(CMD_NewLine, "enter | shift-enter", "");
|
||||||
|
|
||||||
|
void CMD_SearchAllOccurences() {
|
||||||
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
|
String16 needle = GetString(active.buffer, active.view->carets[0].range);
|
||||||
|
SelectAllOccurences(active.view, needle);
|
||||||
|
} RegisterCommand(CMD_SearchAllOccurences, "ctrl-shift-l", "Use the selected word as needle and selects all the possible occurences in current buffer");
|
||||||
|
|
||||||
void CMD_CreateCaretOnNextFind() {
|
void CMD_CreateCaretOnNextFind() {
|
||||||
BSet active = GetBSet(ActiveWindowID);
|
BSet active = GetBSet(ActiveWindowID);
|
||||||
String16 string = GetString(active.buffer, active.view->carets[0].range);
|
String16 string = GetString(active.buffer, active.view->carets[0].range);
|
||||||
@@ -247,3 +253,21 @@ void CMD_ClearCarets() {
|
|||||||
active.view->carets.len = 1;
|
active.view->carets.len = 1;
|
||||||
active.view->carets[0] = MakeCaret(GetFront(active.view->carets[0]));
|
active.view->carets[0] = MakeCaret(GetFront(active.view->carets[0]));
|
||||||
} RegisterCommand(CMD_ClearCarets, "escape", "Clear all carets and reset to 1 caret, also do some windowing stuff that closes things on escape");
|
} RegisterCommand(CMD_ClearCarets, "escape", "Clear all carets and reset to 1 caret, also do some windowing stuff that closes things on escape");
|
||||||
|
|
||||||
|
void CMD_ToggleMacroRecording() {
|
||||||
|
if (RecordingMacro) {
|
||||||
|
RecordingMacro = false;
|
||||||
|
Pop(&MacroPlayback); // Remove the ctrl-m from macro playback thing
|
||||||
|
} else {
|
||||||
|
RecordingMacro = true;
|
||||||
|
MacroPlayback.len = 0;
|
||||||
|
}
|
||||||
|
} RegisterCommand(CMD_ToggleMacroRecording, "ctrl-m", "Start recording a macro");
|
||||||
|
|
||||||
|
void CMD_PlayMacro() {
|
||||||
|
if (RecordingMacro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
For (MacroPlayback) Add(&EventPlayback, it);
|
||||||
|
} RegisterCommand(CMD_PlayMacro, "alt-m", "Start playing back a macro recording");
|
||||||
@@ -40,15 +40,12 @@ BSet ExecBuild(String windows_cmd, String unix_cmd, String working_dir = Project
|
|||||||
SelectRange(build.view, Range{});
|
SelectRange(build.view, Range{});
|
||||||
ResetBuffer(build.buffer);
|
ResetBuffer(build.buffer);
|
||||||
{
|
{
|
||||||
ExecArgs args = ShellArgs(scratch, build.view->id, windows_cmd, working_dir);
|
ExecArgs args = ShellArgs(scratch, build.view->id, OS_WINDOWS ? windows_cmd : unix_cmd, working_dir);
|
||||||
args.scroll_to_end = true;
|
args.scroll_to_end = true;
|
||||||
if (!OS_WINDOWS) {
|
|
||||||
args.cmd = unix_cmd;
|
|
||||||
}
|
|
||||||
Exec(args);
|
Exec(args);
|
||||||
}
|
}
|
||||||
main.window->active_goto_list = build.view->id;
|
main.window->active_goto_list = build.view->id;
|
||||||
main.window->goto_list_pos = 0;
|
main.window->goto_list_pos = -1;
|
||||||
build.window->visible = true;
|
build.window->visible = true;
|
||||||
return build;
|
return build;
|
||||||
}
|
}
|
||||||
@@ -88,17 +88,17 @@ void Set(String string) {
|
|||||||
string = Skip(string, 1);
|
string = Skip(string, 1);
|
||||||
String quote = SkipUntil(&string, {&c, 1});
|
String quote = SkipUntil(&string, {&c, 1});
|
||||||
ExpectP(At(string, 0) == c, ":Set %S <error here>, unclosed quote", name);
|
ExpectP(At(string, 0) == c, ":Set %S <error here>, unclosed quote", name);
|
||||||
ReportConsolef(":Set %S %c%S%c", name, c, quote, c);
|
// ReportConsolef(":Set %S %c%S%c", name, c, quote, c);
|
||||||
*var->string = Intern(&GlobalInternTable, quote);
|
*var->string = Intern(&GlobalInternTable, quote);
|
||||||
} else if (var->type == VariableType_Int) {
|
} else if (var->type == VariableType_Int) {
|
||||||
ExpectP(IsDigit(At(string, 0)), "Expected an integer to follow the command name, instead got: %S", string);
|
ExpectP(IsDigit(At(string, 0)), "Expected an integer to follow the command name, instead got: %S", string);
|
||||||
Int number = SkipInt(&string);
|
Int number = SkipInt(&string);
|
||||||
ReportConsolef(":Set %S %lld", name, number);
|
// ReportConsolef(":Set %S %lld", name, number);
|
||||||
*var->i = number;
|
*var->i = number;
|
||||||
} else if (var->type == VariableType_Float) {
|
} else if (var->type == VariableType_Float) {
|
||||||
ExpectP(IsDigit(At(string, 0)), "Expected float to follow the command name, instead got: %S", string);
|
ExpectP(IsDigit(At(string, 0)), "Expected float to follow the command name, instead got: %S", string);
|
||||||
Float number = SkipFloat(&string);
|
Float number = SkipFloat(&string);
|
||||||
ReportConsolef(":Set %S %f", name, number);
|
// ReportConsolef(":Set %S %f", name, number);
|
||||||
*var->f = number;
|
*var->f = number;
|
||||||
} else if (var->type == VariableType_Color) {
|
} else if (var->type == VariableType_Color) {
|
||||||
ExpectP(IsHexDigit(At(string, 0)), "Expected hex integer to follow the command name, instead got: %S", string);
|
ExpectP(IsHexDigit(At(string, 0)), "Expected hex integer to follow the command name, instead got: %S", string);
|
||||||
@@ -107,7 +107,7 @@ void Set(String string) {
|
|||||||
string = Skip(string, 1);
|
string = Skip(string, 1);
|
||||||
begin.len += 1;
|
begin.len += 1;
|
||||||
}
|
}
|
||||||
ReportConsolef(":Set %S %S", name, begin);
|
// ReportConsolef(":Set %S %S", name, begin);
|
||||||
var->color->value = (uint32_t)strtoll(begin.data, NULL, 16);
|
var->color->value = (uint32_t)strtoll(begin.data, NULL, 16);
|
||||||
} ElseInvalidCodepath();
|
} ElseInvalidCodepath();
|
||||||
|
|
||||||
@@ -48,7 +48,13 @@ void UpdateDebugWindow() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawReplaceText(set.buffer, GetRange(set.buffer), u"Active buffers and views:\n");
|
RawReplaceText(set.buffer, GetRange(set.buffer), u"");
|
||||||
|
#if OS_POSIX
|
||||||
|
struct rusage usage;
|
||||||
|
getrusage(RUSAGE_SELF, &usage);
|
||||||
|
RawAppendf(set.buffer, "MemoryUsage: %lld\n", usage.ru_maxrss);
|
||||||
|
#endif
|
||||||
|
|
||||||
For (Views) {
|
For (Views) {
|
||||||
Buffer *buffer = GetBuffer(it->active_buffer);
|
Buffer *buffer = GetBuffer(it->active_buffer);
|
||||||
RawAppendf(set.buffer, "view->id:%lld, buffer->id:%lld, buffer->name:%S\n", (long long)it->id.id, (long long)buffer->id.id, buffer->name);
|
RawAppendf(set.buffer, "view->id:%lld, buffer->id:%lld, buffer->name:%S\n", (long long)it->id.id, (long long)buffer->id.id, buffer->name);
|
||||||
@@ -8,6 +8,16 @@ void CMD_OpenUpFolder() {
|
|||||||
Open(name);
|
Open(name);
|
||||||
} RegisterCommand(CMD_OpenUpFolder, "ctrl-o", "Open current's file directory or up directory in other cases");
|
} RegisterCommand(CMD_OpenUpFolder, "ctrl-o", "Open current's file directory or up directory in other cases");
|
||||||
|
|
||||||
|
void CMD_OpenSystemFileBrowser() {
|
||||||
|
Scratch scratch;
|
||||||
|
String string = GetPrimaryDirectory();
|
||||||
|
#if OS_WINDOWS
|
||||||
|
Open(Format(scratch, "!!explorer %S", string));
|
||||||
|
#else
|
||||||
|
Open(Format(scratch, "!!xdg-open %S & disown", string));
|
||||||
|
#endif
|
||||||
|
} RegisterCommand(CMD_OpenSystemFileBrowser, "ctrl-alt-r", "Opens the directory of current file in the systems file browser");
|
||||||
|
|
||||||
void InsertDirectoryNavigation(Buffer *buffer) {
|
void InsertDirectoryNavigation(Buffer *buffer) {
|
||||||
Assert(buffer->is_dir);
|
Assert(buffer->is_dir);
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -15,6 +15,7 @@ void New(Window *window, String name = "") {
|
|||||||
name = GetUniqueBufferName(dir, "new");
|
name = GetUniqueBufferName(dir, "new");
|
||||||
}
|
}
|
||||||
WindowOpenBufferView(window, name);
|
WindowOpenBufferView(window, name);
|
||||||
|
RunGCThisFrame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMD_New() {
|
void CMD_New() {
|
||||||
@@ -140,7 +141,7 @@ void CO_ReplaceAll(mco_coro *co) {
|
|||||||
|
|
||||||
field_seek = BaseFindNext(main.buffer, u"for::", MakeCaret(0), SeekFlag_None);
|
field_seek = BaseFindNext(main.buffer, u"for::", MakeCaret(0), SeekFlag_None);
|
||||||
Range range = {field_seek.range.max, main.buffer->len};
|
Range range = {field_seek.range.max, main.buffer->len};
|
||||||
needle = GetString(main.buffer, range);
|
needle = Copy16(ctx->arena, GetString(main.buffer, range));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -64,3 +64,7 @@ void Serialize(Buffer *buffer, Event *e) {
|
|||||||
#undef X
|
#undef X
|
||||||
SerializeEnd(buffer);
|
SerializeEnd(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMD_CopyEvents() {
|
||||||
|
SaveStringInClipboard(GetString(EventBuffer));
|
||||||
|
} RegisterCommand(CMD_CopyEvents, "ctrl-shift-alt-j", "Copy all the events from the EventBuffer");
|
||||||
123
src/plugin_tests.cpp
Normal file
123
src/plugin_tests.cpp
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
#if PLUGIN_TESTS
|
||||||
|
|
||||||
|
|
||||||
|
void Wait(mco_coro *co) {
|
||||||
|
{Event ev = {};ev.kind = EVENT_KIND_INVALID; Add(&EventPlayback, ev);}
|
||||||
|
Event *event = NULL;
|
||||||
|
for (event = Yield(co); event->kind != EVENT_KIND_INVALID; event = Yield(co)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wait(mco_coro *co, int updates) {
|
||||||
|
for (int i = 0; i < updates; i += 1) {
|
||||||
|
{Event ev = {};ev.kind = EVENT_UPDATE; Add(&EventPlayback, ev);}
|
||||||
|
}
|
||||||
|
Wait(co);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenCloseCodeTest(mco_coro *co) {
|
||||||
|
Int initial_buffers_count = Buffers.len;
|
||||||
|
CO_OpenCode(co);
|
||||||
|
Assert(Buffers.len > initial_buffers_count);
|
||||||
|
CO_CloseAll(co);
|
||||||
|
Wait(co);
|
||||||
|
Assert(initial_buffers_count - 1 == Buffers.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CO_RunTests(mco_coro *co) {
|
||||||
|
Testing = true;
|
||||||
|
WaitForEvents = false;
|
||||||
|
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LSHIFT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.shift = 1; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.shift = 1; ev.text = "M"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "e"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "m"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "e"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "s"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_SPACE; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = " "; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LSHIFT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.shift = 1; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "a"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "n"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "d"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_SPACE; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = " "; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "s"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "t"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "u"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "f"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "f"; Add(&EventPlayback, ev);}
|
||||||
|
Wait(co);
|
||||||
|
|
||||||
|
String16 result = uR"FOO(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Memes and stuff)FOO";
|
||||||
|
BSet set = GetBSet(PrimaryWindowID);
|
||||||
|
Assert(AreEqual(result, GetString(set.buffer)));
|
||||||
|
|
||||||
|
// Test the box selection
|
||||||
|
CMD_New();
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_RETURN; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LSHIFT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.shift = 1; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.shift = 1; ev.text = "M"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "e"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "m"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "e"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "s"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_SPACE; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = " "; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LSHIFT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.shift = 1; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "a"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "n"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "d"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_SPACE; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = " "; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "s"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "t"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "u"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "f"; Add(&EventPlayback, ev);}
|
||||||
|
{Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1412; ev.ywindow = 1032; ev.xmouse = 1234; ev.ymouse = 594; ev.text = "f"; Add(&EventPlayback, ev);}
|
||||||
|
Wait(co);
|
||||||
|
|
||||||
|
result = uR"FOO(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Memes and stuff)FOO";
|
||||||
|
set = GetBSet(PrimaryWindowID);
|
||||||
|
Assert(AreEqual(result, GetString(set.buffer)));
|
||||||
|
|
||||||
|
if (ErrorCount != 0) {
|
||||||
|
Scratch scratch;
|
||||||
|
String string = AllocCharString(scratch, LogBuffer);
|
||||||
|
printf("TEXT EDITOR ERRORS!\n==========================\n%.*s", (int)string.len, string.data);
|
||||||
|
}
|
||||||
|
printf("RunTests OK\n");
|
||||||
|
fflush(stdout);
|
||||||
|
void CMD_QuitWithoutSaving();
|
||||||
|
CMD_QuitWithoutSaving();
|
||||||
|
} RegisterCoroutineCommand(CO_RunTests, "", "Basic tests");
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -9,14 +9,14 @@ void CMD_Prev() {
|
|||||||
main.window->skip_checkpoint = true;
|
main.window->skip_checkpoint = true;
|
||||||
JumpBack(main.window);
|
JumpBack(main.window);
|
||||||
NextActiveWindowID = main.window->id;
|
NextActiveWindowID = main.window->id;
|
||||||
} RegisterCommand(CMD_Prev, "alt-q | mousex1", "Go to previous position (either previous view that was open or caret position) in the primary window");
|
} RegisterCommand(CMD_Prev, "alt-q | mousex1 | ctrl-alt-minus", "Go to previous position (either previous view that was open or caret position) in the primary window");
|
||||||
|
|
||||||
void CMD_Next() {
|
void CMD_Next() {
|
||||||
BSet main = GetBSet(PrimaryWindowID);
|
BSet main = GetBSet(PrimaryWindowID);
|
||||||
main.window->skip_checkpoint = true;
|
main.window->skip_checkpoint = true;
|
||||||
JumpForward(main.window);
|
JumpForward(main.window);
|
||||||
NextActiveWindowID = main.window->id;
|
NextActiveWindowID = main.window->id;
|
||||||
} RegisterCommand(CMD_Next, "alt-shift-q | mousex2", "Go to next position, after backtracking, in the primary window");
|
} RegisterCommand(CMD_Next, "alt-shift-q | mousex2 | ctrl-shift-minus", "Go to next position, after backtracking, in the primary window");
|
||||||
|
|
||||||
void CMD_FocusLeftWindow() {
|
void CMD_FocusLeftWindow() {
|
||||||
NextActiveWindowID = SwitchWindow(DIR_LEFT)->id;
|
NextActiveWindowID = SwitchWindow(DIR_LEFT)->id;
|
||||||
@@ -74,9 +74,9 @@ void CMD_CloseWindow() {
|
|||||||
void CMD_GotoNextInList() {
|
void CMD_GotoNextInList() {
|
||||||
BSet main = GetBSet(PrimaryWindowID);
|
BSet main = GetBSet(PrimaryWindowID);
|
||||||
GotoNextInList(main.window, 1);
|
GotoNextInList(main.window, 1);
|
||||||
} RegisterCommand(CMD_GotoNextInList, "ctrl-e", "For example: when jumping from build panel to build error, a jump point is setup, user can click this button to go over to the next compiler error");
|
} RegisterCommand(CMD_GotoNextInList, "ctrl-e | f8", "For example: when jumping from build panel to build error, a jump point is setup, user can click this button to go over to the next compiler error");
|
||||||
|
|
||||||
void CMD_GotoPrevInList() {
|
void CMD_GotoPrevInList() {
|
||||||
BSet main = GetBSet(PrimaryWindowID);
|
BSet main = GetBSet(PrimaryWindowID);
|
||||||
GotoNextInList(main.window, -1);
|
GotoNextInList(main.window, -1);
|
||||||
} RegisterCommand(CMD_GotoPrevInList, "alt-e", "For example: when jumping from build panel to build error, a jump point is setup, user can click this button to go over to the previous compiler error");
|
} RegisterCommand(CMD_GotoPrevInList, "alt-e | shift-f8", "For example: when jumping from build panel to build error, a jump point is setup, user can click this button to go over to the previous compiler error");
|
||||||
@@ -250,8 +250,10 @@ Process SpawnProcess(ExecArgs args) {
|
|||||||
char *exe = Copy(scratch, args.exe).data;
|
char *exe = Copy(scratch, args.exe).data;
|
||||||
|
|
||||||
For (args.env) {
|
For (args.env) {
|
||||||
Add(&env, Copy(scratch, it).data);
|
Add(&env, it.data);
|
||||||
}
|
}
|
||||||
|
Add(&env, (char *)"\0");
|
||||||
|
|
||||||
|
|
||||||
int stdout_desc[2] = {};
|
int stdout_desc[2] = {};
|
||||||
int stdin_desc[2] = {};
|
int stdin_desc[2] = {};
|
||||||
@@ -349,18 +351,15 @@ bool IsValid(Process *process) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
pollfd p = {};
|
pid_t result = waitpid(plat->pid, &status, WNOHANG);
|
||||||
p.fd = plat->child_stdout_read;
|
if (result == 0) {
|
||||||
p.events = POLLRDHUP | POLLERR | POLLHUP | POLLNVAL;
|
return true;
|
||||||
int res = poll(&p, 1, 0);
|
|
||||||
if (res > 0) {
|
|
||||||
pid_t result = waitpid(plat->pid, &status, 0);
|
|
||||||
Assert(result != -1);
|
|
||||||
process->exit_code = WEXITSTATUS(status);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
Assert(result != -1);
|
||||||
|
process->exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
|
||||||
|
process->is_valid = false;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KillProcess(Process *process) {
|
void KillProcess(Process *process) {
|
||||||
@@ -382,7 +381,7 @@ String PollStdout(Allocator allocator, Process *process, bool force_read) {
|
|||||||
p.events = POLLIN;
|
p.events = POLLIN;
|
||||||
int res = poll(&p, 1, 0);
|
int res = poll(&p, 1, 0);
|
||||||
if (res > 0 || force_read) {
|
if (res > 0 || force_read) {
|
||||||
result.len = read(plat->child_stdout_read, result.data, 4 * 4096);
|
result.len = read(plat->child_stdout_read, result.data, 16 * 4096);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -403,7 +402,7 @@ void CloseStdin(Process *process) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
Process SpawnProcess(String command_line, String working_dir, String write_stdin, Array<String> enviroment) { return {}; }
|
Process SpawnProcess(ExecArgs args) { return {}; }
|
||||||
bool IsValid(Process *process) { return false; }
|
bool IsValid(Process *process) { return false; }
|
||||||
void KillProcess(Process *process) { }
|
void KillProcess(Process *process) { }
|
||||||
String PollStdout(Allocator allocator, Process *process, bool force_read) { return {}; }
|
String PollStdout(Allocator allocator, Process *process, bool force_read) { return {}; }
|
||||||
@@ -469,10 +468,9 @@ void UpdateProcesses() {
|
|||||||
View *view = GetView(it.args.output_view);
|
View *view = GetView(it.args.output_view);
|
||||||
|
|
||||||
String poll = PollStdout(scratch, &it, false);
|
String poll = PollStdout(scratch, &it, false);
|
||||||
if (poll.len) {
|
if (poll.len > 0) {
|
||||||
Append(view, poll, it.args.scroll_to_end);
|
Append(view, poll, it.args.scroll_to_end);
|
||||||
}
|
} else if (!IsValid(&it)) {
|
||||||
if (!IsValid(&it)) {
|
|
||||||
ReportConsolef("process %lld exit code = %d", it.id, it.exit_code);
|
ReportConsolef("process %lld exit code = %d", it.id, it.exit_code);
|
||||||
remove_item = true;
|
remove_item = true;
|
||||||
}
|
}
|
||||||
@@ -31,9 +31,7 @@ BlockArena RenderArena;
|
|||||||
Rect2 CurrentScissor;
|
Rect2 CurrentScissor;
|
||||||
|
|
||||||
Font PrimaryFont;
|
Font PrimaryFont;
|
||||||
Font SecondaryFont;
|
|
||||||
|
|
||||||
// ---------- shaders (ES3 / WebGL2) ----------
|
|
||||||
static const char *glsl_vshader_es3 = R"==(#version 300 es
|
static const char *glsl_vshader_es3 = R"==(#version 300 es
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
@@ -82,7 +80,6 @@ void GLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- helper: compile/link ----------
|
|
||||||
static GLuint CompileShaderSrc(GLenum kind, const char *src) {
|
static GLuint CompileShaderSrc(GLenum kind, const char *src) {
|
||||||
GLuint s = glCreateShader(kind);
|
GLuint s = glCreateShader(kind);
|
||||||
glShaderSource(s, 1, &src, NULL);
|
glShaderSource(s, 1, &src, NULL);
|
||||||
@@ -137,7 +134,6 @@ Shader CreateShaderES3(const char *vsrc, const char *fsrc) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- InitRender for ES3 ----------
|
|
||||||
void InitRender() {
|
void InitRender() {
|
||||||
#if !OS_WASM
|
#if !OS_WASM
|
||||||
glDebugMessageCallback(&GLDebugCallback, NULL);
|
glDebugMessageCallback(&GLDebugCallback, NULL);
|
||||||
@@ -185,7 +181,6 @@ void BeginFrameRender(float wx, float wy) {
|
|||||||
CurrentScissor = Rect0Size(wx, wy);
|
CurrentScissor = Rect0Size(wx, wy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- EndFrameRender for ES3 ----------
|
|
||||||
void EndFrameRender(float wx, float wy, Color color) {
|
void EndFrameRender(float wx, float wy, Color color) {
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
@@ -391,6 +386,9 @@ void ReloadFont(String path, U32 size) {
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Atlas atlas = CreateAtlas(scratch, {2048, 2048});
|
Atlas atlas = CreateAtlas(scratch, {2048, 2048});
|
||||||
PrimaryFont = CreateFont(&atlas, (uint32_t)ClampBottom(2u, (U32)size), path);
|
PrimaryFont = CreateFont(&atlas, (uint32_t)ClampBottom(2u, (U32)size), path);
|
||||||
SecondaryFont = CreateFont(&atlas, 12, path);
|
PrimaryFont.texture_id = UploadAtlas(&atlas);
|
||||||
SecondaryFont.texture_id = PrimaryFont.texture_id = UploadAtlas(&atlas);
|
}
|
||||||
|
|
||||||
|
void CleanupRender() {
|
||||||
|
Dealloc(&PrimaryFont.glyphs);
|
||||||
}
|
}
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
String TestDir;
|
|
||||||
BlockArena TestArena;
|
|
||||||
|
|
||||||
void AddCtrlPress(SDL_Keycode key) {
|
|
||||||
Event event = {};
|
|
||||||
event.key = key;
|
|
||||||
event.ctrl = 1;
|
|
||||||
event.xwindow = 1280;
|
|
||||||
event.ywindow = 720;
|
|
||||||
Add(&EventPlayback, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddText(String string) {
|
|
||||||
Event event = {};
|
|
||||||
event.kind = EVENT_TEXT_INPUT;
|
|
||||||
event.xwindow = 1280;
|
|
||||||
event.ywindow = 720;
|
|
||||||
event.text = Copy(SysAllocator, string).data;
|
|
||||||
Add(&EventPlayback, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wait(mco_coro *co) {
|
|
||||||
Add(&EventPlayback, {EVENT_KIND_INVALID});
|
|
||||||
for (Event *event = Yield(co); event->kind != EVENT_KIND_INVALID; event = Yield(co)) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlayTestOpen(mco_coro *co) {
|
|
||||||
Unused(co);
|
|
||||||
// Open file, move a little, then open again and verify the caret didn't move
|
|
||||||
// String basic_env_cpp = Format(SysAllocator, "%S/test_env", TestDir);
|
|
||||||
|
|
||||||
// AddCtrlPress(SDLK_P);
|
|
||||||
// Add(&EventPlayback, {EVENT_KEY_PRESS, SDLK_UP, 1280, 720});
|
|
||||||
// AddCtrlPress(SDLK_Q);
|
|
||||||
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_PERIOD; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_PERIOD; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_F; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_S; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "s"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_R; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "r"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_C; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "c"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_ESCAPE; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_ESCAPE; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LCTRL; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_Q; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LCTRL; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_F; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_T; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "t"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_E; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "e"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_S; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "s"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_T; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "t"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_ESCAPE; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_ESCAPE; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LCTRL; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_Q; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LCTRL; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_F; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_T; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "t"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_E; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "e"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_S; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_TEXT_INPUT; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.text = "s"; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_ESCAPE; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_ESCAPE; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_LCTRL; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
// {Event ev = {};ev.kind = EVENT_KEY_PRESS; ev.key = SDLK_Q; ev.xwindow = 1910; ev.ywindow = 2040; ev.xmouse = 581; ev.ymouse = 952; ev.ctrl = 1; Add(&EventPlayback, ev);}
|
|
||||||
|
|
||||||
// Wait(co);
|
|
||||||
|
|
||||||
// {
|
|
||||||
// BSet main = GetActiveMainSet();
|
|
||||||
// Assert(main.buffer->name == basic_env_cpp);
|
|
||||||
// Assert(main.view->carets[0].range.min == 0);
|
|
||||||
// Assert(main.view->carets[0].range.max == 0);
|
|
||||||
// Int line = PosToLine(main.buffer, main.view->carets[0].range.min);
|
|
||||||
// Assert(line == 0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// AddCtrlPress(SDLK_DOWN);
|
|
||||||
// AddCtrlPress(SDLK_DOWN);
|
|
||||||
// AddCtrlPress(SDLK_DOWN);
|
|
||||||
// Wait(co);
|
|
||||||
|
|
||||||
// Range range = {};
|
|
||||||
// {
|
|
||||||
// BSet main = GetActiveMainSet();
|
|
||||||
// Assert(main.view->carets[0].range.min > 0);
|
|
||||||
// Assert(main.view->carets[0].range.max > 0);
|
|
||||||
// range = main.view->carets[0].range;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// AddCtrlPress(SDLK_P);
|
|
||||||
// Add(&EventPlayback, {EVENT_KEY_PRESS, SDLK_UP, 1280, 720});
|
|
||||||
// AddCtrlPress(SDLK_Q);
|
|
||||||
// Wait(co);
|
|
||||||
|
|
||||||
// Int buffer_len = 0;
|
|
||||||
// {
|
|
||||||
// BSet main = GetActiveMainSet();
|
|
||||||
// Assert(main.buffer->name == basic_env_cpp);
|
|
||||||
// Assert(main.view->carets[0].range.min == range.min);
|
|
||||||
// Assert(main.view->carets[0].range.max == range.max);
|
|
||||||
// buffer_len = main.buffer->len;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// AddText(Format(SysAllocator, "%S:20", basic_env_cpp));
|
|
||||||
// AddCtrlPress(SDLK_Q);
|
|
||||||
// Wait(co);
|
|
||||||
|
|
||||||
// {
|
|
||||||
// BSet main = GetActiveMainSet();
|
|
||||||
// Int pos = main.view->carets[0].range.min;
|
|
||||||
// Int line = PosToLine(main.buffer, pos);
|
|
||||||
// Assert(line == 19);
|
|
||||||
// Assert(main.buffer->name == basic_env_cpp);
|
|
||||||
// Assert(main.buffer->len != buffer_len);
|
|
||||||
// Assert(main.buffer->dirty);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// AddCtrlPress(SDLK_Z);
|
|
||||||
// AddCtrlPress(SDLK_PAGEUP);
|
|
||||||
// Wait(co);
|
|
||||||
|
|
||||||
// {
|
|
||||||
// BSet main = GetActiveMainSet();
|
|
||||||
// Assert(main.buffer->len == buffer_len);
|
|
||||||
// Assert(main.view->carets[0].range.min == 0);
|
|
||||||
// Assert(main.view->carets[0].range.max == 0);
|
|
||||||
// }
|
|
||||||
ReportConsolef("%s DONE", __FUNCTION__);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Test(mco_coro *co) {
|
|
||||||
Wait(co); // First phase starts immediately but stuff is not initialized so Open acts weird
|
|
||||||
Open(TestDir);
|
|
||||||
PlayTestOpen(co);
|
|
||||||
Release(&TestArena);
|
|
||||||
|
|
||||||
|
|
||||||
// Add(&EventPlayback, {EVENT_QUIT});
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitTests() {
|
|
||||||
WaitForEvents = false;
|
|
||||||
TestDir = Format(TestArena, "%S/test_env", GetExeDir(TestArena));
|
|
||||||
|
|
||||||
RemoveCoroutine("Test");
|
|
||||||
CCtx *data = AddCoroutine(Test);
|
|
||||||
data->dont_wait_until_resolved = true;
|
|
||||||
ResumeCoroutine(data);
|
|
||||||
}
|
|
||||||
@@ -1,45 +1,63 @@
|
|||||||
/*
|
/*
|
||||||
- [ ] Cleanups
|
|
||||||
- [ ] How to enable framerate to be unlimited and not break scrolling?
|
## Basics
|
||||||
- [x] When dragging a file into the editor, would be nice if the file opened in the window user dropped the file into. Not the active window.
|
- [ ] Ctrl+Shift+ArrowDown at the end of buffer, doesn't capture characters on last line without new line, same at the top
|
||||||
- [ ] When 2 views of same buffer are open, the view with caret below the caret which modifies the view - starts moving and getting messed up
|
- [ ] When inserting parenthesis and selection is there, put the parens on both sides?
|
||||||
- [ ] Reduce number of created buffers to one per window, should be enough
|
- [ ] I noticed WordComplete getting busted after using editor for a while and returning cutdown words but not sure how to repro ...
|
||||||
|
- [ ] Rewrite WordComplete to use CoroutineCreate, maybe try reducing globals to just the coroutine itself
|
||||||
|
- [ ] WorkComplete, Bounded search, after a while it becomes problematic with many buffers
|
||||||
|
|
||||||
|
## Monaco like design for familiarity
|
||||||
|
- [ ] ctrl-tab - switch file lister with instant hold release semantics?
|
||||||
|
- [ ] SearchAndReplace how to do better?
|
||||||
|
- [ ] ctrl-t find workspace symbols? how can we do it?
|
||||||
|
- [ ] Snippet design?
|
||||||
|
|
||||||
|
## Refactor
|
||||||
|
- [ ] Make a platform layer and separate SDL stuff out
|
||||||
|
- [ ] Report a regression in SDL in newer versions that make it so that events are doubled when unpressing the held button
|
||||||
|
- [ ] Remove -lbacktrace and add my backtrace library thing
|
||||||
|
- [ ] Refactor build.sh to accept commands and remove build_web.sh
|
||||||
- [ ] GetWindowZOrder to IterateWindowsInZOrder
|
- [ ] GetWindowZOrder to IterateWindowsInZOrder
|
||||||
- [ ] Rework history API, tagging modification blocks with carets?
|
- [ ] Investigate reworking history API, tagging modification blocks with carets?
|
||||||
|
- [ ] How to enable framerate to be unlimited and not break scrolling?
|
||||||
|
- [ ] When 2 views of same buffer are open, the view with caret below the caret which modifies the view - starts moving and getting messed up
|
||||||
- [ ] The lexing / parsing code for config / bindings appears sloppy would be nice to clean it up but I don't have any ideas
|
- [ ] The lexing / parsing code for config / bindings appears sloppy would be nice to clean it up but I don't have any ideas
|
||||||
- [ ] Directory tree doesn't make much sense! Maybe just consolidate into one folder? create nice names - the raddbg idea didn't pan out well here
|
- [ ] Redesign `:QueryFile`
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- [ ] KillProcess in console !!! - should also kill all the children ...........
|
||||||
|
- [ ] BeginLog and EndLog, show all logs in the UI thing at the end
|
||||||
|
- [ ] Fuzzy search over executed command ouput
|
||||||
|
- [ ] Command window but for executing commands without special fuzzy stuff?
|
||||||
|
- [ ] Implement Regex and jumps using regex so as to allow for using ctags
|
||||||
|
- [ ] Add UndoKinds (SnapshotUndo, DiffUndo), I want to enable history in fuzzy search buffers without a huge memory cost
|
||||||
|
- [ ] General parser / data description thing, rewrite other parsers using this, rewrite env handling
|
||||||
|
- [ ] DirNav, update lister when files change on disk
|
||||||
|
- [ ] Investigate ways to bind "open" commands to keys from config
|
||||||
|
- [ ] Ability to access and set clipboard as well as affect selection in the open scripts
|
||||||
|
- [ ] Syntax for executing commands from root of project, or maybe commands should be executed from root of the CurrentDirectory
|
||||||
|
|
||||||
|
## Test
|
||||||
- [ ] Test BlockArena correctnsess - random allocations, writes and undos, try to crash
|
- [ ] Test BlockArena correctnsess - random allocations, writes and undos, try to crash
|
||||||
|
|
||||||
- New error mechanism - we were losing errors when ReportError was called multiple times, I still want that but I don't want to lose errors, so turn it into a summary list of errors
|
## Low
|
||||||
- [ ] BeginLog EndLog, and then show all logs as a list in the UI thing
|
|
||||||
- [ ] Undo kinds (to enable history in fuzzy buffers)
|
|
||||||
- [ ] Add undo kind. Snapshot kind, so that history is possible in weird buffers without paying a huge memory cost. The idea is that we would store the exact buffer state to replace with, editor would just save history of first line etc.
|
|
||||||
|
|
||||||
- [ ] Macros
|
|
||||||
- [ ] Regex
|
|
||||||
- [ ] ctags based indexing
|
|
||||||
- [ ] WordComplete
|
|
||||||
- [ ] Rewrite WordComplete to use CoroutineCreate, maybe try reducing globals to just the coroutine itself
|
|
||||||
- [ ] More bounded? seems like it might be problematic on a bigger project but so far it isn't (even for SDL or raddbg)
|
|
||||||
- [ ] Shell / terminal buffer plugin (keep the shell alive and talk with it)
|
- [ ] Shell / terminal buffer plugin (keep the shell alive and talk with it)
|
||||||
- [ ] Directory Navigation
|
- [ ] Fix somehow OpenCode hanging the editor on big files
|
||||||
- [ ] Remake lister when files change on disk
|
|
||||||
- [ ] When saving apply all the modifications instead (like deleting files, renaming etc.) or maybe that's not even needed considering we are integrating shell commands
|
-----------------------------------------------------------------------
|
||||||
- [ ] OpenCode
|
|
||||||
- [ ] Hangs the editor on big files
|
## :QueryFile problems
|
||||||
- [ ] Open
|
- User doesn't see that he in a special mode
|
||||||
- [ ] Way to bind "open" commands to keys from config
|
- Coroutine is boundless here and the boundries of the mode are too lossely defined, it makes it strange when you learn that you are still in this mode
|
||||||
- [ ] Ability to access and set clipboard as well as affect selection in the open scripts
|
- How do we kill all the views/buffers we entered? Do we care?
|
||||||
- [ ] QueryFile
|
|
||||||
- [ ] Indicate to user that he is choosing a file
|
|
||||||
- [ ] Define clear rules for opt out (like switching to different window) and kill or views that were for choosing?
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#define PLUGIN_PROFILER 1
|
#define PLUGIN_PROFILER 1
|
||||||
|
|
||||||
#include "plugin_profiler.h"
|
#include "plugin_profiler.h"
|
||||||
#include "basic/basic.h"
|
#include "basic.h"
|
||||||
#include "basic/basic.cpp"
|
#include "basic.cpp"
|
||||||
#include "SDL3/SDL.h"
|
#include "SDL3/SDL.h"
|
||||||
#include "external/glad/glad.c"
|
#include "external/glad/glad.c"
|
||||||
#include "external/glad/glad.h"
|
#include "external/glad/glad.h"
|
||||||
@@ -50,9 +68,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#define MINICORO_IMPL
|
#define MINICORO_IMPL
|
||||||
#include "external/minicoro.h"
|
#include "external/minicoro.h"
|
||||||
#include "render/generated_font.cpp"
|
#include "render_generated_font.cpp"
|
||||||
#include "render/font.cpp"
|
#include "render_font.cpp"
|
||||||
#include "render/opengl.cpp"
|
#include "render_opengl.cpp"
|
||||||
|
|
||||||
#define PLUGIN_CONFIG 1
|
#define PLUGIN_CONFIG 1
|
||||||
#define PLUGIN_SEARCH_WINDOW 1
|
#define PLUGIN_SEARCH_WINDOW 1
|
||||||
@@ -74,6 +92,7 @@
|
|||||||
#define PLUGIN_REMEDYBG OS_WINDOWS
|
#define PLUGIN_REMEDYBG OS_WINDOWS
|
||||||
#define PLUGIN_FILE_COMMANDS 1
|
#define PLUGIN_FILE_COMMANDS 1
|
||||||
#define PLUGIN_WORD_COMPLETE 1
|
#define PLUGIN_WORD_COMPLETE 1
|
||||||
|
#define PLUGIN_TESTS 1
|
||||||
|
|
||||||
#include "plugin_directory_navigation.h"
|
#include "plugin_directory_navigation.h"
|
||||||
#include "plugin_search_window.h"
|
#include "plugin_search_window.h"
|
||||||
@@ -95,7 +114,6 @@
|
|||||||
#include "commands_clipboard.cpp"
|
#include "commands_clipboard.cpp"
|
||||||
#include "scratch.cpp"
|
#include "scratch.cpp"
|
||||||
#include "draw.cpp"
|
#include "draw.cpp"
|
||||||
#include "test/tests.cpp"
|
|
||||||
#include "plugin_config.cpp"
|
#include "plugin_config.cpp"
|
||||||
#include "plugin_window_management.cpp"
|
#include "plugin_window_management.cpp"
|
||||||
#include "plugin_directory_navigation.cpp"
|
#include "plugin_directory_navigation.cpp"
|
||||||
@@ -114,6 +132,7 @@
|
|||||||
#include "plugin_profiler.cpp"
|
#include "plugin_profiler.cpp"
|
||||||
#include "plugin_file_commands.cpp"
|
#include "plugin_file_commands.cpp"
|
||||||
#include "plugin_word_complete.cpp"
|
#include "plugin_word_complete.cpp"
|
||||||
|
#include "plugin_tests.cpp"
|
||||||
|
|
||||||
#if OS_WASM
|
#if OS_WASM
|
||||||
EM_JS(void, JS_SetMouseCursor, (const char *cursor_str), {
|
EM_JS(void, JS_SetMouseCursor, (const char *cursor_str), {
|
||||||
@@ -137,16 +156,13 @@ void SetMouseCursor(SDL_SystemCursor id) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void SetMouseCursor(SDL_SystemCursor id) {
|
void SetMouseCursor(SDL_SystemCursor id) {
|
||||||
static SDL_Cursor *SDL_MouseCursor;
|
if (SDL_MouseCursor == NULL || SDL_MouseCursorLastID != id) {
|
||||||
static SDL_SystemCursor last_id;
|
|
||||||
|
|
||||||
if (SDL_MouseCursor == NULL || last_id != id) {
|
|
||||||
if (SDL_MouseCursor != NULL) {
|
if (SDL_MouseCursor != NULL) {
|
||||||
SDL_DestroyCursor(SDL_MouseCursor);
|
SDL_DestroyCursor(SDL_MouseCursor);
|
||||||
}
|
}
|
||||||
SDL_MouseCursor = SDL_CreateSystemCursor(id);
|
SDL_MouseCursor = SDL_CreateSystemCursor(id);
|
||||||
SDL_SetCursor(SDL_MouseCursor);
|
SDL_SetCursor(SDL_MouseCursor);
|
||||||
last_id = id;
|
SDL_MouseCursorLastID = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -199,9 +215,6 @@ void SetMouseCursor(Event event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CMD_QuitWithoutSaving() {
|
void CMD_QuitWithoutSaving() {
|
||||||
#if PLUGIN_REMEDYBG
|
|
||||||
QuitDebugger();
|
|
||||||
#endif
|
|
||||||
AppIsRunning = false;
|
AppIsRunning = false;
|
||||||
} RegisterCommand(CMD_QuitWithoutSaving, "", "Self explanatory");
|
} RegisterCommand(CMD_QuitWithoutSaving, "", "Self explanatory");
|
||||||
|
|
||||||
@@ -291,6 +304,27 @@ void OnCommand(Event event) {
|
|||||||
Int p = ScreenSpaceToBufferPos(selected.window, selected.view, selected.buffer, mouse);
|
Int p = ScreenSpaceToBufferPos(selected.window, selected.view, selected.buffer, mouse);
|
||||||
Caret &caret = selected.view->carets[0];
|
Caret &caret = selected.view->carets[0];
|
||||||
caret = SetFrontWithAnchor(caret, DocumentAnchor, p);
|
caret = SetFrontWithAnchor(caret, DocumentAnchor, p);
|
||||||
|
|
||||||
|
if (event.alt && event.shift) {
|
||||||
|
Int front = GetFront(DocumentAnchor);
|
||||||
|
XY from = PosToXY(selected.buffer, front);
|
||||||
|
XY to = ScreenSpaceToXY(selected.window, selected.view, mouse);
|
||||||
|
Int min_line = Min(from.y, to.y);
|
||||||
|
Int max_line = Max(from.y, to.y);
|
||||||
|
Int min_col = Min(from.x, to.x);
|
||||||
|
Int max_col = Max(from.x, to.x);
|
||||||
|
|
||||||
|
selected.view->carets.len = 0;
|
||||||
|
for (Int line = min_line; line <= max_line; line += 1) {
|
||||||
|
XY left_xy = {min_col, line};
|
||||||
|
XY right_xy = {max_col, line};
|
||||||
|
Int left = XYToPosWithoutNL(selected.buffer, left_xy);
|
||||||
|
Int right = XYToPosWithoutNL(selected.buffer, right_xy);
|
||||||
|
Caret new_selection = MakeCaret(left, right);
|
||||||
|
Add(&selected.view->carets, new_selection);
|
||||||
|
}
|
||||||
|
MergeCarets(selected.buffer, &selected.view->carets);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ResizerSelected.id != -1 && Mouse(LEFT_UP)) {
|
if (ResizerSelected.id != -1 && Mouse(LEFT_UP)) {
|
||||||
@@ -397,8 +431,11 @@ void OnCommand(Event event) {
|
|||||||
DocumentSelected = active.window->id;
|
DocumentSelected = active.window->id;
|
||||||
|
|
||||||
Int p = ScreenSpaceToBufferPos(active.window, active.view, active.buffer, mouse);
|
Int p = ScreenSpaceToBufferPos(active.window, active.view, active.buffer, mouse);
|
||||||
if (event.alt) Insert(&active.view->carets, MakeCaret(p, p), 0);
|
if (event.alt) {
|
||||||
if (!event.alt && !event.shift) active.view->carets.len = 1;
|
Insert(&active.view->carets, MakeCaret(p, p), 0);
|
||||||
|
} else if (!event.alt && !event.shift) {
|
||||||
|
active.view->carets.len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
Caret &caret = active.view->carets[0];
|
Caret &caret = active.view->carets[0];
|
||||||
if (event.shift) {
|
if (event.shift) {
|
||||||
@@ -530,6 +567,7 @@ void GarbageCollect() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RunGCThisFrame = false;
|
RunGCThisFrame = false;
|
||||||
|
ReportConsolef("GarbageCollect");
|
||||||
|
|
||||||
ProfileFunction();
|
ProfileFunction();
|
||||||
Allocator sys_allocator = GetSystemAllocator();
|
Allocator sys_allocator = GetSystemAllocator();
|
||||||
@@ -551,8 +589,8 @@ void GarbageCollect() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ref = ViewIsReferenced(it);
|
Int ref = ViewIsReferenced(it);
|
||||||
if (ref) {
|
if (ref < 25) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,6 +861,9 @@ void MainLoop() {
|
|||||||
FrameEvents.len = 0;
|
FrameEvents.len = 0;
|
||||||
GetEventsForFrame(&FrameEvents);
|
GetEventsForFrame(&FrameEvents);
|
||||||
For (FrameEvents) {
|
For (FrameEvents) {
|
||||||
|
if (RecordingMacro) {
|
||||||
|
Add(&MacroPlayback, it);
|
||||||
|
}
|
||||||
#if PLUGIN_RECORD_EVENTS
|
#if PLUGIN_RECORD_EVENTS
|
||||||
if (it.kind != EVENT_UPDATE && !Testing) {
|
if (it.kind != EVENT_UPDATE && !Testing) {
|
||||||
Serialize(EventBuffer, &it);
|
Serialize(EventBuffer, &it);
|
||||||
@@ -887,7 +928,7 @@ void MainLoop() {
|
|||||||
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||||
#else
|
#else
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv, char **envp)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
@@ -895,8 +936,8 @@ int main(int argc, char **argv)
|
|||||||
char **argv = __argv;
|
char **argv = __argv;
|
||||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||||
#endif
|
#endif
|
||||||
InitScratch();
|
|
||||||
InitOS(ReportErrorf);
|
InitOS(ReportErrorf);
|
||||||
|
InitScratch();
|
||||||
|
|
||||||
ProjectFolder = GetWorkingDir(Perm);
|
ProjectFolder = GetWorkingDir(Perm);
|
||||||
HomeFolder = SDL_GetUserFolder(SDL_FOLDER_HOME);
|
HomeFolder = SDL_GetUserFolder(SDL_FOLDER_HOME);
|
||||||
@@ -924,8 +965,16 @@ int main(int argc, char **argv)
|
|||||||
// FreeEnvironmentStringsW(p); // I get a trap here? why?
|
// FreeEnvironmentStringsW(p); // I get a trap here? why?
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
for (int i = 0; environ[i]; i += 1) {
|
char **env = envp;
|
||||||
Add(&ProcessEnviroment, Copy(Perm, environ[i]));
|
if (!env || !env[0]) {
|
||||||
|
env = environ;
|
||||||
|
}
|
||||||
|
if (env && env[0]) {
|
||||||
|
for (int i = 0; env[i]; i += 1) {
|
||||||
|
Add(&ProcessEnviroment, Copy(Perm, env[i]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ReportErrorf("No environment variables found (envp/environ empty)");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -987,8 +1036,8 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
SDL_SetWindowPosition(SDLWindow, xhalf, yhalf);
|
SDL_SetWindowPosition(SDLWindow, xhalf, yhalf);
|
||||||
|
|
||||||
SDL_GLContext gl_context = SDL_GL_CreateContext(SDLWindow);
|
SDL_WindowGLContext = SDL_GL_CreateContext(SDLWindow);
|
||||||
SDL_GL_MakeCurrent(SDLWindow, gl_context);
|
SDL_GL_MakeCurrent(SDLWindow, SDL_WindowGLContext);
|
||||||
SDL_ShowWindow(SDLWindow);
|
SDL_ShowWindow(SDLWindow);
|
||||||
|
|
||||||
// Set icon
|
// Set icon
|
||||||
@@ -1079,7 +1128,6 @@ int main(int argc, char **argv)
|
|||||||
Open(argv[i]);
|
Open(argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Testing) InitTests();
|
|
||||||
#if PLUGIN_LOAD_VCVARS
|
#if PLUGIN_LOAD_VCVARS
|
||||||
LoadVCVars();
|
LoadVCVars();
|
||||||
#endif
|
#endif
|
||||||
@@ -1112,6 +1160,10 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PLUGIN_REMEDYBG
|
||||||
|
QuitDebugger();
|
||||||
|
#endif
|
||||||
|
CleanupRender();
|
||||||
SDL_DestroyWindow(SDLWindow);
|
SDL_DestroyWindow(SDLWindow);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@ void JumpTempBuffer(BSet *set, String buffer_name) {
|
|||||||
set->view = WindowOpenBufferView(set->window, buffer_name);
|
set->view = WindowOpenBufferView(set->window, buffer_name);
|
||||||
set->buffer = GetBuffer(set->view->active_buffer);
|
set->buffer = GetBuffer(set->view->active_buffer);
|
||||||
set->buffer->temp = true;
|
set->buffer->temp = true;
|
||||||
|
RunGCThisFrame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCommand(Array<Command> *arr, String name, Trigger *trigger, CMDFunction *function) {
|
void AddCommand(Array<Command> *arr, String name, Trigger *trigger, CMDFunction *function) {
|
||||||
@@ -530,6 +531,7 @@ BSet Open(Window *window, String path, ResolveOpenMeta meta, bool set_active = t
|
|||||||
CenterView(window->id);
|
CenterView(window->id);
|
||||||
} else if (o.kind == OpenKind_Exec) {
|
} else if (o.kind == OpenKind_Exec) {
|
||||||
ExecArgs args = {};// ShellArgs(scratch, LogView->id, o.path, GetPrimaryDirectory());
|
ExecArgs args = {};// ShellArgs(scratch, LogView->id, o.path, GetPrimaryDirectory());
|
||||||
|
args.env = ProcessEnviroment;
|
||||||
args.poll_process = 1;
|
args.poll_process = 1;
|
||||||
args.output_view = LogView->id;
|
args.output_view = LogView->id;
|
||||||
args.cwd = GetPrimaryDirectory();
|
args.cwd = GetPrimaryDirectory();
|
||||||
@@ -103,6 +103,22 @@ API bool ViewIsCrumb(ViewID view_id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
API Int GetViewReferencedInHistoryRating(ViewID view_id) {
|
||||||
|
ForItem (window, Windows) {
|
||||||
|
For (window->goto_redo) if (it.view_id == view_id) return 1;
|
||||||
|
Int i = 0;
|
||||||
|
For (window->goto_history) {
|
||||||
|
i += 1;
|
||||||
|
if (it.view_id == view_id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ViewIsActive(ViewID id) {
|
bool ViewIsActive(ViewID id) {
|
||||||
For (Windows) {
|
For (Windows) {
|
||||||
if (it->active_view == id) {
|
if (it->active_view == id) {
|
||||||
@@ -112,16 +128,16 @@ bool ViewIsActive(ViewID id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
API bool ViewIsReferenced(View *view) {
|
API Int ViewIsReferenced(View *view) {
|
||||||
if (view->special) {
|
if (view->special) {
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ViewIsCrumb(view->id)) {
|
if (ViewIsActive(view->id)) {
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ViewIsActive(view->id);
|
return GetViewReferencedInHistoryRating(view->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferIsReferenced(Buffer *buffer) {
|
bool BufferIsReferenced(Buffer *buffer) {
|
||||||
@@ -176,20 +176,22 @@ Window *SwitchWindow(int direction) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int ScreenSpaceToBufferPos(Window *window, View *view, Buffer *buffer, Vec2I mouse) {
|
XY ScreenSpaceToXY(Window *window, View *view, Vec2I mouse) {
|
||||||
Vec2I mworld = mouse - window->document_rect.min + view->scroll;
|
Vec2I mworld = mouse - window->document_rect.min + view->scroll;
|
||||||
double px = (double)mworld.x / (double)window->font->char_spacing;
|
double px = (double)mworld.x / (double)window->font->char_spacing;
|
||||||
double py = (double)mworld.y / (double)window->font->line_spacing;
|
double py = (double)mworld.y / (double)window->font->line_spacing;
|
||||||
XY xy = {(Int)round(px), (Int)floor(py)};
|
XY xy = {(Int)round(px), (Int)floor(py)};
|
||||||
|
return xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
Int ScreenSpaceToBufferPos(Window *window, View *view, Buffer *buffer, Vec2I mouse) {
|
||||||
|
XY xy = ScreenSpaceToXY(window, view, mouse);
|
||||||
Int result = XYToPosWithoutNL(buffer, xy);
|
Int result = XYToPosWithoutNL(buffer, xy);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int ScreenSpaceToBufferPosErrorOutOfBounds(Window *window, View *view, Buffer *buffer, Vec2I mouse) {
|
Int ScreenSpaceToBufferPosErrorOutOfBounds(Window *window, View *view, Buffer *buffer, Vec2I mouse) {
|
||||||
Vec2I mworld = mouse - window->document_rect.min + view->scroll;
|
XY xy = ScreenSpaceToXY(window, view, mouse);
|
||||||
double px = (double)mworld.x / (double)window->font->char_spacing;
|
|
||||||
double py = (double)mworld.y / (double)window->font->line_spacing;
|
|
||||||
XY xy = {(Int)round(px), (Int)floor(py)};
|
|
||||||
Int result = XYToPosErrorOutOfBounds(buffer, xy);
|
Int result = XYToPosErrorOutOfBounds(buffer, xy);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -274,10 +276,16 @@ void GotoNextInList(Window *window, Int line_offset = 1) {
|
|||||||
|
|
||||||
Buffer *buffer_goto = GetBuffer(view_goto->active_buffer);
|
Buffer *buffer_goto = GetBuffer(view_goto->active_buffer);
|
||||||
int64_t pos = window->goto_list_pos;
|
int64_t pos = window->goto_list_pos;
|
||||||
|
Int start_line = 0;
|
||||||
|
if (pos < 0) {
|
||||||
|
start_line = line_offset > 0 ? 0 : buffer_goto->line_starts.len - 1;
|
||||||
|
} else {
|
||||||
Int line = PosToLine(buffer_goto, pos);
|
Int line = PosToLine(buffer_goto, pos);
|
||||||
|
start_line = line + line_offset;
|
||||||
|
}
|
||||||
|
|
||||||
bool opened = false;
|
bool opened = false;
|
||||||
for (Int i = line + line_offset; i >= 0 && i < buffer_goto->line_starts.len; i += line_offset) {
|
for (Int i = start_line; i >= 0 && i < buffer_goto->line_starts.len; i += line_offset) {
|
||||||
Range line_range = GetLineRangeWithoutNL(buffer_goto, i);
|
Range line_range = GetLineRangeWithoutNL(buffer_goto, i);
|
||||||
String16 string_line = GetString(buffer_goto, line_range);
|
String16 string_line = GetString(buffer_goto, line_range);
|
||||||
|
|
||||||
Reference in New Issue
Block a user