Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,16 @@
"default": "cpp java js python c rust ruby csharp go haskell",
"description": "Space separated languages, in top to bottom order, shown in menu when a problem is imported via Competitive Companion. Example 'java python' would show java on top, followed by python."
},
"cph.general.includeProblemIndex": {
"type": "boolean",
"default": false,
"description": "Include the problem index for problem file generated ( like P_1_abc ) instead of omitting it"
},
"cph.general.wordRegex": {
"type": "string",
"default": "[\\p{L}]+|[0-9]+",
"description": "The regex that defines what a word is for problem file generated. Each word is separated by an underscore"
},
"cph.general.useShortCodeForcesName": {
"type": "boolean",
"default": false,
Expand All @@ -368,6 +378,11 @@
"default": "",
"description": "The path to the template file that will be used when creating a new file for the default language via Competitive Companion. For Java templates, use 'CLASS_NAME' as a placeholder for the class name like 'class CLASS_NAME{...}'"
},
"cph.general.doTemplateFileVariableReplacement": {
"type": "boolean",
"default": false,
"description": "Replace $var$ in the template file with its value. For example, replace $url$ with the problem's url. For a full list, see what is outputted in the console with debug mode on for Competitive Companion"
},
"cph.general.autoShowJudge": {
"type": "boolean",
"default": true,
Expand Down Expand Up @@ -432,4 +447,4 @@
"type": "git",
"url": "https://github.com/agrawal-d/competitive-programming-helper/"
}
}
}
26 changes: 24 additions & 2 deletions src/companion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ import {
useShortAtCoderName,
getMenuChoices,
getDefaultLanguageTemplateFileLocation,
includeProblemIndex,
wordRegex,
doTemplateFileVariableReplacement,
} from './preferences';
import { getProblemName } from './submit';
import { spawn } from 'child_process';
import { getJudgeViewProvider } from './extension';
import { words_in_text } from './utilsPure';
import telmetry from './telmetry';
import os from 'os';
import { words_in_text } from './utilsPure';

const emptyResponse: CphEmptyResponse = { empty: true };
let savedResponse: CphEmptyResponse | CphSubmitResponse = emptyResponse;
Expand Down Expand Up @@ -147,6 +150,12 @@ export const setupCompanionServer = () => {
};

export const getProblemFileName = (problem: Problem, ext: string) => {
if (!includeProblemIndex()) {
const sections = problem.name.split(' - ');
if (sections.length > 1) {
problem.name = sections.splice(1).join();
}
}
if (isCodeforcesUrl(new URL(problem.url)) && useShortCodeForcesName()) {
return `${getProblemName(problem.url)}.${ext}`;
} else if (isLuoguUrl(new URL(problem.url)) && useShortLuoguName()) {
Expand All @@ -165,7 +174,7 @@ export const getProblemFileName = (problem: Problem, ext: string) => {
useShortCodeForcesName(),
);

const words = words_in_text(problem.name);
const words = words_in_text(problem.name, wordRegex());
if (words === null) {
return `${problem.name.replace(/\W+/g, '_')}.${ext}`;
} else {
Expand Down Expand Up @@ -256,6 +265,19 @@ const handleNewProblem = async (problem: Problem) => {
className,
);
}
if (doTemplateFileVariableReplacement()) {
for (const [key, value] of Object.entries(problem)) {
let replaceWith = JSON.stringify(value);
replaceWith = replaceWith.substring(
1,
replaceWith.length - 1,
);
templateContents = templateContents.replace(
`$${key}$`,
replaceWith,
);
}
}
writeFileSync(srcPath, templateContents);
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ export const getDefaultLangPref = (): string | null => {
return pref;
};

export const includeProblemIndex = (): boolean => {
return getPreference('general.includeProblemIndex');
};
export const wordRegex = (): string => {
return getPreference('general.wordRegex');
};
export const useShortCodeForcesName = (): boolean => {
return getPreference('general.useShortCodeForcesName');
};
Expand All @@ -118,6 +124,9 @@ export const getDefaultLanguageTemplateFileLocation = (): string | null => {
}
return pref;
};
export const doTemplateFileVariableReplacement = (): boolean => {
return getPreference('general.doTemplateFileVariableReplacement');
};

export const getCCommand = (): string =>
getPreference('language.c.Command') || 'gcc';
Expand Down
43 changes: 40 additions & 3 deletions src/tests/utilsPure.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,55 @@ describe('problem name parser', () => {
test('mix of latin, non latin and numbers', () => {
const output = ['apple', '12345', 'mango', 'India', 'こんにちは', '7'];
const input = 'apple 12345 mango India こんにちは 7';
expect(words_in_text(input)).toEqual(output);
expect(words_in_text(input, '[\\p{L}]+|[0-9]+')).toEqual(output);
});

test('just a number', () => {
const output = ['23'];
const input = '23';
expect(words_in_text(input)).toEqual(output);
expect(words_in_text(input, '[\\p{L}]+|[0-9]+')).toEqual(output);
});

test('just a word', () => {
const output = ['grapes'];
const input = 'grapes';
expect(words_in_text(input)).toEqual(output);
expect(words_in_text(input, '[\\p{L}]+|[0-9]+')).toEqual(output);
});

test('word and number', () => {
const output = ['grapes', '1'];
const input = 'grapes1';
expect(words_in_text(input, '[\\p{L}]+|[0-9]+')).toEqual(output);
});

test('mix of latin, non latin, numbers, and apostrophes', () => {
const output = [
"apple's",
'12345',
"mango's",
"India's",
"こん'に'ち'は",
'7',
];
const input = "apple's 12345 mango's India's こん'に'ち'は 7";
expect(words_in_text(input, "[\\p{L}']+|[0-9']+")).toEqual(output);
});

test('number and apostrophe', () => {
const output = ["2'3"];
const input = "2'3";
expect(words_in_text(input, "[\\p{L}']+|[0-9']+")).toEqual(output);
});

test('word and apostrophe', () => {
const output = ["grape's"];
const input = "grape's";
expect(words_in_text(input, "[\\p{L}']+|[0-9']+")).toEqual(output);
});

test('word and number and apostrophes', () => {
const output = ["grape's", "1's"];
const input = "grape's 1's";
expect(words_in_text(input, "[\\p{L}0-9']+")).toEqual(output);
});
});
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export type prefSection =
| 'general.hideStderrorWhenCompiledOK'
| 'general.ignoreSTDERROR'
| 'general.firstTime'
| 'general.includeProblemIndex'
| 'general.wordRegex'
| 'general.useShortCodeForcesName'
| 'general.useShortLuoguName'
| 'general.useShortAtCoderName'
Expand Down Expand Up @@ -49,6 +51,7 @@ export type prefSection =
| 'general.retainWebviewContext'
| 'general.autoShowJudge'
| 'general.defaultLanguageTemplateFileLocation'
| 'general.doTemplateFileVariableReplacement'
| 'general.remoteServerAddress'
| 'general.showLiveUserCount';

Expand Down
4 changes: 2 additions & 2 deletions src/utilsPure.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Pure javascript utilities, that don't use VS Code API.
// They can still use VS Code type definitions.

export const words_in_text = function (text: string) {
const regex = /[\p{L}]+|[0-9]+/gu;
export const words_in_text = function (text: string, wordRegex: string) {
const regex = new RegExp(wordRegex, 'gu');
return text.match(regex);
};

Expand Down