Cursor_Copilot++の使用方法（Next.js中心）

# はじめに
私は普段からCursorを使用しており、
チャットによる開発支援では助けられた経験が何度もあります。
ただ、最近はチャットだけではなくCopilot++のコード補完機能にも助けられているので、
どのように活用しているかをまとめました。

# 目次
- [CursorのCopilot++の設定方法](#cursorのcopilotの設定方法)
- [実際の使用例](#実際の使用方法)
    - [1.事前に宣言した内容の参照](#1事前に宣言した内容の参照)
    - [2.引数の推定](#2引数の推定)
    - [3.styleの補完](#3styleの補完)
    - [4.ダミーデータの補完複製](#4ダミーデータの補完複製)
    - [5.react特有の内容の補完](#5react固有のコードの補完)
- [最後に](#最後に)

# CursorのCopilot++の設定方法

#### 右上の歯車マークからCursor Settingsを呼び出す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/9782bd48-2565-21ed-c2d8-deda72733d26.png)

#### Cursor Settings　の Cursor Tabをenabledにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/a1359cc6-0fd4-f44c-b2d6-613710bc785d.png)

以上でCursorのCopilot++が使用可能になります。
ただ、その下にも設定項目もあります。
現時点で私の方ではこれらの設定の違いについて厳密には把握しきれていませんが、
デメリットは特に感じていないため基本的にenabledにしておくことをお勧めします。

#### Model
使用するAIモデルを選択します。fastは応答速度を優先するが精度が落ちるモデルとのことです。
おすすめ：auto(default)

#### Partial Accepts
入力された内容から次の内容を予測して補完する機能。

#### Cursor Prediction
補完を受け入れた後にTabキーを押すと、次の行に移動してさらに補完する機能。
 
#### Chunked Streaming
大きなデータやコードを小さなチャンクに分割してストリーミングする設定です。
これにより、データの処理が効率的になり、応答時間が短縮されるとのことです。

#### Cached Typeahead
過去の入力パターンや頻繁に使用されるコードをキャッシュし、
より早く正確な補完を行う機能。

## 実際の使用方法

## 1.事前に宣言した内容の参照

メソッドを作成した際、それを利用する箇所に関して補完してくれます。
例えば下記のようにログを表示するようなメソッドを入力したとします。

```
const Home = () => {
  const handleClickHello = () => {
    console.log("hello")
  }

  return (
    <div>
      <h1>Home</h1>
      <p>welcome to my home page</p>
    </div>
  )
}

export default Home
```

すると、メソッドを利用しそうな箇所にカーソルがあった際、
メソッドを利用したコードを補完してくれます。
場合によってはメソッドを定義した段階で補完してくれることもあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/474cc613-e4f8-b084-ed19-a8e1eb8c4091.png)


## 2.引数の推定

Copilot++ではメソッドの引数の補完も行ってくれます。
まずは先ほど作ったhandleClickHelloメソッドをhandleClickMessageに変更します。
このとき、引数に「me」と打った段階で後の内容を補完してくれたのでTabを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/90884c8f-402a-2fa0-bdcf-a5c40e8fe2a7.png)

同時にconsole.log("hello")をconsole.log("message")に正す修正も補完してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/280e920b-bc96-fda5-b1e0-0ca943e7fa7e.png)

次にその補完を受けいれた後はbuttonのonClickの引数に関しても補完してくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/2eba0537-96c7-08f5-9697-b3c0502d68bd.png)

この3回の修正に関して、カーソルを移動せずとも
Tabを連続で押して受けいれるだけで修正ができてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/0ee054bc-2a29-4a05-37d2-ccc92111dbc9.png)

## 3.styleの補完

styled-componentsを用いてボタンのスタイリングを行います。
まずは下記のようにStyledButtonと入力を続けると、よく入力するbuttonの内容が補完されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/95c9a65c-d389-ac9c-1e94-a3aa7e27b2c3.png)

そしてTabを押すと補完が適用され、
すでにあるbuttonの近くにカーソルを持ってくると、
作成したばかりのStyledButtonを使用するように補完してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/e3999637-e632-4a5d-e800-7fe6fbdee4ed.png)

今度は通常のcssで設定してみます。
あらかじめ下記のように別ファイルでcssの設定を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/f8f4c5dc-535d-e692-a03f-5e9e4d044db8.png)

home.tsxにタブを戻し、
該当の箇所に合わせるとclassNameを使用したボタンが補完されます。
こちらは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/9e9dc726-989e-c811-13e5-e93b97cb739e.png)


## 4.ダミーデータの補完・複製

まずは、下記のようにダミーデータの型定義をしたとします。

```javascript
type Dummy = {
  id: numberf
  title: string
  content: string
}

type DummyList = Dummy[]
```

ここでダミーデータを実際に作る際は補完で例を作ってくれます。
正確には「co」と入力した時点でその前に入力していたdummyListを使用して考えてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/7a2ef725-dd21-4663-5f9b-0f132cd0ab55.png)

補完してくれた内容をTabで受け入れると、今度は実際にダミーデータを補完してくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/7d8e87ec-4eb6-cb3c-7c23-51bc984801ce.png)


もう一度Tabで受け入れると補完が反映され、さらなる追加ダミーデータも補完してくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/e1a13305-50ec-56aa-386d-b8d5e771a4df.png)


typeにdateを追加すると時刻も補完してくれ、
それに続く内容は日付を1日ずつ足して補完してくれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/68990354-4dda-e4aa-54e6-86604f95473c.png)

さらに一番最後の行から改行すると新たなデータを補完してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/c5f251d1-ffb5-c6aa-19f9-e202e2243f71.png)

もっと多くダミーデータを増やしたい場合はすでにある３行をそのままコピーし、
例えばidだけ4に変更すると規則性に基づいて4,5,6の続きのデータを補完してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/03142818-859b-3ba5-8584-db16431ea4f7.png)

listのstyled-componentsも作成することで、
楽にリストを作成することができました。

```javascript
import styled from "styled-components"

type Dummy = {
  id: string
  title: string
  content: string
  date: string
}

type DummyList = Dummy[]

const DUMMY_LIST: DummyList = [
  { id: "1", title: "タイトル1", content: "内容1", date: "2021-01-01" },
  { id: "2", title: "タイトル2", content: "内容2", date: "2021-01-02" },
  { id: "3", title: "タイトル3", content: "内容3", date: "2021-01-03" },
  { id: "4", title: "タイトル4", content: "内容4", date: "2021-01-04" },
  { id: "5", title: "タイトル5", content: "内容5", date: "2021-01-05" },
  { id: "6", title: "タイトル6", content: "内容6", date: "2021-01-06" },
]

const Home = () => {
  const handleClickMessage = (message: string) => {
    console.log(message)
  }

  return (
    <div>
      <h1>Home</h1>
      <p>welcome to my home page</p>
      <StyledButton onClick={() => handleClickMessage("hello")}>Hello</StyledButton>
      {DUMMY_LIST.map((dummy) => (
        <StyledList key={dummy.id}>
          <p>{dummy.title}</p>
          <p>{dummy.content}</p>
          <p>{dummy.date}</p>
        </StyledList>
      ))}
    </div>
  )
}

export default Home

const StyledButton = styled.button`
  background-color: blue;
  color: white;
  padding: 10px;
  border-radius: 5px;
  font-size: 16px;
  width: 100px;
`

const StyledList = styled.div`
  display: flex;
  flex-direction: row;
  font-size: 12px;
  gap: 10px;
  width: 240px;
  align-items: center;
  border: 1px solid #000;
  padding: 4px;
  margin: 10px;
`

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/fc253b08-a3b3-0e08-6649-d6e1ab027689.png)


## 5.React固有のコードの補完

Modalのstyled-componentsを追加します。

```javascript
import styled from "styled-components"

const Home = () => {
  const handleClickMessage = (message: string) => {
    console.log(message)
  }

  return (
    <div>
      <h1>Home</h1>
      <p>welcome to my home page</p>
      <StyledButton onClick={() => handleClickMessage("hello")}>Hello</StyledButton>
      <Modal>
        <ModalContent>
          <p>モーダル</p>
        </ModalContent>
      </Modal>
    </div>
  )
}

export default Home

const StyledButton = styled.button`
  background-color: blue;
  color: white;
  padding: 10px;
  border-radius: 5px;
  font-size: 16px;
  width: 100px;
`

const Modal = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  justify-content: center;
  align-items: center;
  z-index: 1000;
  display: flex;
`

const ModalContent = styled.div`
  background-color: #fff;
  width: 500px;
  height: 300px;
  padding: 20px;
  border-radius: 10px;
  text-align: center;
`

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/bb4168f7-876c-3405-e847-21ab9ebff13b.png)

Modalのコンポーネントにopenの引数を与えてあげると、
useStateを用いて設定をしてくれます。
（この画像では「open={open}」を指定するまで出ませんでしたが、
「open={」の段階で補完が出たこともありました）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/f20f7282-3230-d72c-86e3-2ef4b7c6506d.png)

先ほどはModalのstyled-componentsにopenの引数はありませんでしたが、
カーソルを合わせるとその補完をしてくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/8deeefb2-dbfa-ee86-f167-2a1f1c9766a6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/f5345a10-3c50-002e-9d14-c16454b5ceff.png)

handleClickMessageをOpenに変えようと「handleClickO」の時点で補完を出してくれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/36eacb72-131b-71ca-2984-060bdf97a089.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/f6bfa14f-647c-cba8-4358-30bc2be4bbd5.png)

続いて、openがあればcloseも必要であると推測し、
handleClickCloseのメソッドも保管してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/9fa97673-2d8e-ce01-81d4-3f5814afbac4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/7c7e37ee-6e27-43e7-bea9-8c31bddf546c.png)

そして、handleClickOpenのボタンの文言を削除し、
カーソルを合わせると文言の補完をしてくれたのでTabで受け入れて完成です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/b8004d42-1d91-4242-9352-78c2d150e1f4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425282/227be2ad-4f8c-b90d-9254-494004af865c.png)


# 最後に

今回は簡単なコードで試してみましたが、普段開発をする中でも、
入力から次はこのコードを入力するだろうと予測して補完をしてくれるため大変役に立っています。

またメソッドやファイル単位の記述量を極力減らし、
わかりやすい名前をつけることで補完の精度が上がるので、
人間とAIの両方に分かりやすいコードを書く習慣にも繋がると感じました。

Cursorを使用される際は是非Copilot++の設定を有効にすることをお勧めします。