Escher-js / SkimmedMilk

0 stars 0 forks source link

create new branch #13

Closed psmuler closed 1 year ago

psmuler commented 1 year ago

プルダウンメニューに"Create new branch"という項目を表示するようにし、新しいブランチを作る処理を加えましょう

psmuler commented 1 year ago

プルダウンメニューに"Create new branch"という項目を表示し、新しいブランチを作る処理を追加するには、以下の手順でindex.htmlrenderer.jsファイルを更新してください。

  1. index.htmlファイルを更新:

"Create new branch"という項目を追加します。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>My Electron App</title>
  </head>
  <body>
    <h1>Hello, Electron!</h1>
    <button id="file-btn">Open</button>
    <button id="save-btn">Save</button>
    <button id="git-init-btn">Git Init</button>
    <span id="git-status" style="margin-left: 10px;"></span>
    <span id="folder-path" style="margin-left: 10px;"></span>
    <br />
    <select id="branch-select" style="margin-top: 10px;">
      <option>Create new branch</option>
    </select>
    <br />
    <textarea id="text-editor" rows="20" cols="80"></textarea>

    <script src="renderer.js"></script>
  </body>
</html>
  1. renderer.jsファイルを更新:

プルダウンメニューの選択が変更されたときに、"Create new branch"が選択されている場合、新しいブランチ名を入力するプロンプトを表示し、新しいブランチを作成する処理を追加します。

const { ipcRenderer } = require('electron');
const fs = require('fs');
const { exec } = require('child_process');

const fileBtn = document.getElementById('file-btn');
const saveBtn = document.getElementById('save-btn');
const gitInitBtn = document.getElementById('git-init-btn');
const textEditor = document.getElementById('text-editor');
const folderPathSpan = document.getElementById('folder-path');
const gitStatusSpan = document.getElementById('git-status');
const branchSelect = document.getElementById('branch-select');

// ... (fileBtn, saveBtn, gitInitBtn, ipcRendererのイベントリスナーは省略) ...
// ... (updateBranchList関数は省略) ...

branchSelect.addEventListener('change', () => {
  if (branchSelect.value === 'Create new branch') {
    const newBranchName = prompt('Enter the new branch name:');
    if (newBranchName && newBranchName.trim() !== '') {
      const folderPath = folderPathSpan.textContent;
      exec(`git -C "${folderPath}" checkout -b "${newBranchName.trim()}"`, (error, stdout, stderr) => {
        if (error) {
          console.error(`Error: ${error.message}`);
          return;
        }
        if (stderr) {
          console.error(`Stderr: ${stderr}`);
          return;
        }
        console.log(`Stdout: ${stdout}`);
        // ブランチ一覧を更新
        updateBranchList(folderPath);
      });
    }
    // プルダウンメニューの選択をリセット
    branchSelect.value = '';
  }
});

// ... (ipcRendererのイベントリスナーは省略) ...

これで、プルダウ

psmuler commented 1 year ago

フォルダ選択後も"Create new branch"の項目が表示されるようにしましょう

psmuler commented 1 year ago

フォルダ選択後にも"Create new branch"の項目が表示されるようにするには、updateBranchList関数の中で"Create new branch"の項目を常に追加するように変更します。renderer.jsファイルを以下のように更新してください。

// ... (他のコードは省略) ...

function updateBranchList(folderPath) {
  exec(`git -C "${folderPath}" branch`, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error: ${error.message}`);
      return;
    }
    if (stderr) {
      console.error(`Stderr: ${stderr}`);
      return;
    }

    const branches = stdout.split('\n').filter(branch => branch.trim() !== '').map(branch => branch.trim());
    branchSelect.innerHTML = '';

    // "Create new branch"の項目を追加
    const createNewBranchOption = document.createElement('option');
    createNewBranchOption.text = 'Create new branch';
    branchSelect.add(createNewBranchOption);

    branches.forEach(branch => {
      const option = document.createElement('option');
      option.text = branch;
      branchSelect.add(option);
    });
  });
}

// ... (他のコードは省略) ...

これで、フォルダ選択後にも"Create new branch"の項目が表示されます。

psmuler commented 1 year ago

先ほど作りかけた、新しいブランチを作る処理を加えたプルダウンメニューですが、create new branch を選択しても何も表示されません。let inputDialog = new BrowserWindowなどを用いてカスタムでinputboxとOK,Cancelボタンを備えたダイアローグボックスを表示しましょう

psmuler commented 1 year ago

electronBrowserWindowを使ってカスタムのinputboxとOK, Cancelボタンを備えたダイアログボックスを表示するために、以下の手順でmain.jsrenderer.jsファイルを更新し、新しいHTMLファイルbranch_input.htmlを作成します。

  1. branch_input.htmlファイルを作成し、入力ボックスとOK, Cancelボタンを含めます。
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Branch Input</title>
    <style>
      body {
        text-align: center;
        padding: 20px;
      }
      input {
        width: 300px;
      }
    </style>
  </head>
  <body>
    <h1>New Branch</h1>
    <input id="branch-name" type="text" placeholder="Enter branch name" />
    <br />
    <button id="ok-btn">OK</button>
    <button id="cancel-btn">Cancel</button>
    <script src="renderer.js"></script>
  </body>
</html>
  1. main.jsファイルで、createBranchInputDialog関数を作成し、カスタムダイアログのBrowserWindowを作成します。また、ipcMainをインポートし、ダイアログからのイベントを処理できるようにします。
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

// ... (他のコードは省略) ...

function createBranchInputDialog() {
  const inputDialog = new BrowserWindow({
    width: 400,
    height: 200,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
  });

  inputDialog.loadFile(path.join(__dirname, 'branch_input.html'));
}

ipcMain.handle('show-branch-input-dialog', () => {
  createBranchInputDialog();
});

// ... (他のコードは省略) ...
  1. renderer.jsファイルで、プルダウンメニューの選択が変更されたときに、カスタムダイアログを表示するように更新します。また、新しいブランチ名を取得してブランチを作成する処理を追加します。

const { ipcRenderer } = require('electron');
const fs = require('fs');
const { exec } = require('child_process');

// ... (他のコードは省略) ...

branchSelect.addEventListener('change', () => {
  if (branchSelect.value === 'Create new branch') {
    ipcRenderer.invoke('show-branch-input-dialog');
    // プルダウンメニューの選択をリセット
    branchSelect.value = '';
  }
});

ipcRenderer.on('create-new-branch', (event, newBranchName) => {
  const folderPath = folderPathSpan.textContent;
  exec(`git -C "${folderPath}" checkout -b "${newBranchName.trim()}"`, (error, stdout, stderr) => {
    // ... (他のコードは省略) ...
  });
});

// ... (他のコードは省略) ...
psmuler commented 1 year ago

ipcRenderer.on('create-new-branch')の中身を詳細に書いてもらえますか

psmuler commented 1 year ago

ipcRenderer.on('create-new-branch')のイベントリスナー内で、新しいブランチを作成するためにgit checkout -bコマンドを実行します。作成されたブランチに切り替えることも含まれます。また、ブランチが作成された後、ブランチ一覧を更新するためにupdateBranchList()関数を呼び出します。

renderer.jsファイルのipcRenderer.on('create-new-branch')イベントリスナーを以下のように更新します。

// ... (他のコードは省略) ...

ipcRenderer.on('create-new-branch', (event, newBranchName) => {
  const folderPath = folderPathSpan.textContent;

  // 新しいブランチを作成し、作成されたブランチに切り替える
  exec(`git -C "${folderPath}" checkout -b "${newBranchName.trim()}"`, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error: ${error.message}`);
      return;
    }
    if (stderr) {
      console.error(`Stderr: ${stderr}`);
      return;
    }
    console.log(`Stdout: ${stdout}`);

    // ブランチ一覧を更新
    updateBranchList(folderPath);
  });
});

// ... (他のコードは省略) ...

この変更により、create-new-branchイベントがトリガーされたときに、新しいブランチを作成し、作成されたブランチに切り替えます。また、ブランチ作成後にブランチ一覧を更新します。

psmuler commented 1 year ago

ポップアップしたダイアログでOKボタンを押した時のイベントリスナを設定してください

psmuler commented 1 year ago

ポップアップしたダイアログでOKボタンを押したときのイベントリスナを設定するには、renderer.jsファイルに以下のコードを追加します。このコードは、branch_input.htmlファイルで読み込まれるため、同じrenderer.jsファイル内に追加することができます。

// ... (他のコードは省略) ...

if (document.getElementById('branch-input')) {
  const okBtn = document.getElementById('ok-btn');
  const cancelBtn = document.getElementById('cancel-btn');
  const branchNameInput = document.getElementById('branch-name');

  okBtn.addEventListener('click', () => {
    const newBranchName = branchNameInput.value;
    if (newBranchName.trim() === '') {
      alert('Branch name cannot be empty');
      return;
    }
    ipcRenderer.send('create-new-branch', newBranchName);
    window.close();
  });

  cancelBtn.addEventListener('click', () => {
    window.close();
  });
}

// ... (他のコードは省略) ...

このコードは、OKボタンがクリックされたときに、入力されたブランチ名を検証し、新しいブランチ名としてメインプロセスに送信します。また、キャンセルボタンがクリックされたときにダイアログを閉じます。

注意: 上記のコードは、renderer.jsファイルの他の部分と同じファイルに配置されていますが、if (document.getElementById('branch-input'))条件により、branch_input.htmlページでのみ実行されます。これは、他のページではbranch-input要素が存在しないためです。

psmuler commented 1 year ago

他のダイアログボックスなどで変数の汚染があるといけませんから、新しいjsファイルに書き込んだほうがいいのではないでしょうか

psmuler commented 1 year ago

おっしゃる通りです。新しいJavaScriptファイルを作成して、ダイアログボックス専用のコードをそこに移動することで、変数の汚染を防ぐことができます。以下の手順に従って、新しいファイルbranch_input_renderer.jsを作成しましょう。

  1. branch_input_renderer.jsという新しいファイルを作成します。

  2. renderer.jsファイルから、ダイアログボックスのイベントリスナに関連するコードをbranch_input_renderer.jsファイルに移動します。

branch_input_renderer.js:

const { ipcRenderer } = require('electron');

const okBtn = document.getElementById('ok-btn');
const cancelBtn = document.getElementById('cancel-btn');
const branchNameInput = document.getElementById('branch-name');

okBtn.addEventListener('click', () => {
  const newBranchName = branchNameInput.value;
  if (newBranchName.trim() === '') {
    alert('Branch name cannot be empty');
    return;
  }
  ipcRenderer.send('create-new-branch', newBranchName);
  window.close();
});

cancelBtn.addEventListener('click', () => {
  window.close();
});
  1. branch_input.htmlファイルで、新しく作成したbranch_input_renderer.jsファイルを読み込むように変更します。

branch_input.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Branch Input</title>
    <style>
      body {
        text-align: center;
        padding: 20px;
      }
      input {
        width: 300px;
      }
    </style>
  </head>
  <body>
    <h1>New Branch</h1>
    <input id="branch-name" type="text" placeholder="Enter branch name" />
    <br />
    <button id="ok-btn">OK</button>
    <button id="cancel-btn">Cancel</button>
    <script src="branch_input_renderer.js"></script>
  </body>
</html>

これで、新しいブランチの作成に関する処理がbranch_input_renderer.jsに移動され、他のコードとの変数の汚染を防ぐことができます。

psmuler commented 1 year ago

branch_input_renderer がipcRenderer.sendを実行していますが、renderer.jsと通信できるのでしょうか

psmuler commented 1 year ago

はい、branch_input_renderer.jsからrenderer.jsと通信できます。Electronアプリケーションでは、ipcRendereripcMainを使って異なるプロセス間でメッセージをやり取りすることができます。branch_input_renderer.jsからrenderer.jsへの通信は、ipcRendererからipcMainへの通信となり、ipcMainrenderer.jsにメッセージを転送します。

この場合、branch_input_renderer.jsipcRenderer.send('create-new-branch', newBranchName);を使ってcreate-new-branchイベントを送信します。このイベントは、main.jsファイルのipcMainによって受信され、main.jsrenderer.jsにイベントを転送します。

main.jsファイルで、以下のようにbranch_inputウィンドウとmainWindow間でイベントをリレーすることができます。

// ... (他のコードは省略) ...

ipcMain.on('create-new-branch', (event, newBranchName) => {
  mainWindow.webContents.send('create-new-branch', newBranchName);
});

// ... (他のコードは省略) ...

renderer.jsファイルでは、ipcRenderer.on('create-new-branch')イベントリスナーを追加して、main.jsからのイベントを受信し、適切な処理を実行します。

// ... (他のコードは省略) ...

ipcRenderer.on('create-new-branch', (event, newBranchName) => {
  const folderPath = folderPathSpan.textContent;

  // 新しいブランチを作成し、作成されたブランチに切り替える
  exec(`git -C "${folderPath}" checkout -b "${newBranchName.trim()}"`, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error: ${error.message}`);
      return;
    }
    if (stderr) {
      console.error(`Stderr: ${stderr}`);
      return;
    }
    console.log(`Stdout: ${stdout}`);

    // ブランチ一覧を更新
    updateBranchList(folderPath);
  });
});

// ... (他のコードは省略) ...

この方法で、branch_input_renderer.jsからrenderer.jsへの通信が可能になります。

psmuler commented 1 year ago

branchの作成はできましたが、renderer.js>ipcRenderer.on('create-new-branch')>exec(git -C...)内の Switched to a new branchがstderrとして認識され、updateBranchListが実行されずにreturnされてしまいます

psmuler commented 1 year ago

git checkout -b コマンドは、新しいブランチへ切り替えた際にメッセージを stderr に出力することがありますが、これはエラーではありません。そのため、stderr にメッセージが出力された場合でも、それがエラーであるかどうかをチェックする必要があります。

renderer.js 内の ipcRenderer.on('create-new-branch') イベントリスナーの処理を次のように修正して、stderr にメッセージがあってもエラーでなければ updateBranchList を実行するようにしましょう。

// ... (他のコードは省略) ...

ipcRenderer.on('create-new-branch', (event, newBranchName) => {
  const folderPath = folderPathSpan.textContent;

  // 新しいブランチを作成し、作成されたブランチに切り替える
  exec(`git -C "${folderPath}" checkout -b "${newBranchName.trim()}"`, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error: ${error.message}`);
      return;
    }

    // エラーでない場合、stderr の内容を出力
    if (stderr) {
      console.log(`Info: ${stderr}`);
    }

    console.log(`Stdout: ${stdout}`);

    // ブランチ一覧を更新
    updateBranchList(folderPath);
  });
});

// ... (他のコードは省略) ...

この変更により、新しいブランチが作成された場合、updateBranchList が正常に実行されるようになります。ただし、stderr にエラーが出力された場合は、それがエラーであるかどうかを判断するために適切な処理を追加することが重要です。今回の場合、新しいブランチへの切り替えメッセージが stderr に出力されるだけなので、エラーとして扱わないように修正しました。

psmuler commented 1 year ago

新しいブランチへの切り替え時にエラーが発生し、切り替えメッセージ以外のエラーがstderrに出力されることはないのでしょうか?

psmuler commented 1 year ago

新しいブランチへの切り替え時に、git checkout -bコマンドによってstderrに出力されるエラーは存在します。以下は、いくつかの一般的なエラーシナリオです。

  1. 同名のブランチがすでに存在する場合
  2. ブランチ名に無効な文字が含まれている場合

これらのエラーが発生した場合、stderrにエラーメッセージが出力されます。そのため、stderrにメッセージがある場合には、実際にエラーが発生しているかどうかを判断するための処理が必要です。

以下のように、エラーが発生していないかどうかを確認するために、errorオブジェクトの存在をチェックし、stderrの内容を詳細に確認することができます。

// ... (他のコードは省略) ...

ipcRenderer.on('create-new-branch', (event, newBranchName) => {
  const folderPath = folderPathSpan.textContent;

  // 新しいブランチを作成し、作成されたブランチに切り替える
  exec(`git -C "${folderPath}" checkout -b "${newBranchName.trim()}"`, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error: ${error.message}`);
      alert(`Error: ${stderr}`);
      return;
    }

    // エラーでない場合、stderr の内容を出力
    if (stderr) {
      console.log(`Info: ${stderr}`);
    }

    console.log(`Stdout: ${stdout}`);

    // ブランチ一覧を更新
    updateBranchList(folderPath);
  });
});

// ... (他のコードは省略) ...

この変更により、実際にエラーが発生した場合、stderrの内容がアラートとして表示され、ユーザーに通知されます。ただし、この方法では、stderrの内容がエラーであるかどうかを自動的に判断することはできません。そのため、適切なエラーハンドリングを実装するためには、stderrの内容をパースし、特定のエラーメッセージを検出するなどの追加処理が必要になる場合があります。