Skip to content

parrot.nvim 🦜 - the plugin that brings stochastic parrots to Neovim.

License

Notifications You must be signed in to change notification settings

frankroeder/parrot.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

parrot.nvim 🦜

This is parrot.nvim, the ultimate stochastic parrot to support your text editing inside Neovim.

Features β€’ Demo β€’ Getting Started β€’ Commands β€’ Configuration

parrot.nvim logo

[!NOTE]⚠️ This repository is still a work in progress, as large parts of the code are still being simplified and restructured. It is based on the brilliant work gp.nvim by https://github.com/Robitx.

I started this repository because a perplexity subscription provides $5 of API credits every month for free. Instead of letting them go to waste, I modified my favorite GPT plugin, gp.nvim, to meet my needs - a new Neovim plugin was born! πŸ”₯

Unlike gp.nvim, parrot.nvim prioritizes a seamless out-of-the-box experience by simplifying functionality and focusing solely on text generation, excluding the integration of DALLE and Whisper.

Features

  • Persistent conversations as markdown files stored within the Neovim standard path or a user-defined location
  • Custom hooks for inline text editing with predefined prompts
  • Support for multiple providers:
  • Custom agent definitions to determine specific prompt and API parameter combinations, similar to GPTs
  • Flexible support for providing API credentials from various sources, such as environment variables, bash commands, and your favorite password manager CLI
  • Provide repository-specific instructions with a .parrot.md file using the command PrtContext
  • No autocompletion and no hidden requests in the background to analyze your files

Demo

Seamlessly switch between providers and agents.


Trigger code completions based on comments.


Let the parrot fix your bugs.

Getting Started

Dependencies

lazy.nvim

{
  "frankroeder/parrot.nvim",
  tag = "v0.3.1",
  dependencies = { 'ibhagwan/fzf-lua', 'nvim-lua/plenary.nvim' },
  config = function()
    require("parrot").setup {
      providers = {
        pplx = {
          api_key = os.getenv "PERPLEXITY_API_KEY",
          -- OPTIONAL
          -- gpg command
          -- api_key = { "gpg", "--decrypt", vim.fn.expand("$HOME") .. "/pplx_api_key.txt.gpg"  },
          -- macOS security tool
          -- api_key = { "/usr/bin/security", "find-generic-password", "-s pplx-api-key", "-w" },
        },
        openai = {
          api_key = os.getenv "OPENAI_API_KEY",
        },
        anthropic = {
          api_key = os.getenv "ANTHROPIC_API_KEY",
        },
        mistral = {
          api_key = os.getenv "MISTRAL_API_KEY",
        },
      },
    }
  end,
}

Commands

Below are the available commands that can be configured as keybindings. These commands are included in the default setup. Additional useful commands are implemented through hooks (see my example configuration).

General

Command Description
PrtNew open a new chat
PrtProvider <provider> switch the provider (empty arg triggers fzf)
PrtAgent <agent> switch the agent (empty arg triggers fzf)
PrtChatToggle <target> toggle chat window
PrtInfo print plugin config
PrtContext edits the local context file
PrtAsk ask the selected agent a single question
PrtChatFinder fuzzy search chat files using fzf
PrtChatPaste <target> paste visual selection into the latest chat

Interactive

The following commands can be triggered with visual selections.

Command Description
PrtChatNew <target> paste visual selection into new chat (defaults to toggle_target)
PrtChatToggle <target> paste visual selection into new chat (defaults to toggle_target)
PrtImplement implements selected comment/instruction

Chat

The following commands are available within the chat files.

Command Description
PrtChatDelete delete the present chat file (requires confirmation)
PrtChatRespond trigger chat respond
PrtAsk ask the selected agent a single question
PrtStop interrupt ongoing respond

Configuration

For now, refer to my personal lazy.nvim setup for custom hooks and key bindings.

https://github.com/frankroeder/dotfiles/blob/master/nvim/lua/plugins/parrot.lua

Adding a new agents

We provide two types of agents that might need different system prompts and API parameters. To make a new chat agent available, one simply adds a new entry to the list chat or to command, respectively.

require("parrot").setup {
    -- ...
    agents = {
        chat = {
          {
              name = "CodeLlama",
              model = { model = "codellama", temperature = 1.5, top_p = 1, num_ctx = 8192, min_p = 0.05 },
              system_prompt = "Help me!",
              provider = "ollama",
          }
        }
    },
    -- ...
}

Adding a new command

require("parrot").setup {
    -- ...
    hooks = {
      -- PrtAsk simply ask a question that should be answered short and precisely.
      Ask = function(parrot, params)
            local template = [[
            In light of your existing knowledge base, please generate a response that
            is succinct and directly addresses the question posed. Prioritize accuracy
            and relevance in your answer, drawing upon the most recent information
            available to you. Aim to deliver your response in a concise manner,
            focusing on the essence of the inquiry.
            Question: {{command}}
            ]]
            local agent = parrot.get_command_agent()
            parrot.logger.info("Asking agent: " .. agent.name)
            parrot.Prompt(params, parrot.ui.Target.popup, "πŸ€– Ask ~ ", agent.model, template, "", agent.provider)
      end,
    }
    -- ...
}

Utilizing Template Placeholders

Users can utilize the following placeholders in their templates to inject specific content into the user messages:

Placeholder Content
{{selection}} Current visual selection
{{filetype}} Filetype of the current buffer
{{filepath}} Full path of the current file
{{filecontent}} Full content of the current buffer

Below is an example of how to use these placeholders in a completion hook, which receives the full file context and the selected code snippet as input.

require("parrot").setup {
    -- ...
    hooks = {
    	CompleteFullContext = function(prt, params)
    	  local template = [[
          I have the following code from {{filename}}:

          ```{{filetype}}
          {{filecontent}}
          ```

          Please look at the following section specifically:
          ```{{filetype}}
          {{selection}}
          ```

          Please finish the code above carefully and logically.
          Respond just with the snippet of code that should be inserted.
          ]]
    	  local agent = prt.get_command_agent()
    	  prt.Prompt(params, prt.ui.Target.append, nil, agent.model, template, agent.system_prompt, agent.provider)
    	end,
    }
    -- ...
}

Known Issues

  • In case of a corrupted state, simply remove the file ~/.local/share/nvim/parrot/persisted/state.json

more to come ...