make things look a little prettier
parent
16b8b4084d
commit
2ba63ea655
356
src/main.odin
356
src/main.odin
|
@ -1,15 +1,84 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "core:os"
|
import "core:os"
|
||||||
|
import "core:math"
|
||||||
|
import "core:strings"
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
import "vendor:raylib"
|
import "vendor:raylib"
|
||||||
|
|
||||||
source_font_width :: 8;
|
source_font_width :: 8*2;
|
||||||
source_font_height :: 16;
|
source_font_height :: 16*2;
|
||||||
line_number_padding :: 4 * source_font_width;
|
line_number_padding :: 5 * source_font_width;
|
||||||
|
|
||||||
|
PaletteColor :: enum {
|
||||||
|
Background,
|
||||||
|
Foreground,
|
||||||
|
|
||||||
|
Background1,
|
||||||
|
Background2,
|
||||||
|
Background3,
|
||||||
|
Background4,
|
||||||
|
|
||||||
|
Foreground1,
|
||||||
|
Foreground2,
|
||||||
|
Foreground3,
|
||||||
|
Foreground4,
|
||||||
|
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
Yellow,
|
||||||
|
Blue,
|
||||||
|
Purple,
|
||||||
|
Aqua,
|
||||||
|
Gray,
|
||||||
|
|
||||||
|
BrightRed,
|
||||||
|
BrightGreen,
|
||||||
|
BrightYellow,
|
||||||
|
BrightBlue,
|
||||||
|
BrightPurple,
|
||||||
|
BrightAqua,
|
||||||
|
BrightGray,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Its the gruvbox dark theme <https://github.com/morhetz/gruvbox>
|
||||||
|
palette := []u32 {
|
||||||
|
0x282828ff,
|
||||||
|
0xebdbb2ff,
|
||||||
|
|
||||||
|
0x3c3836ff,
|
||||||
|
0x504945ff,
|
||||||
|
0x665c54ff,
|
||||||
|
0x7c6f64ff,
|
||||||
|
|
||||||
|
0xfbf1c7ff,
|
||||||
|
0xebdbb2ff,
|
||||||
|
0xd5c4a1ff,
|
||||||
|
0xbdae93ff,
|
||||||
|
|
||||||
|
0xcc241dff,
|
||||||
|
0x98981aff,
|
||||||
|
0xd79921ff,
|
||||||
|
0x458588ff,
|
||||||
|
0xb16286ff,
|
||||||
|
0x689d6aff,
|
||||||
|
0xa89984ff,
|
||||||
|
|
||||||
|
0xfb4934ff,
|
||||||
|
0xb8bb26ff,
|
||||||
|
0xfabd2fff,
|
||||||
|
0x83a598ff,
|
||||||
|
0xd3869bff,
|
||||||
|
0x8ec07cff,
|
||||||
|
0x928374ff,
|
||||||
|
};
|
||||||
|
|
||||||
|
get_palette_raylib_color :: proc(palette_color: PaletteColor) -> raylib.Color {
|
||||||
|
return raylib.GetColor(palette[palette_color]);
|
||||||
|
}
|
||||||
|
|
||||||
ErrorType :: enum {
|
ErrorType :: enum {
|
||||||
None,
|
None,
|
||||||
|
@ -66,7 +135,7 @@ Cursor :: struct {
|
||||||
|
|
||||||
Glyph :: struct #packed {
|
Glyph :: struct #packed {
|
||||||
codepoint: u8,
|
codepoint: u8,
|
||||||
color: u16,
|
color: PaletteColor,
|
||||||
}
|
}
|
||||||
|
|
||||||
FileBuffer :: struct {
|
FileBuffer :: struct {
|
||||||
|
@ -116,6 +185,15 @@ iterate_file_buffer :: proc(it: ^FileBufferIter) -> (character: u8, idx: FileBuf
|
||||||
cond = true;
|
cond = true;
|
||||||
|
|
||||||
character = it.buffer.content_slices[it.cursor.index.slice_index][it.cursor.index.content_index];
|
character = it.buffer.content_slices[it.cursor.index.slice_index][it.cursor.index.content_index];
|
||||||
|
if it.cursor.index.content_index < len(it.buffer.content_slices[it.cursor.index.slice_index])-1 {
|
||||||
|
it.cursor.index.content_index += 1;
|
||||||
|
} else if it.cursor.index.slice_index < len(it.buffer.content_slices)-1 {
|
||||||
|
it.cursor.index.content_index = 0;
|
||||||
|
it.cursor.index.slice_index += 1;
|
||||||
|
} else {
|
||||||
|
return character, it.cursor.index, false;
|
||||||
|
}
|
||||||
|
|
||||||
if character == '\n' {
|
if character == '\n' {
|
||||||
it.cursor.col = 0;
|
it.cursor.col = 0;
|
||||||
it.cursor.line += 1;
|
it.cursor.line += 1;
|
||||||
|
@ -123,14 +201,10 @@ iterate_file_buffer :: proc(it: ^FileBufferIter) -> (character: u8, idx: FileBuf
|
||||||
it.cursor.col += 1;
|
it.cursor.col += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
it.cursor.index.content_index += 1;
|
return character, it.cursor.index, true;
|
||||||
if it.cursor.index.content_index >= len(it.buffer.content_slices[it.cursor.index.slice_index]) {
|
|
||||||
it.cursor.index.content_index = 0;
|
|
||||||
it.cursor.index.slice_index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
// NOTE: This give the character for the NEXT position, unlike the non-reverse version
|
||||||
|
// which gives the character for the CURRENT position.
|
||||||
iterate_file_buffer_reverse_mangle_cursor :: proc(it: ^FileBufferIter) -> (character: u8, idx: FileBufferIndex, cond: bool) {
|
iterate_file_buffer_reverse_mangle_cursor :: proc(it: ^FileBufferIter) -> (character: u8, idx: FileBufferIndex, cond: bool) {
|
||||||
if it.cursor.index.content_index == 0 {
|
if it.cursor.index.content_index == 0 {
|
||||||
if it.cursor.index.slice_index > 0 {
|
if it.cursor.index.slice_index > 0 {
|
||||||
|
@ -165,6 +239,94 @@ iterate_file_buffer_reverse :: proc(it: ^FileBufferIter) -> (character: u8, idx:
|
||||||
return character, it.cursor.index, cond;
|
return character, it.cursor.index, cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_character_at_iter :: proc(it: FileBufferIter) -> u8 {
|
||||||
|
return it.buffer.content_slices[it.cursor.index.slice_index][it.cursor.index.content_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
IterProc :: proc(it: ^FileBufferIter) -> (character: u8, idx: FileBufferIndex, cond: bool);
|
||||||
|
UntilProc :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool;
|
||||||
|
|
||||||
|
iterate_file_buffer_until :: proc(it: ^FileBufferIter, until_proc: UntilProc) {
|
||||||
|
for until_proc(it, iterate_file_buffer) {}
|
||||||
|
}
|
||||||
|
iterate_file_buffer_until_reverse :: proc(it: ^FileBufferIter, until_proc: UntilProc) {
|
||||||
|
for until_proc(it, iterate_file_buffer_reverse) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
until_non_whitespace :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
|
if character, _, cond := iter_proc(it); cond && strings.is_space(rune(character)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
until_non_alpha_num :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
|
// TODO: make this global
|
||||||
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
|
||||||
|
peek_it := it^;
|
||||||
|
if character, _, cond := iter_proc(&peek_it); cond && strings.ascii_set_contains(set, character) {
|
||||||
|
it^ = peek_it;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
until_end_of_word :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
|
set, _ := strings.ascii_set_make("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
|
||||||
|
|
||||||
|
if character, _, cond := iter_proc(it); cond && !strings.ascii_set_contains(set, character) && !strings.is_space(rune(character)) {
|
||||||
|
for until_non_whitespace(it, iter_proc) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for until_non_alpha_num(it, iter_proc) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
until_double_quote :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
|
before_it := it^;
|
||||||
|
character, _, cond := iter_proc(it);
|
||||||
|
if !cond { return cond; }
|
||||||
|
|
||||||
|
// skip over escaped characters
|
||||||
|
if character == '\\' {
|
||||||
|
_, _, cond = iter_proc(it);
|
||||||
|
} else if character == '"' {
|
||||||
|
it^ = before_it;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
until_single_quote :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> bool {
|
||||||
|
before_it := it^;
|
||||||
|
character, _, cond := iter_proc(it);
|
||||||
|
if !cond { return cond; }
|
||||||
|
|
||||||
|
// skip over escaped characters
|
||||||
|
if character == '\\' {
|
||||||
|
_, _, cond = iter_proc(it);
|
||||||
|
} else if character == '\'' {
|
||||||
|
it^ = before_it;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
until_line_break :: proc(it: ^FileBufferIter, iter_proc: IterProc) -> (cond: bool) {
|
||||||
|
if it.buffer.content_slices[it.cursor.index.slice_index][it.cursor.index.content_index] == '\n' {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, cond = iter_proc(it);
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
update_file_buffer_index_from_cursor :: proc(buffer: ^FileBuffer) {
|
update_file_buffer_index_from_cursor :: proc(buffer: ^FileBuffer) {
|
||||||
it := new_file_buffer_iter(buffer);
|
it := new_file_buffer_iter(buffer);
|
||||||
before_it := new_file_buffer_iter(buffer);
|
before_it := new_file_buffer_iter(buffer);
|
||||||
|
@ -299,7 +461,7 @@ new_file_buffer :: proc(allocator: mem.Allocator, file_path: string) -> (FileBuf
|
||||||
|
|
||||||
if original_content, success := os.read_entire_file_from_handle(fd); success {
|
if original_content, success := os.read_entire_file_from_handle(fd); success {
|
||||||
width := 256;
|
width := 256;
|
||||||
height := 50;
|
height := 256;
|
||||||
|
|
||||||
buffer := FileBuffer {
|
buffer := FileBuffer {
|
||||||
allocator = allocator,
|
allocator = allocator,
|
||||||
|
@ -324,6 +486,109 @@ new_file_buffer :: proc(allocator: mem.Allocator, file_path: string) -> (FileBuf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
color_character :: proc(buffer: ^FileBuffer, start: Cursor, end: Cursor, palette_index: PaletteColor) {
|
||||||
|
start, end := start, end;
|
||||||
|
|
||||||
|
if end.line < buffer.top_line { return; }
|
||||||
|
if start.line < buffer.top_line {
|
||||||
|
start.line = 0;
|
||||||
|
} else {
|
||||||
|
start.line -= buffer.top_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
if end.line >= buffer.top_line + buffer.glyph_buffer_height {
|
||||||
|
end.line = buffer.glyph_buffer_height - 1;
|
||||||
|
end.col = buffer.glyph_buffer_width - 1;
|
||||||
|
} else {
|
||||||
|
end.line -= buffer.top_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
for j in start.line..=end.line {
|
||||||
|
start_col := start.col;
|
||||||
|
end_col := end.col;
|
||||||
|
if j > start.line && j < end.line {
|
||||||
|
start_col = 0;
|
||||||
|
end_col = buffer.glyph_buffer_width;
|
||||||
|
} else if j < end.line {
|
||||||
|
end_col = buffer.glyph_buffer_width;
|
||||||
|
} else if j > start.line && j == end.line {
|
||||||
|
start_col = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in start_col..<math.min(end_col+1, buffer.glyph_buffer_width) {
|
||||||
|
buffer.glyph_buffer[i + j * buffer.glyph_buffer_width].color = palette_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
color_buffer :: proc(buffer: ^FileBuffer) {
|
||||||
|
start_it := new_file_buffer_iter(buffer);
|
||||||
|
it := new_file_buffer_iter(buffer);
|
||||||
|
|
||||||
|
for character in iterate_file_buffer(&it) {
|
||||||
|
if it.cursor.line > it.buffer.glyph_buffer_height && (it.cursor.line - it.buffer.top_line) > it.buffer.glyph_buffer_height {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if character == '/' {
|
||||||
|
start_it = it;
|
||||||
|
// need to go back one character because `it` is on the next character
|
||||||
|
iterate_file_buffer_reverse(&start_it);
|
||||||
|
|
||||||
|
character, _, succ := iterate_file_buffer(&it);
|
||||||
|
if !succ { break; }
|
||||||
|
|
||||||
|
if character == '/' {
|
||||||
|
iterate_file_buffer_until(&it, until_line_break);
|
||||||
|
color_character(buffer, start_it.cursor, it.cursor, .Foreground4);
|
||||||
|
} else if character == '*' {
|
||||||
|
// TODO: block comments
|
||||||
|
}
|
||||||
|
} else if character == '\'' {
|
||||||
|
start_it = it;
|
||||||
|
// need to go back one character because `it` is on the next character
|
||||||
|
iterate_file_buffer_reverse(&start_it);
|
||||||
|
|
||||||
|
// jump into the quoted text
|
||||||
|
iterate_file_buffer_until(&it, until_single_quote);
|
||||||
|
color_character(buffer, start_it.cursor, it.cursor, .Yellow);
|
||||||
|
|
||||||
|
iterate_file_buffer(&it);
|
||||||
|
} else if character == '"' {
|
||||||
|
start_it = it;
|
||||||
|
// need to go back one character because `it` is on the next character
|
||||||
|
iterate_file_buffer_reverse(&start_it);
|
||||||
|
|
||||||
|
// jump into the quoted text
|
||||||
|
iterate_file_buffer_until(&it, until_double_quote);
|
||||||
|
color_character(buffer, start_it.cursor, it.cursor, .Yellow);
|
||||||
|
|
||||||
|
iterate_file_buffer(&it);
|
||||||
|
} else if (character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || character == '_' {
|
||||||
|
start_it = it;
|
||||||
|
// need to go back one character because `it` is on the next character
|
||||||
|
iterate_file_buffer_reverse(&start_it);
|
||||||
|
it = start_it;
|
||||||
|
|
||||||
|
iterate_file_buffer_until(&it, until_end_of_word);
|
||||||
|
|
||||||
|
end_of_word_it := it;
|
||||||
|
_, _, succ := iterate_file_buffer_reverse(&end_of_word_it);
|
||||||
|
if !succ { break; }
|
||||||
|
|
||||||
|
// TODO: color keywords
|
||||||
|
|
||||||
|
if character, _, cond := iterate_file_buffer(&it); cond {
|
||||||
|
if character == '(' {
|
||||||
|
color_character(buffer, start_it.cursor, end_of_word_it.cursor, .Green);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update_glyph_buffer :: proc(buffer: ^FileBuffer) {
|
update_glyph_buffer :: proc(buffer: ^FileBuffer) {
|
||||||
for &glyph in buffer.glyph_buffer {
|
for &glyph in buffer.glyph_buffer {
|
||||||
glyph = Glyph{};
|
glyph = Glyph{};
|
||||||
|
@ -353,7 +618,7 @@ update_glyph_buffer :: proc(buffer: ^FileBuffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if rendered_line >= begin && rendered_col < buffer.glyph_buffer_width {
|
if rendered_line >= begin && rendered_col < buffer.glyph_buffer_width {
|
||||||
buffer.glyph_buffer[rendered_col + screen_line * buffer.glyph_buffer_width].color = 0xFFFF;
|
buffer.glyph_buffer[rendered_col + screen_line * buffer.glyph_buffer_width].color = .Foreground;
|
||||||
buffer.glyph_buffer[rendered_col + screen_line * buffer.glyph_buffer_width].codepoint = buffer.input_buffer[k];
|
buffer.glyph_buffer[rendered_col + screen_line * buffer.glyph_buffer_width].codepoint = buffer.input_buffer[k];
|
||||||
|
|
||||||
rendered_col += 1;
|
rendered_col += 1;
|
||||||
|
@ -370,7 +635,7 @@ update_glyph_buffer :: proc(buffer: ^FileBuffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if rendered_line >= begin && rendered_col < buffer.glyph_buffer_width {
|
if rendered_line >= begin && rendered_col < buffer.glyph_buffer_width {
|
||||||
buffer.glyph_buffer[rendered_col + screen_line * buffer.glyph_buffer_width] = Glyph { codepoint = character, color = 0 };
|
buffer.glyph_buffer[rendered_col + screen_line * buffer.glyph_buffer_width] = Glyph { codepoint = character, color = .Foreground };
|
||||||
}
|
}
|
||||||
|
|
||||||
rendered_col += 1;
|
rendered_col += 1;
|
||||||
|
@ -379,17 +644,39 @@ update_glyph_buffer :: proc(buffer: ^FileBuffer) {
|
||||||
|
|
||||||
draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, font: raylib.Font) {
|
draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, font: raylib.Font) {
|
||||||
update_glyph_buffer(buffer);
|
update_glyph_buffer(buffer);
|
||||||
|
color_buffer(buffer);
|
||||||
|
|
||||||
begin := buffer.top_line;
|
begin := buffer.top_line;
|
||||||
cursor_x := x + line_number_padding + buffer.cursor.col * source_font_width;
|
cursor_x := x + line_number_padding + buffer.cursor.col * source_font_width;
|
||||||
cursor_y := y + buffer.cursor.line * source_font_height;
|
cursor_y := y + buffer.cursor.line * source_font_height;
|
||||||
|
|
||||||
cursor_y -= begin * source_font_height;
|
cursor_y -= begin * source_font_height;
|
||||||
|
|
||||||
|
// draw cursor
|
||||||
if state.mode == .Normal {
|
if state.mode == .Normal {
|
||||||
raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), source_font_width, source_font_height, raylib.BLUE);
|
raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), source_font_width, source_font_height, raylib.BLUE);
|
||||||
} else if state.mode == .Insert {
|
} else if state.mode == .Insert {
|
||||||
raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), source_font_width, source_font_height, raylib.GREEN);
|
raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), source_font_width, source_font_height, raylib.GREEN);
|
||||||
raylib.DrawRectangle(i32(cursor_x + len(buffer.input_buffer) * source_font_width), i32(cursor_y), source_font_width, source_font_height, raylib.BLUE);
|
|
||||||
|
num_line_break := 0;
|
||||||
|
line_length := 0;
|
||||||
|
for c in buffer.input_buffer {
|
||||||
|
if c == '\n' {
|
||||||
|
num_line_break += 1;
|
||||||
|
line_length = 0;
|
||||||
|
} else {
|
||||||
|
line_length += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if num_line_break > 0 {
|
||||||
|
cursor_x = x + line_number_padding + line_length * source_font_width;
|
||||||
|
cursor_y = cursor_y + num_line_break * source_font_height;
|
||||||
|
} else {
|
||||||
|
cursor_x += line_length * source_font_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
raylib.DrawRectangle(i32(cursor_x), i32(cursor_y), source_font_width, source_font_height, raylib.BLUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for j in 0..<buffer.glyph_buffer_height {
|
for j in 0..<buffer.glyph_buffer_height {
|
||||||
|
@ -404,11 +691,12 @@ draw_file_buffer :: proc(state: ^State, buffer: ^FileBuffer, x: int, y: int, fon
|
||||||
|
|
||||||
if glyph.codepoint == 0 { break; }
|
if glyph.codepoint == 0 { break; }
|
||||||
|
|
||||||
raylib.DrawTextCodepoint(font, rune(glyph.codepoint), raylib.Vector2 { f32(text_x), f32(text_y) }, source_font_height, raylib.LIGHTGRAY);
|
raylib.DrawTextCodepoint(font, rune(glyph.codepoint), raylib.Vector2 { f32(text_x), f32(text_y) }, source_font_height, raylib.GetColor(palette[glyph.color]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: don't mangle cursor
|
||||||
scroll_file_buffer :: proc(buffer: ^FileBuffer, dir: ScrollDir) {
|
scroll_file_buffer :: proc(buffer: ^FileBuffer, dir: ScrollDir) {
|
||||||
switch dir {
|
switch dir {
|
||||||
case .Up:
|
case .Up:
|
||||||
|
@ -424,6 +712,7 @@ scroll_file_buffer :: proc(buffer: ^FileBuffer, dir: ScrollDir) {
|
||||||
if buffer.cursor.line >= buffer.top_line + buffer.glyph_buffer_height - 4 {
|
if buffer.cursor.line >= buffer.top_line + buffer.glyph_buffer_height - 4 {
|
||||||
buffer.cursor.line = buffer.top_line + buffer.glyph_buffer_height - 1 - 4;
|
buffer.cursor.line = buffer.top_line + buffer.glyph_buffer_height - 1 - 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
case .Down:
|
case .Down:
|
||||||
{
|
{
|
||||||
|
@ -435,6 +724,8 @@ scroll_file_buffer :: proc(buffer: ^FileBuffer, dir: ScrollDir) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_file_buffer_index_from_cursor(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use buffer list in state
|
// TODO: use buffer list in state
|
||||||
|
@ -581,21 +872,44 @@ main :: proc() {
|
||||||
|
|
||||||
font := raylib.LoadFont("../c_editor/Mx437_ToshibaSat_8x16.ttf");
|
font := raylib.LoadFont("../c_editor/Mx437_ToshibaSat_8x16.ttf");
|
||||||
state: State;
|
state: State;
|
||||||
|
buffer, err := new_file_buffer(context.allocator, os.args[1]);
|
||||||
buffer, err := new_file_buffer(context.allocator, "./src/main.odin");
|
|
||||||
if err.type != .None {
|
if err.type != .None {
|
||||||
fmt.println("Failed to create file buffer:", err);
|
fmt.println("Failed to create file buffer:", err);
|
||||||
os.exit(1);
|
os.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for !raylib.WindowShouldClose() {
|
for !raylib.WindowShouldClose() {
|
||||||
|
screen_width := raylib.GetScreenWidth();
|
||||||
|
screen_height := raylib.GetScreenHeight();
|
||||||
|
buffer.glyph_buffer_height = math.min(256, int((screen_height - 32 - source_font_height) / source_font_height));
|
||||||
|
|
||||||
{
|
{
|
||||||
raylib.BeginDrawing();
|
raylib.BeginDrawing();
|
||||||
defer raylib.EndDrawing();
|
defer raylib.EndDrawing();
|
||||||
|
|
||||||
raylib.ClearBackground(raylib.GetColor(0x232136ff));
|
raylib.ClearBackground(get_palette_raylib_color(.Background));
|
||||||
draw_file_buffer(&state, &buffer, 0, 32, font);
|
draw_file_buffer(&state, &buffer, 32, 32, font);
|
||||||
raylib.DrawTextEx(font, raylib.TextFormat("Line: %d, Col: %d --- Slice Index: %d, Content Index: %d", buffer.cursor.line + 1, buffer.cursor.col + 1, buffer.cursor.index.slice_index, buffer.cursor.index.content_index), raylib.Vector2 { 0, 0 }, source_font_height, 0, raylib.DARKGRAY);
|
|
||||||
|
raylib.DrawRectangle(0, screen_height - source_font_height, screen_width, source_font_height, get_palette_raylib_color(.Background2));
|
||||||
|
|
||||||
|
line_info_text := raylib.TextFormat("Line: %d, Col: %d --- Slice Index: %d, Content Index: %d", buffer.cursor.line + 1, buffer.cursor.col + 1, buffer.cursor.index.slice_index, buffer.cursor.index.content_index);
|
||||||
|
line_info_width := raylib.MeasureTextEx(font, line_info_text, source_font_height, 0).x;
|
||||||
|
|
||||||
|
switch state.mode {
|
||||||
|
case .Normal:
|
||||||
|
raylib.DrawRectangle(0, screen_height - source_font_height, 8 + len("NORMAL")*source_font_width, source_font_height, get_palette_raylib_color(.Foreground4));
|
||||||
|
raylib.DrawRectangleV(raylib.Vector2 { f32(screen_width) - line_info_width - 8 , f32(screen_height - source_font_height) }, raylib.Vector2 { 8 + line_info_width, f32(source_font_height) }, get_palette_raylib_color(.Foreground4));
|
||||||
|
|
||||||
|
raylib.DrawTextEx(font, "NORMAL", raylib.Vector2 { 4, f32(screen_height - source_font_height) }, source_font_height, 0, get_palette_raylib_color(.Background1));
|
||||||
|
case .Insert:
|
||||||
|
raylib.DrawRectangle(0, screen_height - source_font_height, 8 + len("INSERT")*source_font_width, source_font_height, raylib.SKYBLUE);
|
||||||
|
raylib.DrawRectangleV(raylib.Vector2 { f32(screen_width) - line_info_width - 8 , f32(screen_height - source_font_height) }, raylib.Vector2 { 8 + line_info_width, f32(source_font_height) }, raylib.SKYBLUE);
|
||||||
|
|
||||||
|
raylib.DrawTextEx(font, "INSERT", raylib.Vector2 { 4, f32(screen_height - source_font_height) }, source_font_height, 0, raylib.DARKBLUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
raylib.DrawTextEx(font, line_info_text, raylib.Vector2 { f32(screen_width) - line_info_width - 4, f32(screen_height - source_font_height) }, source_font_height, 0, get_palette_raylib_color(.Background1));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch state.mode {
|
switch state.mode {
|
||||||
|
|
Loading…
Reference in New Issue