Skip to content

Commit

Permalink
added new edit command
Browse files Browse the repository at this point in the history
  • Loading branch information
noel-friedrich committed Feb 18, 2024
1 parent 298fe25 commit b987d6e
Show file tree
Hide file tree
Showing 10 changed files with 354 additions and 176 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
## Introduction

The page is build to work like a Unix-Terminal, including:
* 196 commands such as `ls`, `cd` and of course `cowsay`
* 197 commands such as `ls`, `cd` and of course `cowsay`
* a file-system that you can navigate and manipulate
* TAB-Autocompletion (TABA) and Command-Validity Checking (CVC)
* multiple ways to get rickrolled
Expand Down Expand Up @@ -105,7 +105,7 @@ The following list can also be viewed using the `whatis *` command
| `du` | display storage of current directory |
| `easter-eggs` | open easter egg hunt |
| `echo` | print a line of text |
| `edit` | edit a file of the current directory |
| `edit` | edit a file |
| `enigma` | Simulate an Enigma machine |
| `error404` | Display a 404 error |
| `eval` | evaluate javascript code |
Expand Down Expand Up @@ -177,6 +177,7 @@ The following list can also be viewed using the `whatis *` command
| `neural-rocket` | trains neural networks to fly rockets |
| `nsolve` | solve an equation using the newton-raphson method |
| `number-guess` | guess a random number |
| `old-edit` | edit a file of the current directory (old version of editor) |
| `particle` | start a particle simulation |
| `pascal` | print a pascal triangle |
| `password` | Generate a random password |
Expand Down
4 changes: 2 additions & 2 deletions gui/edit/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ <h1>
</h1>

<p class="subtitle">
edit a file of the current directory
edit a file
</p>

<div id="inputs-container"></div>
Expand Down Expand Up @@ -55,7 +55,7 @@ <h1>
<script src="../../js/terminal.js"></script>

<script>
const command_data = {"description": "edit a file of the current directory", "args": {"?file:f": "the file to open"}, "name": "edit"}
const command_data = {"description": "edit a file", "args": {"file:f": "file to edit"}, "name": "edit"}
</script>

<script src="../main.js"></script>
Expand Down
65 changes: 65 additions & 0 deletions gui/old-edit/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>old-edit (Terminal Command)</title>
<link rel="stylesheet" href="../../style.css">
<link rel="stylesheet" href="../style.css?t=0">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Lora">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Quicksand">
<link rel="icon" type="image/x-icon" href="../../res/img/favicon.png">
</head>

<body>
<header>
<img src="../../res/img/favicon.png" alt="Logo" class="logo">
<h1><a href="../index.html">terminal</a></h1>
</header>

<main>

<h1>
old-edit
</h1>

<p class="subtitle">
edit a file of the current directory (old version of editor)
</p>

<div id="inputs-container"></div>

<p id="mainErrorOutput" class="error"></p>

<button id="runButton">Run</button>

<div class="terminal-container">
<div class="terminal-output" id="terminal"></div>
</div>

<hr>

<a href="../index.html" class="linkbutton">Open Command List</a>
<a href="../../index.html" class="linkbutton">Open Terminal</a>

</main>

<footer>
Generated by <a href="https://www.noel-friedrich.de/">Noel Friedrich</a><div style="width:1em;display:inline-block">;</div>
<a href="http://www.noel-friedrich.de/blobber/legal/impressum">Impressum</a>
<a href="http://www.noel-friedrich.de/blobber/legal/data-policy">Privacy</a>
</footer>

<script src="../../js/filesystem.js"></script>
<script src="../../js/terminal.js"></script>

<script>
const command_data = {"description": "edit a file of the current directory (old version of editor)", "args": {"?file:f": "the file to open"}, "isSecret": true, "name": "old-edit"}
</script>

<script src="../main.js"></script>

</body>

</html>
257 changes: 90 additions & 167 deletions js/commands/edit.js
Original file line number Diff line number Diff line change
@@ -1,185 +1,108 @@
const cssCode = {
".editor-parent": {
"width": "100%",
"resize": "both",
"display": "grid",
"grid-template-rows": "auto 1fr",
"grid-template-columns": "1fr",
},

".editor-header-title": {
"width": "fit-content",
"color": "var(--background)",
"background": "var(--foreground)",
},

".editor-body": {
"display": "grid",
"grid-template-rows": "1fr",
"grid-template-columns": "auto 1fr",
},

".editor-sidebar": {
"color": "var(--background)",
"background": "var(--foreground)",
"padding-right": "0.1em",
"padding-left": "0.1em",
},

".editor-content": {
"outline": "none",
"padding-right": "0.5em",
"padding-left": "0.5em",
},

".editor-content > div:focus-visible": {
"outline": "none",
"background": "#1d1d1d",
},
}

function createEditorHTML() {
let parent = createElement("div", {className: "editor-parent"})
let header = createElement("div", {className: "editor-header"}, parent)
let headerTitle = createElement("div", {className: "editor-header-title"}, header)
let body = createElement("div", {className: "editor-body"}, parent)
let sidebar = createElement("div", {className: "editor-sidebar"}, body)
let contentScroll = createElement("div", {className: "editor-content-scroll"}, body)
let content = createElement("div", {
className: "editor-content",
contentEditable: true,
}, contentScroll)

return {
parent, header, headerTitle, body, sidebar, content, contentScroll
}
}

function implementCSS(code) {
let style = document.createElement("style")
for (const [selector, properties] of Object.entries(code)) {
let css = selector + " {"
for (const [property, value] of Object.entries(properties))
css += property + ": " + value + ";"
css += "}"
style.innerHTML += css
}
terminal.document.head.appendChild(style)
}

let tempFileContent = null
let tempFileName = null
let elements = null
let lineCount = null
let prevLineCount = null
let currentlyEditing = false

function updateLineNums() {
lineCount = elements.content.childNodes.length

if (lineCount == 0) {
elements.sidebar.textContent = "1"
prevLineCount = lineCount
} else if (prevLineCount !== lineCount) {
elements.sidebar.textContent = ""
for (let i = 0; i < lineCount; i++) {
let line = createElement("div", {className: "editor-line-num"}, elements.sidebar)
line.textContent = i + 1
}
prevLineCount = lineCount
terminal.addCommand("edit", async function(args) {
function makeTextarea(textContent) {
const textarea = document.createElement("textarea")
textarea.value = textContent

textarea.style.position = "relative"
textarea.style.background = "var(--background)"
textarea.style.color = "var(--foreground)"
textarea.style.marginTop = `calc(var(--font-size) * 0.8)`
textarea.style.padding = `calc(var(--font-size) * 0.5)`
textarea.style.border = "1px solid var(--foreground)"
textarea.style.borderRadius = `calc(var(--font-size) * 0.5)`

textarea.style.width = `calc(var(--font-size) * 35)`
textarea.style.minWidth = `calc(var(--font-size) * 15)`
textarea.style.maxWidth = `calc(var(--font-size) * 100)`

textarea.rows = 20

return textarea
}
}

function createElement(tag, props, parent=null) {
const element = document.createElement(tag)
for (const [key, value] of Object.entries(props))
element[key] = value
if (parent)
parent.appendChild(element)
return element
}

function getText() {
let text = ""
for (let line of elements.content.querySelectorAll("div")) {
text += line.textContent + "\n"

function makeButton(text) {
const button = terminal.createTerminalButton({text})

button.style.marginTop = `calc(var(--font-size) * -0.5)`
button.style.marginRight = `calc(var(--font-size) * 0.2)`
button.style.padding = `calc(var(--font-size) * 0.5)`
button.style.border = "1px solid var(--foreground)"
button.style.borderRadius = `0 0 calc(var(--font-size) * 0.5) calc(var(--font-size) * 0.5)`
button.style.width = "5em"

return button
}
return text.slice(0, -1)
}

function loadContent() {
let lastElement = null
for (let line of tempFileContent.split("\n")) {
let lineElement = createElement("div", {}, elements.content)
lineElement.textContent = line
if (lineElement.textContent.trim() == "")
lineElement.appendChild(document.createElement("br"))
lastElement = lineElement

const file = terminal.getFile(args.file)

if (file.isDirectory) {
throw new Error("Cannot edit directory data")
}
if (lastElement)
setTimeout(() => lastElement.focus(), 100)
lineCount = tempFileContent.split("\n").length
updateLineNums()
}

terminal.addCommand("edit", async function(args) {
if (terminal.inTestMode) return

tempFileContent = ""
tempFileName = "Untitled File"
currentlyEditing = true
prevLineCount = null
elements = createEditorHTML()

if (args.file) {
let file = terminal.getFile(args.file)
if (file.type == FileType.FOLDER)
throw new Error("cannot edit a folder")
tempFileContent = file.content
tempFileName = file.path
const textarea = makeTextarea(file.content)
const saveButton = makeButton("Save")
const cancelButton = makeButton("Cancel")
const br = document.createElement("br")
let editingActive = true

terminal.parentNode.appendChild(textarea)
terminal.parentNode.appendChild(br)
terminal.parentNode.appendChild(saveButton)
terminal.parentNode.appendChild(cancelButton)
terminal.scroll()
textarea.focus()

saveButton.onclick = save

function removeElements() {
textarea.remove()
saveButton.remove()
cancelButton.remove()
br.remove()
}

implementCSS(cssCode)
terminal.parentNode.appendChild(elements.parent)
function save() {
if (!editingActive) {
return
}

elements.headerTitle.textContent = tempFileName
elements.content.addEventListener("input", updateLineNums)
loadContent()
file.content = textarea.value
editingActive = false
removeElements()
terminal.printSuccess(`Changes saved at ${file.path}`)
}

terminal.document.addEventListener("keydown", event => {
// save
if (event.ctrlKey && event.key == "s") {
currentlyEditing = false
event.preventDefault()
textarea.onkeydown = function(event) {
if (!editingActive) {
return
}
})

while (currentlyEditing) {
await sleep(100)
}
if (event.key == "Tab") {
event.preventDefault()
let start = this.selectionStart
let end = this.selectionEnd

this.value = this.value.substring(0, start) + "\t" + this.value.substring(end);

this.selectionStart = this.selectionEnd = start + 1;
}

while (tempFileName == "" || tempFileName == "Untitled File") {
tempFileName = await terminal.prompt("file name: ")
while (!terminal.isValidFileName(tempFileName)) {
terminal.printError("invalid file name")
tempFileName = await terminal.prompt("file name: ")
if (event.key == "s" && event.ctrlKey) {
event.preventDefault()
save()
}
}

if (terminal.fileExists(tempFileName)) {
let file = terminal.getFile(tempFileName)
if (file.type == FileType.FOLDER)
throw new Error("cannot edit a folder")
file.content = getText()
} else {
terminal.currDirectory.addChild(
new PlainTextFile(getText()).setName(tempFileName)
)
terminal.onInterrupt(() => {
removeElements()
})

while (editingActive) {
await sleep(1000)
}
}, {
description: "edit a file of the current directory",
description: "edit a file",
args: {
"?file:f": "the file to open",
"file:f": "file to edit",
}
})

})
Loading

0 comments on commit b987d6e

Please sign in to comment.