From 1087e9898f56b98eb7aac1c7f5ee9d04b94aae0a Mon Sep 17 00:00:00 2001 From: mattwparas Date: Wed, 31 May 2023 06:23:07 -0700 Subject: [PATCH] first commit --- .gitignore | 2 + config.toml | 16 +++ helix.scm | 266 +++++++++++++++++++++++++++++++++++++++++++++++++ init.scm | 121 ++++++++++++++++++++++ languages.toml | 4 + prelude.scm | 34 +++++++ steel-mode.scm | 5 + 7 files changed, 448 insertions(+) create mode 100644 .gitignore create mode 100644 config.toml create mode 100644 helix.scm create mode 100644 init.scm create mode 100644 languages.toml create mode 100644 prelude.scm create mode 100644 steel-mode.scm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa63546 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +runtime/ +extensions/ diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..07ea471 --- /dev/null +++ b/config.toml @@ -0,0 +1,16 @@ +theme = "ayu_mirage" + +[editor.statusline] +center = ["custom"] + +# create a new minor mode bound to `+` +[keys.normal."+"] +m = ":run-shell-command echo 2" +c = ":run-shell-command cargo build" +t = ":run-shell-command cargo test" +n = ":run-shell-command echo 3" + +[editor.cursor-shape] +insert = "bar" +normal = "block" +select = "underline" \ No newline at end of file diff --git a/helix.scm b/helix.scm new file mode 100644 index 0000000..1f33492 --- /dev/null +++ b/helix.scm @@ -0,0 +1,266 @@ +; (require-builtin helix/core/typable as helix.) +; (require-builtin helix/core/static as helix.static.) +; (require-builtin helix/core/keybindings as helix.keybindings.) + +(require "prelude.scm" + (for-syntax "prelude.scm")) + +(require-helix) +; (require "steel/result" as result/) +; (require "steel/option") + +;; (require-builtin external-command-module as ext.) + +(provide set-theme-dracula + set-theme-custom + theme-then-vsplit + custom-undo + lam + delete-word-forward + insert-string-at-selection + highlight-to-matching-paren + delete-sexpr + run-expr + run-highlight + make-minor-mode! + git-status + reload-helix-scm + open-helix-scm + open-init-scm + new-function + dummy + ;; wrapped-go-change-theme + ;test-component + ) + +;; Run without quoting? +; (define (steel cx . exprs) +; (helix.static.run-in-engine! ) + +;; Hmmmmm should just use my class system instead? that might help with the dispatching +;(define (Component::render-func obj) +; (if (SteelDynamicComponent? obj) +; (SteelDynamicComponent-render obj) +; Component::render)) + +;(define (Component::handle-event-func obj) +; (if (SteelDynamicComponent? obj) +; (SteelDynamicComponent-handle-event obj) +; Component::handle-event)) + +;(define (Component::should-update-func obj) +; (if (SteelDynamicComponent? obj) +; (SteelDynamicComponent-should-update obj) +; Component::should-update)) + +;(define (Component::cursor-func obj) +; (if (SteelDynamicComponent? obj) +; (SteelDynamicComponent-cursor obj) +; Component::cursor)) + +;(define (Component::required-size-func obj) +; (if (SteelDynamicComponent? obj) +; (SteelDynamicComponent-required-size obj) +; Component::required-size)) + +;(define (make-dynamic! component) +; (new-component! "steel-dynamic-component" +; component +; (Component::render-func component) +; (hash +; "handle_event" (Component::handle-event-func component) +; "should_update" (Component::should-update-func component) +; "cursor" (Component::cursor-func component) +; "required_size" (Component::required-size-func component)))) + +; (define (wrapped-popup)) + +; (define (test-component cx) +; (push-component! cx (new-component! "steel-dynamic-component" +; (list) +; (lambda (area frame context) void) +; (hash)))) + +;; I think options might still come through as void? +(define (unwrap-or obj alt) + (if (void? obj) alt obj)) + +;; TODO: Figure out a more ergonomic way of expression some of the position manipulation. +;; As it is, we have to do quite a bit to grab the right stuff +;(define (test-component cx) +; (let ((component (make-dynamic! (Component::Text "hello world!")))) +; (push-component! +; cx +; (Popup::new component +; (~> cx +; (cx->cursor) +; (car) +; (unwrap-or (Position::default))))))) + +;;@doc +;; change the theme, but from a dylib! +; (define (wrapped-go-change-theme cx entered-theme) +; (ext.go-change-theme cx (list entered-theme) helix.PromptEvent::Validate)) + +;;@doc +;; Call this dummy function! +(define (dummy cx) + void) + +;;@doc +;; Sets the theme to be the dracula theme +(define (set-theme-dracula cx) + (helix.theme cx (list "dracula") helix.PromptEvent::Validate)) + +;;@doc +;; Sets the theme to be the theme passed in +(define (set-theme-custom cx entered-theme) + (helix.theme cx (list entered-theme) helix.PromptEvent::Validate)) + +;;@doc +;; Switch theme to the entered theme, then split the current file into +;; a vsplit +(define (theme-then-vsplit cx entered-theme) + (set-theme-custom cx entered-theme) + (helix.vsplit cx '() helix.PromptEvent::Validate)) + +;;@doc +;; Perform an undo +(define (custom-undo cx) + (helix.static.undo cx)) + +;;@doc +;; Insert a lambda +(define (lam cx) + (helix.static.insert_char cx #\λ) + (helix.static.insert_mode cx)) + +;;@doc +;; Insert the string at the selection and go back into insert mode +(define (insert-string-at-selection cx str) + (helix.static.insert_string cx str) + (helix.static.insert_mode cx)) + +;;@doc +;; Delete the word forward +(define (delete-word-forward cx) + (helix.static.delete_word_forward cx)) + +;;@doc +;; Registers a minor mode with the registered modifer and key map +;; +;; Examples: +;; ```scheme +;; (make-minor-mode! "+" +;; (hash "P" ":lam")) +;; ``` +(define (make-minor-mode! modifier bindings) + (~> (hash "normal" (hash modifier bindings)) + (value->jsexpr-string) + (helix.keybindings.set-keybindings!))) + +(define-syntax minor-mode! + (syntax-rules (=>) + [(minor-mode! modifier (key => function)) + (make-minor-mode! modifier (minor-mode-cruncher (key => function)))] + + [(minor-mode! modifier (key => (function ...))) + (make-minor-mode! modifier (minor-mode-cruncher (key => (function ...))))] + + [(minor-mode! modifier (key => function) remaining ...) + (make-minor-mode! modifier (minor-mode-cruncher (key => function) remaining ...))] + + [(minor-mode! modifier (key => (function ...)) remaining ...) + (make-minor-mode! modifier (minor-mode-cruncher (key => function) ... remaining ...))])) + +(define-syntax minor-mode-cruncher + (syntax-rules (=>) + [(minor-mode-cruncher (key => (function ...))) + (hash key (map (lambda (x) (string-append ":" (symbol->string x))) (quote (function ...))))] + + [(minor-mode-cruncher (key => function)) + (hash key (string-append ":" (symbol->string (quote function))))] + + [(minor-mode-cruncher (key => (function ...)) remaining ...) + (hash-insert (minor-mode-cruncher remaining ...) + key + (map (lambda (x) (string-append ":" (symbol->string x))) (quote (function ...))))] + + [(minor-mode-cruncher (key => function) remaining ...) + (hash-insert (minor-mode-cruncher remaining ...) + key + (string-append ":" (symbol->string (quote function))))])) + +;;@doc +;; Highlight to the matching paren +(define (highlight-to-matching-paren cx) + (helix.static.select_mode cx) + (helix.static.match_brackets cx)) + +(define (run-expr cx) + (define current-selection (helix.static.current_selection cx)) + (when (or (equal? "(" current-selection) (equal? ")" current-selection)) + (highlight-to-matching-paren cx) + (helix.static.run-in-engine! cx (helix.static.current-highlighted-text! cx)) + (helix.static.normal_mode cx))) + +(define (run-highlight cx) + (helix.static.run-in-engine! cx (helix.static.current-highlighted-text! cx))) + +;;@doc +;; Delete the s-expression matching this bracket +;; If the current selection is not on a bracket, this is a no-op +(define (delete-sexpr cx) + (define current-selection (helix.static.current_selection cx)) + (when (or (equal? "(" current-selection) (equal? ")" current-selection)) + (highlight-to-matching-paren cx) + (helix.static.delete_selection cx))) + +; (minor-mode! "+" ("l" => lam) +; ("q" => (set-theme-dracula lam))) + +(minor-mode! "P" + ("l" => lam) + ("p" => highlight-to-matching-paren) + ("d" => delete-sexpr) + ("r" => run-expr) + ;; ("t" => test-component) + ) + +(make-minor-mode! "+" (hash "l" ":lam")) + +(define (git-status cx) + (helix.run-shell-command cx '("git" "status") helix.PromptEvent::Validate)) + +(minor-mode! "G" ("s" => git-status)) + +;;@doc +;; Reload the helix.scm file +(define (reload-helix-scm cx) + (helix.static.run-in-engine! cx + (string-append "(require \"" (helix.static.get-helix-scm-path) "\")"))) + +;;@doc +;; Open the helix.scm file +(define (open-helix-scm cx) + (helix.open cx (list (helix.static.get-helix-scm-path)) helix.PromptEvent::Validate)) + +;;@doc +;; Opens the init.scm file +(define (open-init-scm cx) + (helix.open cx (list (helix.static.get-init-scm-path)) helix.PromptEvent::Validate)) + +;;@doc run git status +(define (new-function cx) + (git-status cx)) + +;;@doc +;; Collect memory usage of engine runtime? +(define (print-engine-stats) + (error "TODO")) + +;; TODO: Capture the output of standard out and pipe it to the +;; window here +;; (help open-helix-scm) + +;; (error "uh oh!") diff --git a/init.scm b/init.scm new file mode 100644 index 0000000..f31abc1 --- /dev/null +++ b/init.scm @@ -0,0 +1,121 @@ +(require-builtin steel/random as rand::) +(require-builtin helix/core/static as helix.static.) +(require-builtin helix/core/typable as helix.) + +(require-builtin steel/web/blocking/requests as requests.) +(require "steel/result") +(require-builtin steel/time) + +(require-builtin steel/process as process/) +(require "steel/lists/lists.scm") + +;; (require-builtin external-command-module as ext.) +;; (ext.go-change-theme *helix.cx* (list "default") helix.PromptEvent::Validate) + +; (require "steel/result") + +;; (require-builtin dylib/toml as toml::) +;; (displayln (toml::add-100 #\c)) + +(define (get-weather) + (~> (requests.get "http://wttr.in/?format=3") + (requests.call) + (unwrap-ok) + (requests.response->text) + (unwrap-ok))) + +(define (format-weather weather-line) + (~>> weather-line (trim-end))) + +;; Main loop for getting the weather +(define (main) + (while #t + (begin + (set-status-line! (format-weather (get-weather))) + (time/sleep-ms (* 60 1000))))) + +(define rng (rand::thread-rng!)) + +;; Spawn a thread for the weather! +(spawn-thread! main) + +(set-theme-dracula *helix.cx*) + +;; Picking one from the possible themes is _fine_ +(define possible-themes '("ayu_mirage" "tokyonight_storm")) + +(define (select-random lst) + (let ([index (rand::rng->gen-range rng 0 (length lst))]) (list-ref lst index))) + +(define (randomly-pick-theme options) + ;; Randomly select the theme from the possible themes list + (helix.theme *helix.cx* (list (select-random options)) helix.PromptEvent::Validate)) + +(randomly-pick-theme possible-themes) + +;;@doc +;; Ensure the LSP registered is installed on the machine, and if not, install it +(define (ensure-installed program install-thunk) + (when (void? (process/which program)) + (install-thunk))) + +;;@doc +;; Install marksman using the snap tool chain prior to launching +(define (install-marksman) + (displayln "Installing marksman...") + (if (equal? (current-os!) "linux") + (helix.static.block-on-shell-command *helix.cx* + (list "sudo snap install marksman") + helix.PromptEvent::Validate) + (error "Unknown installation mechanism for marksman on non unix platforms!"))) + +;;@doc +;; Install taplo using cargo +(define (install-taplo) + (displayln "Installing taplo...") + (helix.static.block-on-shell-command *helix.cx* + (list "cargo install taplo-cli --locked") + helix.PromptEvent::Validate)) + +;;@doc +;; Install marksman via a subprocess installation - standardize this with some sort of +;; program installation builder struct. +(define (install-marksman-subprocess) + (~> (process/command "sudo" '("snap" "install" "marksman")) (process/spawn-process))) + +;;@doc +;; Install taplo +(define (install-taplo-subprocess) + (~> (process/command "cargo" '("install" "taplo-cli" "--locked")))) + +;;@doc +;; Install raco fmt +; (define (install-raco-fmt) +; (displayln "Installing raco fmt...") +; (helix.static.block-on-shell-command) + +; ) + +(define (ensure-all-installed program-thunk-pairs) + (for-each (λ (pairs) (ensure-installed (list-ref pairs 0) (list-ref pairs 1))) program-thunk-pairs)) + +(define (do-nothing) + void) + +;; Ensure that all of the following are installed: +(ensure-all-installed + (list (list "marksman" install-marksman) (list "taplo" install-taplo) (list "black" do-nothing))) + +; ;; Install marksman +; (ensure-installed *helix.cx* "marksman" install-marksman) + +; ;; Install taplo (toml) +; (ensure-installed *helix.cx* "taplo" install-taplo) + +; ;; Ensure that the following programs are installed +; (ensure-installed *helix.cx* "black" (λ () void)) + +;;;;;;;;;;;;;;;;;;;;;;;;;; Options ;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Allow hidden files to show up +(helix.set-option *helix.cx* '("file-picker.hidden" "false")) diff --git a/languages.toml b/languages.toml new file mode 100644 index 0000000..3dc060c --- /dev/null +++ b/languages.toml @@ -0,0 +1,4 @@ +[[language]] +name = "scheme" +formatter = { command = "raco", args = ["fmt", "-i"] } +auto-format = true diff --git a/prelude.scm b/prelude.scm new file mode 100644 index 0000000..eae7488 --- /dev/null +++ b/prelude.scm @@ -0,0 +1,34 @@ +;; (require-builtin helix/core/typable as helix.) +;; (require-builtin helix/core/static as helix.static.) +(require-builtin helix/core/keybindings as helix.keybindings.) + +(provide + (for-syntax require-helix) + make-minor-mode! + + ) + +;; Provide the macro to help with setting up new files +(define-syntax require-helix + (syntax-rules () + [(require-helix) + (begin + (require-builtin helix/core/typable as helix.) + (require-builtin helix/core/static as helix.static.) + (require-builtin helix/core/keybindings as helix.keybindings.))])) + + +;;@doc +;; Registers a minor mode with the registered modifer and key map +;; +;; Examples: +;; ```scheme +;; (make-minor-mode! "normal" "+" +;; (hash "P" ":lam")) +;; ``` +(define (make-minor-mode! mode modifier bindings) + (~> (hash "normal" (hash mode + (hash modifier bindings))) + (value->jsexpr-string) + (helix.keybindings.set-keybindings!))) + diff --git a/steel-mode.scm b/steel-mode.scm new file mode 100644 index 0000000..c61135a --- /dev/null +++ b/steel-mode.scm @@ -0,0 +1,5 @@ +(require-builtin helix/core/typable as helix.) +(require-builtin helix/core/static as helix.static.) +(require-builtin helix/core/keybindings as helix.keybindings) + +(define ()) \ No newline at end of file