bigcode-project/jupytercoder

Refactor content.js

liyongsea opened this issue · 2 comments

Today content.js is 600 lines long. It becomes not modular

Here is a suggestion of refactor by chatgpt

You:

Reproduce the js file structure by ignoring the content of the function

ChatGPT:

Certainly! Here's the reproduced file structure by ignoring the content of the functions:

sync function getOpenAIKey() {}

async function getOtherServiceUrl() {}

async function getChecked() {}

async function getmodelType() {}

async function getHuggingfaceApiKey() {}

async function sendToOpenAI(prompt) {}

async function sendToOtherService(code) {}

async function getCodeCompletion(code) {}

let codeToFill = "";

let isRequestInProgress = false;

let isRequestSuccessful = false;

let activeRequestTextarea = null;

function insertSuggestion(suggestion) {}

const getActiveCellPointerCode = (activeCell) => {}

function getCellContentTextRequiredForOpenAI(activeCell) {}

function getCellContentTextRequiredForBigCode(activeCell) {}

async function getCellContentText(activeCell) {}

function extractTextFromCodeCell(cell) {}

function extractTextFromTextCell(cell) {}

function removeJupyterOutput(str) {}

const loadCss = ``;

const startWaitingAnimation = (activeCell) => {}

const addFillCodeKeyListener = (event) => {}

const mainProcess = async () => {}

const montedEventListener = () => {}

let currctJupyterModel = {};

const notebookModel = {};

const labModel = {};

if (document.querySelector('body.notebook_app')) {}

const bodyObserver = new MutationObserver(function(mutations) {});

bodyObserver.observe(document.body, { attributes: true });

Please note that the content of the functions has been omitted. Only the function names and the overall file structure have been reproduced.

You:

propose a structure of code to make this more modular. This file is called content.js from a chrome extension

ChatGPT:

To make the code more modular, you can organize it into separate modules based on their functionality. Here's a proposed modular structure for the content.js file in your Chrome extension:

// api.js module
const api = {
  getOpenAIKey() {},
  getOtherServiceUrl() {},
  getChecked() {},
  getmodelType() {},
  getHuggingfaceApiKey() {},
  sendToOpenAI(prompt) {},
  sendToOtherService(code) {},
  getCodeCompletion(code) {},
};

// utility.js module
const utility = {
  insertSuggestion(suggestion) {},
  getActiveCellPointerCode(activeCell) {},
  getCellContentTextRequiredForOpenAI(activeCell) {},
  getCellContentTextRequiredForBigCode(activeCell) {},
  getCellContentText(activeCell) {},
  extractTextFromCodeCell(cell) {},
  extractTextFromTextCell(cell) {},
  removeJupyterOutput(str) {},
};

// animation.js module
const animation = {
  loadCss: ``,
  startWaitingAnimation(activeCell) {},
  addFillCodeKeyListener(event) {},
  mainProcess() {},
  montedEventListener() {},
};

// jupyterModel.js module
const jupyterModel = {
  currctJupyterModel: {},
  notebookModel: {},
  labModel: {},
};

// content.js - entry point
(function () {
  // Import modules
  const { api, utility, animation, jupyterModel } = window;

  // Code for content.js goes here

  // Use the imported modules in your code
  // Example: api.getOpenAIKey();
  //          utility.insertSuggestion();
  //          animation.mainProcess();
  //          jupyterModel.currctJupyterModel = jupyterModel.notebookModel;
})();

In this structure, the code is divided into modules (api.js, utility.js, animation.js, and jupyterModel.js). Each module handles specific functionality related to the API, utility functions, animations, and Jupyter Notebook models respectively. The entry point content.js imports these modules and utilizes their functions as needed.

Note that the code in the entry point should be placed within an IIFE (Immediately Invoked Function Expression) to create a local scope and prevent polluting the global scope. Also, ensure that you include the necessary dependencies or import statements for the modules in the appropriate places.

By organizing the code into modular components, it becomes easier to manage and maintain, promoting code reusability and separation of concerns.

You:

Let say (api.js, utility.js, animation.js, and jupyterModel.js) is already written. Write the complete content.js to reproduce the same hehavior as before

ChatGPT:

Certainly! If the api.js, utility.js, animation.js, and jupyterModel.js modules are already written, you can use them in the content.js file to reproduce the same behavior. Here's the complete content.js file:

// content.js - entry point
(function () {
  // Import modules
  const { api, utility, animation, jupyterModel } = window;

  // Code for content.js goes here

  // Code to be filled in after request completion
  let codeToFill = "";
  let isRequestInProgress = false;
  let isRequestSuccessful = false;
  let activeRequestTextarea = null;

  function addFillCodeKeyListener(event) {
    if (event.ctrlKey && isRequestSuccessful) {
      event.preventDefault();

      const animationElementList = document.querySelectorAll(".per-insert-code");

      if (animationElementList.length === 1) {
        animationElementList[0].remove();
        utility.insertSuggestion(codeToFill);
      }

      isRequestSuccessful = false;
    }
  }

  async function mainProcess() {
    const activeTextarea = document.activeElement;
    activeRequestTextarea = activeTextarea;

    const activeCell = activeTextarea.parentElement.parentElement;

    const code = await utility.getCellContentText(activeCell);

    if (!code) return;

    if (activeCell) {
      const [animationInterval, animationElement, inputElement] = animation.startWaitingAnimation(activeCell);
      isRequestInProgress = true;

      let suggestion;

      try {
        suggestion = await api.getCodeCompletion(code);
      } catch {
        clearInterval(animationInterval);
        inputElement.classList.remove('before-content');
        inputElement.classList.add('paused');
        const pausedTimeOut = setTimeout(() => {
          inputElement.classList.remove('paused');
          clearTimeout(pausedTimeOut);
          isRequestInProgress = false;
          isRequestSuccessful = false;
        }, 5000);
        return;
      }

      if (suggestion) {
        clearInterval(animationInterval);
        inputElement.classList.remove('before-content');
        isRequestSuccessful = true;
        isRequestInProgress = false;
        codeToFill = suggestion;
        animationElement.innerHTML = suggestion;
      }
    }
  }

  // Two options 'lab' and 'notebook'
  jupyterModel.currctJupyterModel = {};

  const notebookModel = {};

  const labModel = {};

  if (document.querySelector('body.notebook_app')) {
    animation.montedEventListener();
    jupyterModel.currctJupyterModel = jupyterModel.notebookModel;
  }

  const bodyObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
      if (mutation.attributeName === "data-jp-theme-name") {
        const dataJpThemeName = document.body.getAttribute("data-jp-theme-name");
        if (dataJpThemeName.indexOf("JupyterLab") !== -1) {
          animation.montedEventListener();
          jupyterModel.currctJupyterModel = jupyterModel.labModel;
        }
      }
    });
  });

  bodyObserver.observe(document.body, { attributes: true });

  document.addEventListener('keydown', async (event) => {
    if (event.ctrlKey && event.code === 'Space') {
      event.preventDefault();

      if (isRequestInProgress || isRequestSuccessful) {
        return;
      }

      await mainProcess();
    }
  });

  document.addEventListener('keydown', addFillCodeKeyListener);
})();

In this complete content.js file, the modules api.js, utility.js, animation.js, and jupyterModel.js are imported and used within the mainProcess function and event listeners. The code structure and behavior remain the same

ChatGPT:

as before, but now the functionality is separated into different modules for better organization and maintainability.

solved by #32