Coder Social home page Coder Social logo

cpinitiative / ide Goto Github PK

View Code? Open in Web Editor NEW
310.0 3.0 32.0 6.65 MB

A realtime collaborative IDE with code execution, intellisense, mobile support, and built-in USACO submissions.

Home Page: https://ide.usaco.guide/

License: Mozilla Public License 2.0

JavaScript 55.65% CSS 0.25% TypeScript 44.03% HTML 0.06%

ide's Introduction

Realtime Collaborative IDE

A realtime collaborative IDE with code execution, intellisense, and built-in USACO submissions. Designed primarily for Competitive Programming and USACO, with mobile support for coding on the go.

This IDE is built and maintained by Nathan Wang and Benjamin Qi, and is part of the Competitive Programming Initiative.

Running Locally

This project uses the Firebase Realtime Database. This tutorial is helpful (even though Cloud Firestore is not what's being used here). You'll need to install the firebase CLI and Node.js 18.

npm install
npm run dev

npm run dev will start a Firebase emulator for you. By default, the dev server uses a local firebase emulator and the production YJS server. To change these settings, edit src/dev_constants.ts.

Note: If you get a firebase emulators timeout error on Mac, see firebase/firebase-tools#2379 (comment) and Issue #67 in this repo.

Playwright Tests

npm run dev  # Start the dev server in a separate terminal
npm run test

We use Playwright for our e2e tests. The VSCode extension for Playwright can be useful for debugging tests.

Note: If you are using the production YJS servers, the Copy Files test will fail because the YJS_SECURITY_KEY environment variable needs to be set. For local development, feel free to ignore the Copy Files CI test. Alternatively, you can run a local YJS server (see the ide-yjs repository) and use that instead.

Configuring Firebase

You can update the Firebase configuration (if you want to use a custom firebase project, for example) by modifying pages/_app.tsx.

Tech Stack

  • Code execution through a custom Serverless Online Judge
  • Realtime collaboration with YJS
  • Monaco Editor (desktop)
  • Codemirror 6 Editor (mobile)
  • monaco-languageclient with clangd-12 for LSP
  • React
  • Jotai
  • Next.js
  • Typescript
  • Tailwind CSS
  • Firebase Realtime Database
  • Playwright for end-to-end testing
  • Deployed with Vercel

Contact Info

If you have any questions, please open an issue or reach out to us at [email protected].

Misc Notes

LSP Installation

We used Ubuntu 20.04 on Azure, B2s. Open port 3000 on the Azure firewall rules.

1. Install clangd-12

sudo apt update
sudo apt install clangd-12

2. Install node

sudo apt install nodejs npm
sudo npm install -g n
sudo n install lts
sudo n                       # choose v16 or whatever lts is

3. Setup Server

git clone https://github.com/TypeFox/monaco-languageclient.git

cd packages/examples/node

Modify server.ts:

import * as rpc from 'vscode-ws-jsonrpc/cjs';
import { launch } from './json-server-launcher';
import fs from 'fs';
import * as https from 'https';

const privateKey = fs.readFileSync(
  '/etc/letsencrypt/live/lsp.usaco.guide/privkey.pem',
  'utf8'
);
const certificate = fs.readFileSync(
  '/etc/letsencrypt/live/lsp.usaco.guide/fullchain.pem',
  'utf8'
);

process.on('uncaughtException', function (err: any) {
  console.error('Uncaught Exception: ', err.toString());
  if (err.stack) {
    console.error(err.stack);
  }
});

// create the express application
const app = express();
// server the static content, i.e. index.html
app.use(express.static(__dirname));
// start the server
//const server = app.listen(3000);
const httpsServer = https.createServer(
  { key: privateKey, cert: certificate },
  app
);
httpsServer.listen(3000);
// create the web socket
const wss = new ws.Server({
  noServer: true,
  perMessageDeflate: false,
});
httpsServer.on(
  'upgrade',
  (request: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
    // eslint-disable-next-line n/no-deprecated-api
    const pathname = request.url ? url.parse(request.url).pathname : undefined;
    if (pathname === '/sampleServer') {
      wss.handleUpgrade(request, socket, head, webSocket => {
        const socket: rpc.IWebSocket = {
          send: content =>
            webSocket.send(content, error => {
              if (error) {
                throw error;
              }
            }),
          onMessage: cb => webSocket.on('message', cb),
          onError: cb => webSocket.on('error', cb),
          onClose: cb => webSocket.on('close', cb),
          dispose: () => webSocket.close(),
        };
        // launch the server when the web socket is opened
        if (webSocket.readyState === webSocket.OPEN) {
          launch(socket);
        } else {
          webSocket.on('open', () => launch(socket));
        }
      });
    }
  }
);

Modify json-server-launcher.ts:

//import * as path from 'path';
import * as rpc from 'vscode-ws-jsonrpc/cjs';
import * as server from 'vscode-ws-jsonrpc/cjs/server';
import * as lsp from 'vscode-languageserver';
import { start } from './json-server';
import { Message } from 'vscode-languageserver';

export function launch(socket: rpc.IWebSocket) {
  const reader = new rpc.WebSocketMessageReader(socket);
  const writer = new rpc.WebSocketMessageWriter(socket);
  const asExternalProccess =
    process.argv.findIndex(value => value === '--external') !== -1;
  if (asExternalProccess) {
    // start the language server as an external process
    //const extJsonServerPath = path.resolve(__dirname, 'ext-json-server.js');
    const socketConnection = server.createConnection(reader, writer, () =>
      socket.dispose()
    );
    //const serverConnection = server.createServerProcess('JSON', 'node', [extJsonServerPath]);
    const serverConnection = server.createServerProcess('CPP', 'clangd-12');
    if (serverConnection) {
      server.forward(socketConnection, serverConnection, message => {
        if (Message.isRequest(message)) {
          if (message.method === lsp.InitializeRequest.type.method) {
            const initializeParams = message.params as lsp.InitializeParams;
            initializeParams.processId = process.pid;
          }
        }
        return message;
      });
    }
  } else {
    // start the language server inside the current process
    start(reader, writer);
  }
}

Then:

# "cannot find module 'semver' error when running npm install?
# See https://stackoverflow.com/questions/33870520/npm-install-cannot-find-module-semver
npm install
npm run build
node dist/server.js --external

To keep the server running:

sudo apt install tmux
tmux
node dist/server.js --external

# https://askubuntu.com/questions/8653/how-to-keep-processes-running-after-ending-ssh-session
ctrl+b d

# later, to get back into the session
tmux attach -t 0

Firepad / YJS Browser Incompatibility

See FirebaseExtended/firepad#315 and yjs/y-monaco#6.

Replace something similar to

var n = this.configurationService.getValue('files.eol', {
  overrideIdentifier: t,
  resource: e,
});
return n && 'auto' !== n ? n : d.isLinux || d.isMacintosh ? '\n' : '\r\n';

with

var n = this.configurationService.getValue('files.eol', {
  overrideIdentifier: t,
  resource: e,
});
return n && 'auto' !== n ? n : d.isLinux || d.isMacintosh ? '\n' : '\n';

using package-patch.

Monaco Workers

Run

mkdir ./public/monaco-workers
cp -r ./node_modules/monaco-editor-workers/dist/workers/editorWorker* ./public/monaco-workers

This is used by MonacoEditor.tsx (Monaco uses web workers).

Troubleshooting firebase emulators:exec

If firebase emulators:exec fails for unknown reason, try running firebase emulators:exec "yarn playwright test" || cat firebase-debug.log.

Tests that should be written

  • Compile error, stdout, stderr
  • Too large input
  • Too large output
  • Classrooms
  • Copying files (#64, this broke already lol)

Updating Monaco Editor

Make sure Monaco is compatible with monaco-languageclient!! https://github.com/TypeFox/monaco-languageclient/blob/main/docs/versions-and-history.md#monaco-editor--codingamemonaco-vscode-api-compatibility-table

  1. npm install monaco-editor@latest

  2. Modify node_modules/monaco-editor/esm/vs/editor/standalone/browser/standaloneServices.js:

    -        return (isLinux || isMacintosh) ? '\n' : '\r\n';
    +        return (isLinux || isMacintosh) ? '\n' : '\n';
    

    See patches/monaco-editor+??.patch for more details

  3. npx patch-package monaco-editor

  4. Commit the updated patch to Github

  5. rm -r ./public/monaco-workers

  6. mkdir ./public/monaco-workers

  7. cp -r ./node_modules/monaco-editor-workers/dist/workers/editorWorker* ./public/monaco-workers

  8. Test that everything works: LSP, browser sync, cross-platform sync, etc

ide's People

Contributors

96f4 avatar asynchronousai avatar bertaland avatar bqi343 avatar danielzsh avatar enyoukai avatar ericshu6 avatar gilgameshxzero avatar maggie-j-liu avatar sharad-sharma avatar shaubby avatar thecodingwizard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ide's Issues

Tabs vs. spaces?

As far as I can tell, the IDE always indents with tabs rather than spaces. It would be nice if there was a setting to change whether the IDE uses tabs or spaces and also a setting to adjust indent size.

Thanks!

Vim mode doesn't work

When switching from the "Normal" editor mode to the "Vim" editor mode in the "User" tab of Settings, the mode doesn't actually change to Vim; rather, it continues operating like it's in Normal mode. The following message shows up in console when the mode is changed to Vim and "Save" is pressed:

image

Additionally, if you try to go back to Normal mode after you're in Vim mode, the IDE crashes:

image

Also, this bug seems to only have appeared about a few days ago, as Vim mode was working fine before then.

shorter URLs for easier sharing

As mentioned in #7.

Perhaps 6 chars? Though probably the only use case is when I have two devices and I can't directly copy and paste between them.

Output in new workspace

Whenever I create a new workspace , the output of the previous workspace is getting copied. The input is getting cleared but the output is getting copied.

Thanks

Language Server Protocol Support

Immediate tasks:

  • add monaco-languageclient
  • add clangd-12
  • Java
  • Python

Future:

  • improve LSP server code (prevent it from dying due to lack of memory)
  • implement code bundling in a way that lets monaco be cached
  • Add compile flags to LSP
  • Improve connection UI (probably a status indicator rather than toasts)
  • Add ability to disable LSP
  • Add timeout to LSP to auto-stop LSP
  • e2e tests for LSP

References: https://github.com/TypeFox/monaco-languageclient and https://github.com/radian-software/riju

Submit button not working

When I press the button to submit my code to USACO, the loading wheel just keeps on looping. Looking through the console, it seems like the IP you send the code to has an expired certificate, which is then blocked by the browser.

Display Compile Output Even if Compilation Exceeds

Ex. https://ide.usaco.guide/MsXySNwQ8SR4gQKNu9w should display a warning like this:

Main.cpp: In function ‘int main()’:
Main.cpp:8:22: warning: ‘a’ is used uninitialized [-Wuninitialized]
    8 |         cout << a << " " << b << " " << c;
      |                      ^~~
Main.cpp:8:34: warning: ‘b’ is used uninitialized [-Wuninitialized]
    8 |         cout << a << " " << b << " " << c;
      |                                  ^~~
Main.cpp:8:41: warning: ‘c’ is used uninitialized [-Wuninitialized]
    8 |         cout << a << " " << b << " " << c;
      |                                         ^

but currently it displays nothing.

CSAcademy does this.

USACO Judge Settings carry over to new file

Steps to reproduce:

  1. create a new file
  2. add a judge URL
  3. click the "home" button
  4. create a new file

The second new file will have the same judge settings as the first new file (until you reload the page).

Title of the Tab

When I visit a workspace and then go the home page , the title of the tab in the browser is not changing
Here is the title :

Screen Shot 2022-02-05 at 4 37 36 PM

Thanks

No response when click Insert File Template

Hi @cpinitiative this is an excellent project, but it seems there is a small bug, when I click the Insert File Template in File, the website has no response but just warns Reset current file? Any changes you made will be lost.

image

All code in Main.cpp has been reset, but I still can't upload my template file.

My broswer edition is chrome 89.0.4389.114, then I change to firefox 88.0, it also responses nothing.

Maybe it's a feature which is being developed.

As for another suggestion, it would be better if supports display all files in sidebar likes nerdtree.

Thanks!

Creating Extra Files

Pressing "Create New File" creates a bunch of new files. The result after I clicked it three times:

Screen Shot 2021-06-26 at 10 34 35 AM

maybe it has to do w/ the permission change? @thecodingwizard

Dashboard Updates

  • Option to hide (or delete?) files as mentioned in #7.
    • There should still be an option to toggle showing recently hidden files in case you hid one by accident.
  • Toggle default file permissions.

Only allow one language per file?

Instead of having three tabs, we can also just only allow one language per file. It seems like this would simplify a bit of code + simplify the UI, and I can't really think of that many use cases where someone would want multiple languages in one file?

Option to load individual test cases for USACO

Target use case: if a user gets a particular test case wrong after submitting, the user can then click on the test case to load that test case and get the input + expected output.

I forgot how big exactly all the USACO test files are, but I recall it wasn't very big at all. We could just write a script to download all the test cases and upload it to the server

Copy file button not working

when you haven't added anything to the 3 code editors or the scribble editor, vercel error should explain why

Console:
image

From Vercel:
image

userSettingsAtom

we should move defaultPermission into an atom
and then read that atom in joinNewWorkspaceAsOwnerAtom
ie. maybe we should make a userSettingsAtom that synchronizes settings to firebase, and can store:

  • name
  • editorMode
  • defaultPermission
  • color
  • defaultLanguage
  • defaultTemplate
  • etc

Enable Bracket Pair Colorization

It is a very important feature especially for the competitive programmer to have bracket pair colorized, as we use a lot of Nested loops, if-else statements.

USACO IDE File Download

This isn't a big issue but downloading files from the USACO IDE that CPI created saves the file as main.cpp. Renaming this for every file that is created as well as any time I download, submit, fix something, and then download again to resubmit is a huge pain. I also like to keep the files of each problem I solve for personal storage, but I don't think this is a bad idea. A possible solution would be titling the final [chosennameofproject].cpp.

Integrate w/ USACO Monthly Table

Could add an extra option in the dropdown to open a new file in the IDE corresponding to that problem (or open an existing file if the user already owns one for that problem).

Screen Shot 2021-06-20 at 9 20 29 PM

Display output to all users

Amazing project, kudos to all developers! :)
As far as I see, the output of the program (stdout and stderr), and the compile output only arrives to that user who pressed the Run Code button. It would be great if everyone watching could see the same result. Do you think it can be done?

USACO Problem URLs

  • Validate URL (before submit is pressed?)
  • allow pasting of the just the ID (1137)
  • Display the name of the problem somewhere, as well as the input / output format.

Screen Shot 2021-06-20 at 9 41 37 AM

stdio [read-only]

Is it possible to make the stdio section editable as altering the output is an old habit of mine.

Can't run code locally...

After following the instructions to start a local development server and doing yarn dev, I ended up with a bunch of ERR_UNSUPPORTED_DIR_IMPORT errors.

Does anyone know how to fix this? I want to check out the codebase lol

Thanks!
image

Can't log in with gmail id

I tried to log in using my gmail account. But every time site was failed to log in. It was just loading my gmail account name after pop up of a new window. Then I selected my account and site show that loading and back to previous page. It did not logged in.

files won't load

All of my files (old files and newly created ones) won't load. The section where the files are meant to be shown displays "Loading files..." and refuses to load despite multiple page refreshes and logging into the account using a different device.
Screen Shot 2022-06-25 at 10 01 53 PM

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.