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

Feature Request: support sub-commands in CopilotChat.nvim #5

Closed
jellydn opened this issue Dec 21, 2023 · 14 comments
Closed

Feature Request: support sub-commands in CopilotChat.nvim #5

jellydn opened this issue Dec 21, 2023 · 14 comments
Labels
duplicate This issue or pull request already exists enhancement New feature or request v2

Comments

@jellydn
Copy link
Contributor

jellydn commented Dec 21, 2023

Context

GitHub Copilot for VS Code offers a range of useful sub-commands like /new, /fix, /explain, and /tests that enhance the coding experience. These commands allow users to generate new code, fix issues, get explanations, and write tests efficiently.

VSCode

Proposal

Integrate these sub-commands into CopilotChat.nvim to bring similar functionalities to Neovim. Below are the specific commands and their intended functionalities:

  • /new: Generate new code blocks or files.
  • /fix: Automatically suggest fixes for highlighted code issues.
  • /explain: Provide detailed explanations for specific code segments.
  • /tests: Generate test cases for existing code.

Technical Considerations

  • We could add a command like GCFIX, GCTests, etc for each sub command.
  • We might need to migrate to pure lua plugin if needed.

Request for Feedback

I am not sure about the feasibility of this without Github Copilot team input. Let me know if you have any thoughts on plan on this. @gptlang Thanks for great work for bring this plugin to Neovim community. 👏

@gptlang
Copy link
Member

gptlang commented Dec 21, 2023

I was not aware of these features (Not a user of VScode). Thank you.

I will look into this.

@thomazmoura
Copy link

I'm really interested in this, since my main reason for still using Copilot on VS Code is the /workspace sub-command. It lets you make questions to CoPilot on the context of the whole local codebase. It's amazing for exploring and understand projects you had no prior contact with. That's what actually made me renew my copilot license.

I wonder if this kind of feature is even accessible outside VS Code, though, or if it uses VS Code internals to guess which files it have to look at.

@gptlang

This comment was marked as outdated.

@gptlang
Copy link
Member

gptlang commented Dec 29, 2023

I'll have to abandon porting everything to lua since this might be a bit too complicated for me to do in a new language

@gptlang
Copy link
Member

gptlang commented Dec 30, 2023

I've got some of the sub-commands down but my VSCode is missing @workspace among others from the video

Edit: I haven't updated VScode in a loooong time

@jellydn
Copy link
Contributor Author

jellydn commented Dec 31, 2023

Hi @gptlang Just FYI - I have just watched this video about how @workspace works. https://youtu.be/a2DDYMEPwbE?si=rQeeCA-21O5jD8IK

@gptlang
Copy link
Member

gptlang commented Jan 4, 2024

I'm still working on this. Running into a bit of trouble. During the embedding request, it sends each function/class with ... for omitted code. I don't know how they parse/identify the functions.

e.g.

File: `rplugin/python3/copilot.py`
```py
class Copilot:
    ...
    def request_auth(self):
        url = "https://github.com/login/device/code"

        response = self.session.post(
            url,
            headers=LOGIN_HEADERS,
            data=json.dumps({
                "client_id": "Iv1.b507a08c87ecfe98",
                "scope": "read:user"
            })
        ).json()
        return response
    ...
File: `rplugin/python3/copilot.py`
```py
class Copilot:
    def __init__(self, token: str = None):
        if token is None:
            token = utilities.get_cached_token()
        self.github_token = token
        self.token: dict[str, any] = None
        self.chat_history: list[typings.Message] = []
        self.vscode_sessionid: str = None
        self.machineid = utilities.random_hex()

        self.session = requests.Session()
    ...

@gptlang
Copy link
Member

gptlang commented Jan 4, 2024

Maybe tree sitter? Not sure how to ensure that the parser for any specific language is installed.

@gptlang
Copy link
Member

gptlang commented Jan 4, 2024

Looks like I was right. They bundle the parsers into the extension.
image

I don't think I have the energy to properly implement tree-sitter. If anyone has a shortcut, let me know.

I don't use AI much so I'm gonna put this in my backlog and work on other stuff first.

@cjoke
Copy link

cjoke commented Jan 6, 2024

This is awesome work gptlang! I now use copilot and copilotchat with vsplit. works like a charm! made my day! :)

@neutrinoA4
Copy link
Contributor

Thank you for the wonderful plugin.
I'm sure there is a better way, but I looked into how to parse python code.
Omit everything other than the function and class definition part under the cursor.
I hope this helps even a little.

local pythonParseSample = function()
    local ts_utils = require 'nvim-treesitter.ts_utils'
    local current_node = ts_utils.get_node_at_cursor()
    local expr = current_node
    local lines = {}
    local target_function = nil
    local target_class = nil

    -- get function and class definition node
    while expr do
      if target_function == nil and string.find(expr:type(), 'function_definition') then
        target_function = expr
      end

      if string.find(expr:type(), 'class_definition') then
        target_class = expr
        break
      end

      expr = expr:parent()
    end

    if target_class == nil and target_function ~= nil then
      -- return function define body
      lines = ts_utils.get_node_text(target_function)
      return table.concat(lines, "\n")
    end

    if target_class ~= nil then
      local class_lines = ts_utils.get_node_text(target_class)

      if target_function == nil then
        -- return class define body
        return table.concat(class_lines, "\n")
      end

      local class_definition_line = class_lines[1]
      table.insert(lines, class_definition_line)

      local class_start_row = target_class:start()
      local class_end_row = target_class:end_()
      local function_start_row = target_function:start()
      local function_end_row = target_function:end_()

      if function_start_row ~= class_start_row + 1 then
        -- insert ... between class definition and function definition
        table.insert(lines, "...")
      end

      for _, node in ipairs(ts_utils.get_node_text(target_function)) do
        table.insert(lines, node)
      end

      if function_end_row ~= class_end_row then
        -- insert ... between function definition and class definition
        table.insert(lines, "...")
      end

      return table.concat(lines, "\n")
    end
  end

@gptlang
Copy link
Member

gptlang commented Jan 10, 2024

@neutrinoA4 thanks for the suggestion! Is this language agnostic (via tree-sitter) or specific to Python?

@neutrinoA4
Copy link
Contributor

@gptlang
This code is Python specific.
Mainly "function_definition" and "class_definition" in the following parts differ depending on the language.

   -- get function and class definition node
    while expr do
      if target_function == nil and string.find(expr:type(), 'function_definition') then
        target_function = expr
      end

      if string.find(expr:type(), 'class_definition') then
        target_class = expr
        break
      end

For example, struct in rust language is "struct_item",
functions are specified as "function_item"

ChenRocks pushed a commit to ChenRocks/CopilotChat.nvim that referenced this issue Jan 24, 2024
* chore: sync fork

* feat: add option to change view mode

* chore: sync the change from CopilotC-Nvim#9

* docs: add new usage to canary branch

fix: typo on usage

* chore: sync fork

chore: sync the fork

chore: sync fork

chore: sync fork

* feat: add spinner

* feat: show spinner on processing

* chore: sync fork
@jellydn jellydn added the enhancement New feature or request label Feb 6, 2024
@deathbeam deathbeam added the v1 label Mar 6, 2024
@jellydn jellydn added v2 and removed v1 labels Mar 19, 2024
@deathbeam
Copy link
Collaborator

I think #360 is better description for remainder of this, as we already have subcommands, we just dont have full context awareness, so closing as duplicate

@deathbeam deathbeam added the duplicate This issue or pull request already exists label Sep 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists enhancement New feature or request v2
Projects
None yet
Development

No branches or pull requests

6 participants