From fdd9f3532345ee42fea96d47aa3def38658fe62e Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Fri, 22 Dec 2023 22:29:34 -0600 Subject: [PATCH] lets get this porting done --- .gitignore | 1 + Makefile | 4 ++ flake.lock | 111 ++++++++++++++++++++++++++++++ flake.nix | 74 ++++++++++++++++++++ src/main.odin | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 373 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 flake.lock create mode 100755 flake.nix create mode 100644 src/main.odin diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ac4bff3 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +all: editor + +editor: src/*.odin + odin build src/ -out:bin/editor -lld diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..66084da --- /dev/null +++ b/flake.lock @@ -0,0 +1,111 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixgl": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1685908677, + "narHash": "sha256-E4zUPEUFyVWjVm45zICaHRpfGepfkE9Z2OECV9HXfA4=", + "owner": "guibou", + "repo": "nixGL", + "rev": "489d6b095ab9d289fe11af0219a9ff00fe87c7c5", + "type": "github" + }, + "original": { + "owner": "guibou", + "repo": "nixGL", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1660551188, + "narHash": "sha256-a1LARMMYQ8DPx1BgoI/UN4bXe12hhZkCNqdxNi6uS0g=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "441dc5d512153039f19ef198e662e4f3dbb9fd65", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1703013332, + "narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixgl": "nixgl", + "nixpkgs": "nixpkgs_2" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100755 index 0000000..aed63b1 --- /dev/null +++ b/flake.nix @@ -0,0 +1,74 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + nixgl.url = "github:guibou/nixGL"; + }; + + outputs = { self, nixpkgs, flake-utils, nixgl, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + overlays = [ nixgl.overlay ]; + pkgs = import nixpkgs { + inherit system overlays; + }; + fixed-odin = pkgs.odin.overrideAttrs (finalAttrs: prevAttr: rec { + src = /Users/temp/Documents/personal/Odin; + LLVM_CONFIG = "${pkgs.llvmPackages_17.llvm.dev}/bin/llvm-config"; + nativeBuildInputs = with pkgs; prevAttr.nativeBuildInputs ++ [ libcxx libcxxabi ]; + postPatch = prevAttr.postPatch + '' + sed -i build_odin.sh \ + -e 's|CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"|CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags) -I ${pkgs.libiconv.outPath}/include/"|' \ + -e 's|LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"|LDFLAGS="$LDFLAGS -pthread -lm -lstdc++ -L ${pkgs.libiconv.outPath}/lib/ -L ${pkgs.llvmPackages_17.libcxxabi.outPath}/lib/"|' + ''; + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + cp odin $out/bin/odin + + mkdir -p $out/share + cp -r core $out/share/core + cp -r vendor $out/share/vendor + + wrapProgram $out/bin/odin \ + --set PATH ${pkgs.lib.makeBinPath (with pkgs; [ + coreutils + llvmPackages_17.bintools + llvmPackages_17.lld + llvmPackages_17.clang + ])} \ + --set-default ODIN_ROOT $out/share + + runHook postInstall + ''; + }); + in + { + devShell = pkgs.mkShell { + buildInputs = with pkgs; (if pkgs.system == "aarch64-darwin" || pkgs.system == "x86_64-darwin" then [ + fixed-odin + darwin.apple_sdk.frameworks.CoreData + darwin.apple_sdk.frameworks.Kernel + darwin.apple_sdk.frameworks.CoreVideo + darwin.apple_sdk.frameworks.GLUT + darwin.apple_sdk.frameworks.IOKit + darwin.apple_sdk.frameworks.OpenGL + darwin.apple_sdk.frameworks.Cocoa + ] else if pkgs.system == "x86_64-linux" then [ + pkg-config + binutils + odin + libGL + xorg.libX11 + xorg.libXi + xorg.xinput + xorg.libXcursor + xorg.libXrandr + xorg.libXinerama + pkgs.nixgl.nixGLIntel + ] else throw "unsupported system" ); + }; + } + ); +} diff --git a/src/main.odin b/src/main.odin new file mode 100644 index 0000000..c21327b --- /dev/null +++ b/src/main.odin @@ -0,0 +1,183 @@ +package main + +import "core:fmt" +import "core:mem" +import "vendor:raylib" + +source_font_width :: 8; +source_font_height :: 16; +line_number_padding :: 4 * source_font_width; + +ContentType :: enum { + Original, + Added, +} + +ContentSlice :: struct { + type: ContentType, + slice: []u8, +} + +FileBufferIndex :: struct { + slice_index: int, + content_index: int, +} + +Cursor :: struct { + col: int, + line: int, + buffer_index: FileBufferIndex, +} + +Glyph :: struct #packed { + codepoint: u8, + color: u16, +} + +FileBuffer :: struct { + allocator: mem.Allocator, + + file_path: string, + top_line: int, + cursor: Cursor, + + original_content: [dynamic]u8, + added_content: [dynamic]u8, + content_slices: [dynamic]ContentSlice, + + glyph_buffer_width: int, + glyph_buffer_height: int, + glyph_buffer: [dynamic]Glyph, + + input_buffer: [dynamic]u8, +} + +FileBufferIter :: struct { + index: FileBufferIndex, + buffer: ^FileBuffer, +} + +new_file_buffer_iter :: proc(file_buffer: ^FileBuffer) -> FileBufferIter { + return FileBufferIter { buffer = file_buffer }; +} +iterate_file_buffer :: proc(it: ^FileBufferIter) -> (character: u8, idx: FileBufferIndex, cond: bool) { + if it.index.slice_index >= len(it.buffer.content_slices) || it.index.content_index >= len(it.buffer.content_slices[it.index.slice_index].slice) { + return; + } + cond = true; + + character = it.buffer.content_slices[it.index.slice_index].slice[it.index.content_index]; + + it.index.content_index += 1; + if it.index.content_index >= len(it.buffer.content_slices[it.index.slice_index].slice) { + it.index.content_index = 0; + it.index.slice_index += 1; + } + + return; +} + +new_file_buffer :: proc(allocator: mem.Allocator, file_path: string) -> FileBuffer { + context.allocator = allocator; + + width := 80; + height := 24; + + test_str := "This is a test string\nfor a file buffer\nThis is line 3\nThis is line 4\n\n\nThis is line 7 (with some gaps between 4)"; + + buffer := FileBuffer { + allocator = allocator, + file_path = file_path, + + original_content = make([dynamic]u8, 0, len(test_str)), + added_content = make([dynamic]u8, 0, 1024*1024), + content_slices = make([dynamic]ContentSlice, 0, 1024*1024), + + glyph_buffer_width = width, + glyph_buffer_height = height, + glyph_buffer = make([dynamic]Glyph, width*height, width*height), + + input_buffer = make([dynamic]u8, 0, 1024), + }; + + append(&buffer.original_content, test_str); + append(&buffer.content_slices, ContentSlice { type = .Original, slice = buffer.original_content[:] }); + + return buffer; +} + +update_glyph_buffer :: proc(buffer: ^FileBuffer) { + //mem.set(&buffer.glyph_buffer, 0, size_of(Glyph)*buffer.glyph_buffer_width*buffer.glyph_buffer_height); + + begin := buffer.top_line; + rendered_col: int; + rendered_line: int; + + it := new_file_buffer_iter(buffer); + for character in iterate_file_buffer(&it) { + if character == '\r' { continue; } + + line := rendered_line - begin; + if rendered_line >= begin && line >= buffer.glyph_buffer_height { break; } + + if character == '\n' { + rendered_col = 0; + rendered_line += 1; + continue; + } + + if rendered_line >= begin && rendered_col < buffer.glyph_buffer_width { + buffer.glyph_buffer[rendered_col + line * buffer.glyph_buffer_width] = Glyph { codepoint = character, color = 0 }; + } + + rendered_col += 1; + } +} + +draw_file_buffer :: proc(buffer: ^FileBuffer, x: int, y: int, font: raylib.Font) { + update_glyph_buffer(buffer); + + begin := buffer.top_line; + cursor_x := x + line_number_padding + buffer.cursor.col * source_font_width; + cursor_y := y + buffer.cursor.line * source_font_height; + + for j in 0..