Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for other C compiler: gcc #305

Merged
merged 2 commits into from
Apr 14, 2024
Merged
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
7 changes: 6 additions & 1 deletion src/executors/CExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export default class CExecutor extends ClingExecutor {
}

override run(codeBlockContent: string, outputter: Outputter, cmd: string, cmdArgs: string, ext: string) {
return super.run(codeBlockContent, outputter, cmd, `-x c ${cmdArgs}`, "cpp");
const install_path = this.settings[`clingPath`];
if (install_path.endsWith("cling") || install_path.endsWith("cling.exe")) {
return super.run(codeBlockContent, outputter, cmd, this.settings[`cArgs`], "cpp");
} else {
return super.run(codeBlockContent, outputter, cmd, this.settings[`cArgs`], "c");
}
}
}
13 changes: 8 additions & 5 deletions src/executors/ClingExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ export default abstract class ClingExecutor extends NonInteractiveCodeExecutor {
}

override run(codeBlockContent: string, outputter: Outputter, cmd: string, args: string, ext: string) {

// Run code with a main block
if (this.settings[`${this.language}UseMain`]) {
// Generate a new temp file id and don't set to undefined to super.run() uses the same file id
this.getTempFile(ext);
// Cling expects the main function to have the same name as the file
const code = codeBlockContent.replace(/main\(\)/g, `temp_${this.tempFileId}()`);

// Cling expects the main function to have the same name as the file / the extension is only c when gcc is used
let code: string;
if (ext != "c") {
code = codeBlockContent.replace(/main\(\)/g, `temp_${this.tempFileId}()`);
} else {
code = codeBlockContent;
}
return super.run(code, outputter, this.settings.clingPath, args, ext);
}

// Run code without a main block
// Run code without a main block (cling only)
return new Promise<void>((resolve, reject) => {
const childArgs = [...args.split(" "), ...codeBlockContent.split("\n")];
const child = child_process.spawn(this.settings.clingPath, childArgs, {env: process.env, shell: this.usesShell});
Expand Down
2 changes: 1 addition & 1 deletion src/executors/Executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ export default abstract class Executor extends EventEmitter {
protected getTempFile(ext: string) {
if (this.tempFileId === undefined)
this.tempFileId = Date.now().toString();
return `${os.tmpdir()}/temp_${this.tempFileId}.${ext}`;
return `${os.tmpdir()}\\temp_${this.tempFileId}.${ext}`;
}
}
37 changes: 30 additions & 7 deletions src/executors/NonInteractiveCodeExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {Outputter} from "src/Outputter";
import {LanguageId} from "src/main";
import { ExecutorSettings } from "../settings/Settings.js";
import windowsPathToWsl from "../transforms/windowsPathToWsl.js";
import { error } from "console";

export default class NonInteractiveCodeExecutor extends Executor {
usesShell: boolean
Expand Down Expand Up @@ -44,16 +45,38 @@ export default class NonInteractiveCodeExecutor extends Executor {
} else {
args.push(tempFileName);
}

const child = child_process.spawn(cmd, args, {env: process.env, shell: this.usesShell});

this.handleChildOutput(child, outputter, tempFileName).then(() => {
this.tempFileId = undefined; // Reset the file id to use a new file next time
});


let child: child_process.ChildProcessWithoutNullStreams;

// check if compiled by gcc
if (cmd.endsWith("gcc") || cmd.endsWith("gcc.exe")) {
// remove .c from tempFileName and add .out for the compiled output and add output path to args
const tempFileNameWExe: string = tempFileName.slice(0, -2) + ".out";
args.push("-o", tempFileNameWExe);

// compile c file with gcc and handle possible output
const childGCC = child_process.spawn(cmd, args, {env: process.env, shell: this.usesShell});
this.handleChildOutput(childGCC, outputter, tempFileName);
childGCC.on('exit', (code) => {
if (code === 0) {
// executing the compiled file
child = child_process.spawn(tempFileNameWExe, { env: process.env, shell: this.usesShell });
this.handleChildOutput(child, outputter, tempFileNameWExe).then(() => {
this.tempFileId = undefined; // Reset the file id to use a new file next time
});
}
});
} else {
child = child_process.spawn(cmd, args, { env: process.env, shell: this.usesShell });
this.handleChildOutput(child, outputter, tempFileName).then(() => {
this.tempFileId = undefined; // Reset the file id to use a new file next time
});
}

// We don't resolve the promise here - 'handleChildOutput' registers a listener
// For when the child_process closes, and will resolve the promise there
this.resolveRun = resolve;
this.resolveRun = resolve;
}).catch((err) => {
this.notifyError(cmd, cmdArgs, tempFileName, err, outputter);
resolve();
Expand Down
36 changes: 12 additions & 24 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import ExecutorManagerView, {

import runAllCodeBlocks from './runAllCodeBlocks';

export const languageAliases = ["javascript", "typescript", "bash", "csharp", "wolfram", "nb", "wl", "hs", "py", "scpt"] as const;
export const languageAliases = ["javascript", "typescript", "bash", "csharp", "wolfram", "nb", "wl", "hs", "py"] as const;
export const canonicalLanguages = ["js", "ts", "cs", "lean", "lua", "python", "cpp", "prolog", "shell", "groovy", "r",
"go", "rust", "java", "powershell", "kotlin", "mathematica", "haskell", "scala", "racket", "fsharp", "c", "dart",
"ruby", "batch", "sql", "octave", "maxima", "applescript", "zig"] as const;
Expand Down Expand Up @@ -59,7 +59,7 @@ export default class ExecuteCodePlugin extends Plugin {
supportedLanguages.forEach(l => {
console.debug(`Registering renderer for ${l}.`)
this.registerMarkdownCodeBlockProcessor(`run-${l}`, async (src, el, _ctx) => {
await MarkdownRenderer.renderMarkdown('```' + l + '\n' + src + (src.endsWith('\n') ? '' : '\n') + '```', el, _ctx.sourcePath, null);
await MarkdownRenderer.renderMarkdown('```' + l + '\n' + src + (src.endsWith('\n') ? '' : '\n') + '```', el, '', null);
});
});

Expand Down Expand Up @@ -212,7 +212,7 @@ export default class ExecuteCodePlugin extends Plugin {
button.className = runButtonDisabledClass;
let transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
transformedCode = addMagicToJS(transformedCode);
this.runCode(transformedCode, out, button, this.settings.nodePath, this.settings.nodeArgs, this.settings.jsFileExtension, language, file);
this.runCode(transformedCode, out, button, this.settings.nodePath, this.settings.nodeArgs, "js", language, file);
});

} else if (language === "java") {
Expand All @@ -231,7 +231,7 @@ export default class ExecuteCodePlugin extends Plugin {
transformedCode = addInlinePlotsToPython(transformedCode, TOGGLE_HTML_SIGIL);
transformedCode = addMagicToPython(transformedCode);

this.runCode(transformedCode, out, button, this.settings.pythonPath, this.settings.pythonArgs, this.settings.pythonFileExtension, language, file);
this.runCode(transformedCode, out, button, this.settings.pythonPath, this.settings.pythonArgs, "py", language, file);
});

} else if (language === "shell") {
Expand Down Expand Up @@ -259,7 +259,7 @@ export default class ExecuteCodePlugin extends Plugin {
button.addEventListener("click", async () => {
button.className = runButtonDisabledClass;
const transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
this.runCode(transformedCode, out, button, this.settings.clingPath, `-std=${this.settings.clingStd} ${this.settings.clingArgs}`, this.settings.cppFileExtension, language, file);
this.runCode(transformedCode, out, button, this.settings.clingPath, `-std=${this.settings.clingStd} ${this.settings.clingArgs}`, "cpp", language, file);
});

} else if (language === "prolog") {
Expand Down Expand Up @@ -289,7 +289,7 @@ export default class ExecuteCodePlugin extends Plugin {
button.className = runButtonDisabledClass;
let transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
transformedCode = addInlinePlotsToR(transformedCode);
this.runCode(transformedCode, out, button, this.settings.RPath, this.settings.RArgs, this.settings.RFileExtension, language, file);
this.runCode(transformedCode, out, button, this.settings.RPath, this.settings.RArgs, "R", language, file);
});

} else if (language === "go") {
Expand Down Expand Up @@ -317,21 +317,21 @@ export default class ExecuteCodePlugin extends Plugin {
button.addEventListener("click", async () => {
button.className = runButtonDisabledClass;
const transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
this.runCodeInShell(transformedCode, out, button, this.settings.luaPath, this.settings.luaArgs, this.settings.luaFileExtension, language, file);
this.runCodeInShell(transformedCode, out, button, this.settings.luaPath, this.settings.luaArgs, "lua", language, file);
});

} else if (language === "dart") {
button.addEventListener("click", async () => {
button.className = runButtonDisabledClass;
const transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
this.runCodeInShell(transformedCode, out, button, this.settings.dartPath, this.settings.dartArgs, this.settings.dartFileExtension, language, file);
this.runCodeInShell(transformedCode, out, button, this.settings.dartPath, this.settings.dartArgs, "dart", language, file);
});

} else if (language === "cs") {
button.addEventListener("click", async () => {
button.className = runButtonDisabledClass;
const transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
this.runCodeInShell(transformedCode, out, button, this.settings.csPath, this.settings.csArgs, this.settings.csFileExtension, language, file);
this.runCodeInShell(transformedCode, out, button, this.settings.csPath, this.settings.csArgs, "csx", language, file);
});

} else if (language === "haskell") {
Expand Down Expand Up @@ -363,7 +363,7 @@ export default class ExecuteCodePlugin extends Plugin {
button.addEventListener("click", async () => {
button.className = runButtonDisabledClass;
const transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
this.runCodeInShell(transformedCode, out, button, this.settings.rubyPath, this.settings.rubyArgs, this.settings.rubyFileExtension, language, file);
this.runCodeInShell(transformedCode, out, button, this.settings.rubyPath, this.settings.rubyArgs, "rb", language, file);
})
} else if (language === "sql") {
button.addEventListener("click", async () => {
Expand All @@ -376,26 +376,14 @@ export default class ExecuteCodePlugin extends Plugin {
button.className = runButtonDisabledClass;
let transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
transformedCode = addInlinePlotsToOctave(transformedCode);
this.runCodeInShell(transformedCode, out, button, this.settings.octavePath, this.settings.octaveArgs, this.settings.octaveFileExtension, language, file);
this.runCodeInShell(transformedCode, out, button, this.settings.octavePath, this.settings.octaveArgs, "octave", language, file);
})
} else if (language === "maxima") {
button.addEventListener("click", async () => {
button.className = runButtonDisabledClass;
let transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
transformedCode = addInlinePlotsToMaxima(transformedCode);
this.runCodeInShell(transformedCode, out, button, this.settings.maximaPath, this.settings.maximaArgs, this.settings.maximaFileExtension, language, file);
})
}else if (language === "racket") {
button.addEventListener("click", async () => {
button.className = runButtonDisabledClass;
const transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
this.runCodeInShell(transformedCode, out, button, this.settings.racketPath, this.settings.racketArgs, this.settings.racketFileExtension, language, file);
})
} else if (language === "applescript") {
button.addEventListener("click", async () => {
button.className = runButtonDisabledClass;
const transformedCode = await new CodeInjector(this.app, this.settings, language).injectCode(srcCode);
this.runCodeInShell(transformedCode, out, button, this.settings.applescriptPath, this.settings.applescriptArgs, this.settings.applescriptFileExtension, language, file);
this.runCodeInShell(transformedCode, out, button, this.settings.maximaPath, this.settings.maximaArgs, "maxima", language, file);
})
} else if (language === "zig") {
button.addEventListener("click", async () => {
Expand Down
16 changes: 0 additions & 16 deletions src/settings/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export interface ExecutorSettings {
onlyCurrentBlock: boolean;
nodePath: string;
nodeArgs: string;
jsFileExtension: string;
jsInject: string;
tsPath: string;
tsArgs: string;
Expand All @@ -23,20 +22,16 @@ export interface ExecutorSettings {
leanInject: string;
luaPath: string;
luaArgs: string;
luaFileExtension: string;
luaInject: string;
dartPath: string;
dartArgs: string;
dartFileExtension: string;
dartInject: string;
csPath: string;
csArgs: string;
csFileExtension: string;
csInject: string;
pythonPath: string;
pythonArgs: string;
pythonEmbedPlots: boolean;
pythonFileExtension: string;
pythonInject: string;
shellPath: string;
shellArgs: string;
Expand Down Expand Up @@ -77,7 +72,6 @@ export interface ExecutorSettings {
cargoEvalArgs: string;
rustInject: string;
cppRunner: string;
cppFileExtension: string;
cppInject: string;
cppArgs: string;
cppUseMain: boolean;
Expand All @@ -88,7 +82,6 @@ export interface ExecutorSettings {
RPath: string;
RArgs: string;
REmbedPlots: boolean;
RFileExtension: string;
rInject: string;
kotlinPath: string;
kotlinArgs: string;
Expand Down Expand Up @@ -120,7 +113,6 @@ export interface ExecutorSettings {
cInject: string;
rubyPath: string;
rubyArgs: string;
rubyFileExtension: string;
rubyInject: string;
sqlPath: string;
sqlArgs: string;
Expand Down Expand Up @@ -180,7 +172,6 @@ export const DEFAULT_SETTINGS: ExecutorSettings = {
onlyCurrentBlock: false,
nodePath: "node",
nodeArgs: "",
jsFileExtension: "js",
jsInject: "",
tsPath: "ts-node",
tsArgs: "",
Expand All @@ -190,20 +181,16 @@ export const DEFAULT_SETTINGS: ExecutorSettings = {
leanInject: "",
luaPath: "lua",
luaArgs: "",
luaFileExtension: "lua",
luaInject: "",
dartPath: "dart",
dartArgs: "",
dartFileExtension: "dart",
dartInject: "",
csPath: "dotnet-script",
csArgs: "",
csFileExtension: "csx",
csInject: "",
pythonPath: "python",
pythonArgs: "",
pythonEmbedPlots: true,
pythonFileExtension: "py",
pythonInject: "",
shellPath: "bash",
shellArgs: "",
Expand Down Expand Up @@ -236,7 +223,6 @@ export const DEFAULT_SETTINGS: ExecutorSettings = {
cargoEvalArgs: "",
rustInject: "",
cppRunner: "cling",
cppFileExtension: "cpp",
cppInject: "",
cppArgs: "",
cppUseMain: false,
Expand All @@ -247,7 +233,6 @@ export const DEFAULT_SETTINGS: ExecutorSettings = {
RPath: "Rscript",
RArgs: "",
REmbedPlots: true,
RFileExtension: "R",
rInject: "",
kotlinPath: "kotlinc",
kotlinArgs: "-script",
Expand Down Expand Up @@ -279,7 +264,6 @@ export const DEFAULT_SETTINGS: ExecutorSettings = {
cInject: "",
rubyPath: "ruby",
rubyArgs: "",
rubyFileExtension: "rb",
rubyInject: "",
sqlPath: "psql",
sqlArgs: "-d <database> -U <user> -f",
Expand Down
14 changes: 7 additions & 7 deletions src/settings/per-lang/makeCSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@ import { SettingsTab } from "../SettingsTab";
export default (tab: SettingsTab, containerEl: HTMLElement) => {
containerEl.createEl('h3', { text: 'C Settings' });
new Setting(containerEl)
.setName('Cling path')
.setDesc('The path to your Cling installation.')
.setName('gcc / Cling path')
.setDesc('The path to your gcc / Cling installation.')
.addText(text => text
.setValue(tab.plugin.settings.clingPath)
.onChange(async (value) => {
const sanitized = tab.sanitizePath(value);
tab.plugin.settings.clingPath = sanitized;
console.log('Cling path set to: ' + sanitized);
console.log('gcc / Cling path set to: ' + sanitized);
await tab.plugin.saveSettings();
}));
new Setting(containerEl)
.setName('Cling arguments for C')
.setName('gcc / Cling arguments for C')
.addText(text => text
.setValue(tab.plugin.settings.cArgs)
.onChange(async (value) => {
tab.plugin.settings.cArgs = value;
console.log('Cling args set to: ' + value);
console.log('gcc / Cling args set to: ' + value);
await tab.plugin.saveSettings();
}));
new Setting(containerEl)
.setName('Cling std')
.setName('Cling std (ignored for gcc)')
.addDropdown(dropdown => dropdown
.addOption('c++98', 'C++ 98')
.addOption('c++11', 'C++ 11')
Expand All @@ -38,7 +38,7 @@ export default (tab: SettingsTab, containerEl: HTMLElement) => {
await tab.plugin.saveSettings();
}));
new Setting(containerEl)
.setName('Use main function')
.setName('Use main function (mandatory for gcc)')
.setDesc('If enabled, will use a main() function as the code block entrypoint.')
.addToggle((toggle) => toggle
.setValue(tab.plugin.settings.cUseMain)
Expand Down
Loading