Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inlay hints #14

Open
wants to merge 2 commits into
base: steel-event-system
Choose a base branch
from

Conversation

merisbahti
Copy link

Suggestion for an interface for displaying "inline ghost text" from the scripting engine.

Tested with the following plugin (make sure you've an env variable called OPENAI_API_KEY.)

(require (prefix-in helix. "helix/commands.scm"))
(require (prefix-in helix.static. "helix/static.scm"))
(require "helix/misc.scm")
(require "component.scm")
(require "helix/editor.scm")
(require-builtin helix/components)
(require-builtin helix/core/text as text.)
(require "cogs/helix-ext.scm")

(define (run-cmd cmd . args)
  (let
    ([builder (command cmd args)])
    (set-piped-stdout! builder)
    (~> builder spawn-process Ok->value wait->stdout Ok->value)))
(define api-key (trim (run-cmd "printenv" "OPENAI_API_KEY")))
(define (get-document-as-slice)
  (let* ([focus (editor-focus)]
         [focus-doc-id (editor->doc-id focus)])
    (text.rope->string (editor->text focus-doc-id))))
(define openapi-server "https://api.openai.com/v1/chat/completions")
(define (make-request code-with-cursor callback)
  (spawn-native-thread
    (fn ()
      (define output
        (run-cmd
          "curl"
          openapi-server
          "-d"
          (value->jsexpr-string
            (hash
              'model
              "gpt-4o-mini"
              'messages
              (list
                (hash
                  'role
                  "user"
                  'content
                  (string-join
                    (list "Only answer in code without wrapping into markdown, what would you put at the position of <CURSOR>, don't include text before or after <CURSOR>:
"
                      code-with-cursor))))
              'prediction
              (hash 'type "content" 'content code-with-cursor)
              'temperature
              0.1))
          "-H"
          "Content-Type: application/json"
          "-H"
          (string-join (list "Authorization: Bearer " api-key))))
      (define parsed-output
        (~>
          (string->jsexpr output)
          (hash-ref 'choices)
          (list-ref 0)
          (hash-ref 'message)
          (hash-ref 'content)))
      (hx.with-context
        (fn ()
          (callback parsed-output))))))

(define *latest-inlay-hint* (None))
(provide ask-prompt)

;; accepts the current ai generated hint
(provide accept-current-hint)
(define (accept-current-hint)
  (when (not (None? *latest-inlay-hint*))
    (helix.static.insert_string (cadr *latest-inlay-hint*))
    (clear-inlay-hint)))

(define (clear-inlay-hint)
  (when (not (None? *latest-inlay-hint*))
    (apply remove-inlay-hint (cons *helix.cx* *latest-inlay-hint*))
    (set! *latest-inlay-hint* (None))))

(define *latest-debounce-id* 0) ;; each character should'nt send a request
(define (ask-prompt)
  (define current-debounce-id (+ 1 *latest-debounce-id*))
  (set! *latest-debounce-id* current-debounce-id)
  (define doc (get-document-as-slice))
  (define cursor-pos (hx.cx->pos))
  (define code-with-cursor
    (string-join
      (list
        (substring doc 0 cursor-pos)
        "<CURSOR>"
        (substring doc cursor-pos))))
  (enqueue-thread-local-callback-with-delay 300
    (fn ()
      (when
        (not (equal? current-debounce-id *latest-debounce-id*))
        (return! void))
      (make-request code-with-cursor
        (fn (x)
          (when (not (equal? current-debounce-id *latest-debounce-id*)) (return! void))
          (hx.with-context
            (fn ()
              (clear-inlay-hint)
              (set! *latest-inlay-hint* (list cursor-pos x))
              (add-inlay-hint *helix.cx* cursor-pos x))))))))
(register-hook! "post-command"
  (fn (_)
    (displayln *latest-inlay-hint*)
    (clear-inlay-hint)))
(register-hook! "post-insert-char"
  (fn (_)
    (displayln *latest-inlay-hint* _)
    (clear-inlay-hint)
    (ask-prompt)))
(register-hook! "on-mode-switch"
  (fn (_)
    (set! *latest-debounce-id* (+ 1 *latest-debounce-id*))
    (clear-inlay-hint)))

@merisbahti merisbahti changed the title wip inlay hints inlay hints Dec 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant