Skip to content

Commit d72e801

Browse files
authored
Merge pull request #207 from Incharajayaram/stdin-feature
feat: Add stdin support, improve error reporting and UI
2 parents 0d61918 + 81c6f73 commit d72e801

File tree

1 file changed

+128
-52
lines changed

1 file changed

+128
-52
lines changed

src/pages/EditorComponent.js

Lines changed: 128 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,41 @@ const OutputLayout = styled("div")(({ theme }) => ({
6565
"@media (min-width: 1024px)": {
6666
height: "30vh",
6767
padding: "1rem",
68+
width: "50%",
69+
},
70+
}));
71+
72+
const InputLayout = styled("div")(({ theme }) => ({
73+
backgroundColor: theme.palette.background.paper,
74+
height: "20vh",
75+
margin: "1rem 0",
76+
overflow: "auto",
77+
border: `2px solid ${theme.palette.divider}`,
78+
borderRadius: "1rem",
79+
padding: "1rem",
80+
"@media (min-width: 1024px)": {
81+
height: "30vh",
82+
padding: "1rem",
83+
width: "50%",
84+
margin: "1rem 0 0 1rem",
85+
},
86+
}));
87+
88+
const StyledTextArea = styled("textarea")(({ theme }) => ({
89+
width: "100%",
90+
height: "calc(100% - 40px)",
91+
background: "transparent",
92+
color: theme.palette.text.primary,
93+
border: "none",
94+
resize: "none",
95+
outline: "none",
96+
fontSize: "1rem",
97+
"&::placeholder": {
98+
color: theme.palette.text.secondary,
99+
opacity: 0.8,
100+
},
101+
"&:focus::placeholder": {
102+
color: "transparent",
68103
},
69104
}));
70105

@@ -79,6 +114,7 @@ const decodeFormat = (data) => {
79114

80115
function EditorComponent() {
81116
const [code, setCode] = useState(null);
117+
const [stdin, setStdin] = useState("");
82118
const [output, setOutput] = useState([]);
83119
const [currentLanguage, setCurrentLanguage] = useState(
84120
LANGUAGES[0].DEFAULT_LANGUAGE
@@ -133,9 +169,28 @@ function EditorComponent() {
133169
DEFAULT_LANGUAGE: selectedLanguage.DEFAULT_LANGUAGE,
134170
NAME: selectedLanguage.NAME,
135171
});
136-
setCode(selectedLanguage.HELLO_WORLD);
172+
const savedCode = localStorage.getItem(`code-${selectedLanguage.DEFAULT_LANGUAGE}`);
173+
if (savedCode !== null) {
174+
setCode(savedCode);
175+
} else {
176+
setCode(selectedLanguage.HELLO_WORLD);
177+
}
137178
}, [currentLanguage]);
138179

180+
useEffect(() => {
181+
const handler = setTimeout(() => {
182+
if (code) {
183+
localStorage.setItem(`code-${currentLanguage}`, code);
184+
} else {
185+
localStorage.removeItem(`code-${currentLanguage}`);
186+
}
187+
}, 500);
188+
189+
return () => {
190+
clearTimeout(handler);
191+
};
192+
}, [code]);
193+
139194
const handleEditorThemeChange = async (_, theme) => {
140195
if (["light", "vs-dark"].includes(theme.ID)) {
141196
setCurrentEditorTheme(theme);
@@ -178,7 +233,7 @@ function EditorComponent() {
178233
body: JSON.stringify({
179234
source_code: encodedCode,
180235
language_id: languageDetails.ID,
181-
stdin: "",
236+
stdin: btoa(stdin),
182237
expected_output: "",
183238
}),
184239
}
@@ -208,16 +263,25 @@ function EditorComponent() {
208263
)
209264
.then((response) => response.json())
210265
.then((data) => {
211-
if (!data.stdout) {
212-
enqueueSnackbar("Please check the code", { variant: "error" });
213-
if (data.stderr) {
214-
setOutput(decodeFormat(data.stderr));
215-
} else if (data.compile_output) {
216-
setOutput(decodeFormat(data.compile_output));
217-
}
218-
return;
266+
const newOutput = [];
267+
let errorMessage = [];
268+
269+
if (data.stdout) {
270+
newOutput.push(...decodeFormat(data.stdout));
219271
}
220-
setOutput(decodeFormat(data.stdout));
272+
if (data.stderr) {
273+
newOutput.push(...decodeFormat(data.stderr));
274+
errorMessage.push("Error in code");
275+
}
276+
if (data.compile_output) {
277+
newOutput.push(...decodeFormat(data.compile_output));
278+
errorMessage.push("Compilation error");
279+
}
280+
281+
if (errorMessage.length > 0) {
282+
enqueueSnackbar(errorMessage.join(" and "), { variant: "error" });
283+
}
284+
setOutput(newOutput);
221285
})
222286
.catch((error) => {
223287
enqueueSnackbar("Error retrieving output: " + error.message, {
@@ -229,7 +293,7 @@ function EditorComponent() {
229293
} catch (error) {
230294
enqueueSnackbar("Error: " + error.message, { variant: "error" });
231295
}
232-
}, [enqueueSnackbar, languageDetails]);
296+
}, [enqueueSnackbar, languageDetails, stdin]);
233297

234298
// import file
235299
const [isImporting, setIsImporting] = React.useState(false);
@@ -651,49 +715,61 @@ function EditorComponent() {
651715
</StyledButton>
652716
</div>
653717
</StyledLayout>
654-
<OutputLayout>
655-
<div className="output-header">
656-
<Typography
657-
variant="h6"
658-
sx={{ fontSize: "1rem", fontWeight: "bold" }}
659-
>
660-
Output
661-
</Typography>
662-
<div className="output-controls">
663-
<Button
664-
size="small"
665-
onClick={copyOutput}
666-
startIcon={<FaCopy />}
667-
variant="outlined"
668-
sx={{ minWidth: "auto", padding: "4px 8px" }}
669-
>
670-
Copy
671-
</Button>
672-
<Button
673-
size="small"
674-
onClick={clearOutput}
675-
startIcon={<FaTrash />}
676-
variant="outlined"
677-
sx={{ minWidth: "auto", padding: "4px 8px", marginLeft: "0.5rem" }}
718+
<div style={{ display: "flex", flexDirection: "row" }}>
719+
<OutputLayout>
720+
<div className="output-header">
721+
<Typography
722+
variant="h6"
723+
sx={{ fontSize: "1rem", fontWeight: "bold" }}
678724
>
679-
Clear
680-
</Button>
725+
Output
726+
</Typography>
727+
<div className="output-controls">
728+
<Button
729+
size="small"
730+
onClick={copyOutput}
731+
startIcon={<FaCopy />}
732+
variant="outlined"
733+
sx={{ minWidth: "auto", padding: "4px 8px" }}
734+
>
735+
Copy
736+
</Button>
737+
<Button
738+
size="small"
739+
onClick={clearOutput}
740+
startIcon={<FaTrash />}
741+
variant="outlined"
742+
sx={{ minWidth: "auto", padding: "4px 8px", marginLeft: "0.5rem" }}
743+
>
744+
Clear
745+
</Button>
746+
</div>
681747
</div>
682-
</div>
683-
<div className="output-content">
684-
{Array.isArray(output) && output.length > 0 ? (
685-
output.map((result, i) => (
686-
<div key={i} className="output-line">
687-
{result}
748+
<div className="output-content">
749+
{Array.isArray(output) && output.length > 0 ? (
750+
output.map((result, i) => (
751+
<div key={i} className="output-line">
752+
{result}
753+
</div>
754+
))
755+
) : (
756+
<div className="output-empty">
757+
No output yet. Run your code to see results!
688758
</div>
689-
))
690-
) : (
691-
<div className="output-empty">
692-
No output yet. Run your code to see results!
693-
</div>
694-
)}
695-
</div>
696-
</OutputLayout>
759+
)}
760+
</div>
761+
</OutputLayout>
762+
<InputLayout>
763+
<Typography variant="h6" sx={{ fontSize: "1rem", fontWeight: "bold" }}>
764+
Input
765+
</Typography>
766+
<StyledTextArea
767+
value={stdin}
768+
onChange={(e) => setStdin(e.target.value)}
769+
placeholder="Provide all program input here before running"
770+
/>
771+
</InputLayout>
772+
</div>
697773
</>
698774
);
699775

0 commit comments

Comments
 (0)