123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- 'use strict';
- // The module 'vscode' contains the VS Code extensibility API
- // Import the module and reference it with the alias vscode in your code below
- import * as vscode from 'vscode';
- import { existsSync, writeFileSync, readdirSync } from 'fs';
- import { join, dirname, extname } from 'path';
- import { SITES } from './conn';
- import { newContestFromId, testSolution, veredictName, stressSolution, upgradeArena, newProblemFromId, removeExtension } from './core';
- import { Veredict } from './types';
- /**
- * TODO: Allow custom checker easily
- * TODO: Add several checkers and try to infer which is the correct! [*]
- * TODO: Smart ID detection while parsing ContestId & ProblemId [*]
- * TODO: Smart generator [*]
- * TODO: Find great name/slogan!!! other than acmhelper Competitive Programming made simple
- * TODO: Implement parser for codeforces to test on real cases
- * TODO: Learn how to move static files from `src` to `out`.
- * TODO: Allow programming in other languages than c++
- *
- * [*] Machine Learning?
- */
- const TESTCASES = 'testcases';
- function isProblemFolder(path: string) {
- return existsSync(join(path, 'sol.cpp')) &&
- existsSync(join(path, 'attic'));
- }
- function currentProblem() {
- // Try to find the problem using current open file
- if (vscode.window.activeTextEditor){
- let path = vscode.window.activeTextEditor.document.uri.path;
- const MAX_DEPTH = 3;
- for (let i = 0; i < MAX_DEPTH && !isProblemFolder(path); i++) {
- path = dirname(path);
- }
- if (isProblemFolder(path)){
- return path;
- }
- }
- // Try to find the problem using the current open workspace folder
- if (vscode.workspace.workspaceFolders !== undefined){
- let path = vscode.workspace.workspaceFolders[0].uri.path;
- const MAX_DEPTH = 1;
- for (let i = 0; i < MAX_DEPTH && !isProblemFolder(path); i++) {
- path = dirname(path);
- }
- if (isProblemFolder(path)){
- return path;
- }
- }
- // Problem not found
- return undefined;
- }
- function quickPickSites() {
- let sites: any[] = [];
- SITES.forEach(value => {
- sites.push({
- "label" : value.name,
- "target" : value.name,
- "description" : value.description,
- });
- });
- return sites;
- }
- // Create a new problem
- async function addProblem() {
- if (vscode.workspace.workspaceFolders === undefined) {
- vscode.window.showErrorMessage("Open the folder that will contain the problem.");
- return;
- }
- let path = vscode.workspace.workspaceFolders[0].uri.path;
- let site_info = await vscode.window.showQuickPick(quickPickSites(), { placeHolder: 'Select contest site' });
- if (site_info === undefined){
- vscode.window.showErrorMessage("Site not provided.");
- return;
- }
- let site = site_info.target;
- // TODO: IMPORTANT: Provide custom problem id example in placeholder per different site
- let id = await vscode.window.showInputBox({placeHolder: "Problem ID"});
- if (id === undefined){
- vscode.window.showErrorMessage("Problem ID not provided.");
- return;
- }
- path = join(path, `${id}`);
- newProblemFromId(path, site, id);
- await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(path));
- // TODO: How can I have access to new proccess created using `openFolder`?
- // Just want to run two commands below
- // await vscode.commands.executeCommand("vscode.open", vscode.Uri.file("sol.cpp"));
- // vscode.window.showInformationMessage(`Add problem ${site}/${id} at ${path}`);
- }
- async function addContest() {
- if (vscode.workspace.workspaceFolders === undefined) {
- vscode.window.showErrorMessage("Open the folder that will contain the contest.");
- return;
- }
- let path = vscode.workspace.workspaceFolders[0].uri.path;
- let site_info = await vscode.window.showQuickPick(quickPickSites(), { placeHolder: 'Select contest site' });
- if (site_info === undefined){
- vscode.window.showErrorMessage("Site not provided.");
- return;
- }
- let site = site_info.target;
- let id = undefined;
- if (site === "personal"){
- let name= await vscode.window.showInputBox({placeHolder: "Contest Name"});
- if (name === undefined){
- vscode.window.showErrorMessage("Name not provided.");
- return;
- }
- path = join(path, name);
- let probCountStr = await vscode.window.showInputBox({placeHolder: "Number of problems"});
- if (name === undefined){
- vscode.window.showErrorMessage("Number of problems not provided.");
- return;
- }
- id = Number.parseInt(probCountStr!);
- }
- else{
- // TODO: IMPORTANT: Provide custom contest id example in placeholder per different site
- id = await vscode.window.showInputBox({placeHolder: "Contest ID"});
- if (id === undefined){
- vscode.window.showErrorMessage("Contest ID not provided.");
- return;
- }
- path = join(path, `${id}`);
- }
- newContestFromId(path, site, id);
- vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(path));
- }
- async function debugTestcase(path: string, tcId: string){
- // Change editor layout to show failing test
- await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{ groups: [{}], size: 0.5 }, { groups: [{}, {}, {}], size: 0.5 }] });
- let sol = join(path, `sol.cpp`);
- let inp = join(path, TESTCASES, `${tcId}.in`);
- let out = join(path, TESTCASES, `${tcId}.out`);
- let cur = join(path, TESTCASES, `${tcId}.cur`);
- // TODO: How to clear opened tabs?
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(sol), vscode.ViewColumn.One);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.Two);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Three);
- // This file might not exist!
- if (existsSync(cur)){
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(cur), vscode.ViewColumn.Four);
- }
- }
- async function runSolution(){
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let result = testSolution(path);
- if (result.status === Veredict.OK){
- vscode.window.showInformationMessage("OK");
- }
- else{
- vscode.window.showErrorMessage(`${veredictName(result.status)} on test ${result.failTcId}`);
- debugTestcase(path, result.failTcId!);
- }
- }
- async function openTestcase() {
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let tcs: any[] = [];
- // Read testcases
- readdirSync(join(path, TESTCASES)).
- filter( function (tcpath) {
- return extname(tcpath) === '.in';}).
- map( function(tcpath) {
- let name = removeExtension(tcpath);
- tcs.push({
- 'label' : name,
- 'target' : name,
- });
- });
- let tc = await vscode.window.showQuickPick(tcs, { placeHolder: 'Select testcase' });
- if (tc !== undefined){
- let inp = join(path, TESTCASES, `${tc.target}.in`);
- let out = join(path, TESTCASES, `${tc.target}.out`);
- await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{}, {}]});
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.One);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Two);
- }
- }
- async function addTestcase() {
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let index = 0;
- while (existsSync(join(path, TESTCASES, `${index}.hand.in`))){
- index += 1;
- }
- let inp = join(path, TESTCASES, `${index}.hand.in`);
- let out = join(path, TESTCASES, `${index}.hand.out`);
- writeFileSync(inp, "");
- writeFileSync(out, "");
- await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{}, {}]});
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.One);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Two);
- }
- async function coding() {
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- await vscode.commands.executeCommand("vscode.setEditorLayout", { groups: [{}]});
- let sol = join(path, `sol.cpp`);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(sol), vscode.ViewColumn.One);
- }
- // TODO: Show time that the program took when it's ok
- async function stress(){
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let result = stressSolution(path);
- if (result.status === Veredict.OK){
- vscode.window.showInformationMessage("OK");
- }
- else{
- vscode.window.showErrorMessage(`${veredictName(result.status)} on test ${result.failTcId}`);
- debugTestcase(path, result.failTcId!);
- }
- }
- async function upgrade(){
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- upgradeArena(path);
- }
- // this method is called when your extension is activated
- // your extension is activated the very first time the command is executed
- export function activate(context: vscode.ExtensionContext) {
- console.log('Congratulations, your extension "acmhelper-vscode" is now active!');
- let addProblemCommand = vscode.commands.registerCommand('extension.addProblem', addProblem);
- let addContestCommand = vscode.commands.registerCommand('extension.addContest', addContest);
- let runSolutionCommand = vscode.commands.registerCommand('extension.runSolution', runSolution);
- let openTestcaseCommand = vscode.commands.registerCommand('extension.openTestcase', openTestcase);
- let addTestcaseCommand = vscode.commands.registerCommand('extension.addTestcase', addTestcase);
- let codingCommand = vscode.commands.registerCommand('extension.coding', coding);
- let stressCommand = vscode.commands.registerCommand('extension.stress', stress);
- let upgradeCommand = vscode.commands.registerCommand('extension.upgrade', upgrade);
- context.subscriptions.push(addProblemCommand);
- context.subscriptions.push(addContestCommand);
- context.subscriptions.push(runSolutionCommand);
- context.subscriptions.push(openTestcaseCommand);
- context.subscriptions.push(addTestcaseCommand);
- context.subscriptions.push(codingCommand);
- context.subscriptions.push(stressCommand);
- context.subscriptions.push(upgradeCommand);
- }
- // this method is called when your extension is deactivated
- export function deactivate() {
- }
|