lazyshell.zsh 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #!/usr/bin/env zsh
  2. __lazyshell_complete() {
  3. if [ -z "$OPENAI_API_KEY" ]; then
  4. echo ""
  5. echo "Error: OPENAI_API_KEY is not set"
  6. echo "Get your API key from https://beta.openai.com/account/api-keys and then run:"
  7. echo "export OPENAI_API_KEY=<your API key>"
  8. zle reset-prompt
  9. return 1
  10. fi
  11. local buffer_context="$BUFFER"
  12. # Read user input
  13. # Todo: use zle to read input
  14. local REPLY
  15. autoload -Uz read-from-minibuffer
  16. read-from-minibuffer '> GPT query: '
  17. BUFFER="$buffer_context"
  18. CURSOR=$#BUFFER
  19. if [[ -z "$buffer_context" ]]; then
  20. local prompt="Write a bash command for query: \`$REPLY\`. Answer with the command only."
  21. else
  22. local prompt="Alter bash command \`$buffer_context\` to comply with query \`$REPLY\`. Answer with the command only."
  23. fi
  24. # todo: better escaping
  25. local escaped_prompt=$(echo "$prompt" | sed 's/"/\\"/g' | sed 's/\n/\\n/g')
  26. local data='{"prompt":"'"$escaped_prompt"'","model":"text-davinci-003","max_tokens":256,"temperature":0}'
  27. # Display a spinner while the API request is running in the background
  28. local spinner=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏")
  29. set +m
  30. local response_file=$(mktemp)
  31. { curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $OPENAI_API_KEY" --data "$data" https://api.openai.com/v1/completions > "$response_file" } &>/dev/null &
  32. local pid=$!
  33. while true; do
  34. for i in "${spinner[@]}"; do
  35. if ! kill -0 $pid 2> /dev/null; then
  36. break 2
  37. fi
  38. zle -R "$i GPT query: $REPLY"
  39. sleep 0.1
  40. done
  41. done
  42. wait $pid
  43. if [ $? -ne 0 ]; then
  44. # todo displayed error is erased immediately, find a better way to display it
  45. zle -R "Error: API request failed"
  46. return 1
  47. fi
  48. # Read the response from file
  49. # Todo: avoid using temp files
  50. local response=$(cat "$response_file")
  51. rm -f "$response_file"
  52. local generated_text=$(echo -E $response | jq -r '.choices[0].text' | xargs)
  53. local error=$(echo -E $response | jq -r '.error.message')
  54. if [ $? -ne 0 ]; then
  55. zle -R "Error: Invalid response from API"
  56. return 1
  57. fi
  58. if [[ -n "$error" && "$error" != "null" ]]; then
  59. zle -R "Error: $error"
  60. return 1
  61. fi
  62. # Replace the current buffer with the generated text
  63. BUFFER="$generated_text"
  64. CURSOR=$#BUFFER
  65. }
  66. if [ -z "$OPENAI_API_KEY" ]; then
  67. echo "Warning: OPENAI_API_KEY is not set"
  68. echo "Get your API key from https://beta.openai.com/account/api-keys and then run:"
  69. echo "export OPENAI_API_KEY=<your API key>"
  70. fi
  71. # Bind the __lazyshell_complete function to the Alt-g hotkey
  72. zle -N __lazyshell_complete
  73. bindkey '^g' __lazyshell_complete