Compare commits
No commits in common. "561146b81d137d686860e441e0acf826bf980920" and "4b16e30a7901643b78af7850ecb056e781c0a281" have entirely different histories.
561146b81d
...
4b16e30a79
@ -1,5 +1,5 @@
|
|||||||
:experimental:
|
:experimental:
|
||||||
:docdatetime: 2022-10-18T17:56:26+02:00
|
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||||
|
|
||||||
= Cargo
|
= Cargo
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ Bibliothek. +
|
|||||||
Es wird auch gleich `main.rs`, ein `.git`-Ordner (inkl. `.gitignore`)
|
Es wird auch gleich `main.rs`, ein `.git`-Ordner (inkl. `.gitignore`)
|
||||||
und `Cargo.toml` erstellt.
|
und `Cargo.toml` erstellt.
|
||||||
|
|
||||||
== Angelegte Dateien
|
== Angelegte Datein
|
||||||
|
|
||||||
=== Cargo.toml
|
=== Cargo.toml
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:experimental:
|
:experimental:
|
||||||
:docdatetime: 2022-10-18T17:56:26+02:00
|
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||||
|
|
||||||
= Erstes Spiel
|
= Erstes Spiel
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ CLI-Eingabe
|
|||||||
** ohne die ``use'' Anweisung oben, müsste es `std::io::stdin()` sein
|
** ohne die ``use'' Anweisung oben, müsste es `std::io::stdin()` sein
|
||||||
* `.read_line(&mut guess)` ließt eine Zeile und speichert sie in guess
|
* `.read_line(&mut guess)` ließt eine Zeile und speichert sie in guess
|
||||||
** `&` erstellt dabei eine Referenz (wie in C)
|
** `&` erstellt dabei eine Referenz (wie in C)
|
||||||
** Referenzen sind standardmäßig immutable - deshalb `&mut`
|
** Referenzen sind standardmäßig imutable - deshalb `&mut`
|
||||||
** `read_line()` gibt ein `Result`-Objekt zurück, dieser kann `Ok` oder
|
** `read_line()` gibt ein `Result`-Objekt zurück, dieser kann `Ok` oder
|
||||||
`Err` enthalten
|
`Err` enthalten
|
||||||
* `.expect("Fehlermeldung")` entpackt das `Result`-Objekt
|
* `.expect("Fehlermeldung")` entpackt das `Result`-Objekt
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:experimental:
|
:experimental:
|
||||||
:docdatetime: 2022-10-18T17:56:26+02:00
|
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||||
|
|
||||||
= Konzepte
|
= Konzepte
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ fn main() {
|
|||||||
|
|
||||||
Die Ausgabe des Programms ist dabei der letztere Wert, hier also 10.
|
Die Ausgabe des Programms ist dabei der letztere Wert, hier also 10.
|
||||||
Es ist also mehr eine neue Variable unter dem selben Namen wie die alte.
|
Es ist also mehr eine neue Variable unter dem selben Namen wie die alte.
|
||||||
Sogar der Datentyp kann sich dabei ändern, man muss sich also nicht ständig neue Namen für Variablen ausdenken, nur weil man sie casted (Juchuu!).
|
Sogar der Datentyp kann sich dabei ändern, man muss sich also nicht ständig neue Namen für Variabeln ausdenken, nur weil man sie casted (Juchuu!).
|
||||||
|
|
||||||
Da Variablen immer Block-Scope-basiert (?) sind, kann dies natürlich auch in einem eingebetteten Block genutzt werden.
|
Da Variablen immer Block-Scope-basiert (?) sind, kann dies natürlich auch in einem eingebetteten Block genutzt werden.
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ Chars werden mit single-quotes geschrieben (Strings mit doppelten quotes).
|
|||||||
|
|
||||||
Allerdings scheint es noch ein wenig komplizierter zu sein, das kommt aber erst später.
|
Allerdings scheint es noch ein wenig komplizierter zu sein, das kommt aber erst später.
|
||||||
|
|
||||||
=== Compound Types
|
=== Combound Types
|
||||||
Gruppierung von mehreren Werten in einem Typ.
|
Gruppierung von mehreren Werten in einem Typ.
|
||||||
|
|
||||||
==== Tupel
|
==== Tupel
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:experimental:
|
:experimental:
|
||||||
:docdatetime: 2022-10-18T17:56:26+02:00
|
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||||
|
|
||||||
= Ownership
|
= Ownership
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html[Link zum Buc
|
|||||||
== Was ist das?
|
== Was ist das?
|
||||||
|
|
||||||
Jeder Wert hat eine Variable, die ihn "besitzt".
|
Jeder Wert hat eine Variable, die ihn "besitzt".
|
||||||
Jeder Wert kann zu einem Zeitpunkt nur von _einer_ Variable besessen werden.
|
Jeder Wert kann zu einem Zeitpunkt nur von _einer_ Variable bessessen werden.
|
||||||
Sollte die Variable aus dem Scope verschwinden, wird der Wert ungültig und aus dem Speicher entfernt.
|
Sollte die Variable aus dem Scope verschwinden, wird der Wert ungültig und aus dem Speicher entfernt.
|
||||||
|
|
||||||
== Warum?
|
== Warum?
|
||||||
@ -148,4 +148,4 @@ Fun fact: String Literale sind auch Slices und damit Referenzen von Strings.
|
|||||||
Noch mehr fun fact: Da dynamische String und String Literale damit quasi den selben Typ beschreiben, haben sie auch den gemeinsamen Typ `&str`.
|
Noch mehr fun fact: Da dynamische String und String Literale damit quasi den selben Typ beschreiben, haben sie auch den gemeinsamen Typ `&str`.
|
||||||
Für Leseoperationen kann also im Allgemeinen dieser benutzt werden.
|
Für Leseoperationen kann also im Allgemeinen dieser benutzt werden.
|
||||||
|
|
||||||
Slices können auch mutable sein, dafür muss aber das ursprüngliche Array mutable sein und es kann immer nur ein mutable Slice gleichzeitig existieren (also genauso wie beim Ownership).
|
Slices können auch mutable sein, dafür muss aber das ursprüngliche Array mmutable sein und es kann immer nur ein mutable Slice gleichzetig existieren (also genauso wie beim Ownership).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:experimental:
|
:experimental:
|
||||||
:docdatetime: 2022-10-18T17:56:26+02:00
|
:docdatetime: 2022-08-10T17:04:53+02:00
|
||||||
|
|
||||||
= Enums und Pattern Matching
|
= Enums und Pattern Matching
|
||||||
|
|
||||||
@ -73,13 +73,13 @@ Es gibt zwar keine Attribute, aber da ja auch die internen Structs Methoden habe
|
|||||||
|
|
||||||
Options hab ich oben schonmal kurz beschrieben.
|
Options hab ich oben schonmal kurz beschrieben.
|
||||||
In Rust ist dieser Datentyp sehr wichtig.
|
In Rust ist dieser Datentyp sehr wichtig.
|
||||||
Die Dokumentation dazu ist https://doc.rust-lang.org/std/option/enum.Option.html[hier zu finden] und enthält sehr viel Wichtiges und Interessantes.
|
Die Dokumentation dazu ist https://doc.rust-lang.org/std/option/enum.Option.html[hier zu finden] und enthält sehr viel Wichtiges und Interesantes.
|
||||||
|
|
||||||
== `match`
|
== `match`
|
||||||
|
|
||||||
`match` ist quasi das `switch` von Rust.
|
`match` ist quasi das `switch` von Rust.
|
||||||
Nur kann es auch prüfen, ob eine Variable einem Enum-Typen angehört.
|
Nur kann es auch prüfen, ob eine Variable einem Enum-Typen angehört.
|
||||||
So wie Rust bis jetzt klang, kann wahrscheinlich jedem Datentypen ein "match-Trait" gegeben werden, der dann eine "Zugehörigkeit" (Gleichheit stimmt ja irgendwie nicht) prüfen kann.
|
So wie Rust bis jetzt klang, kann wahrscheinlich jedem Datentypen ein "match-Trait" gegeben werden, der dann eine "Zugehörigkeit" (Gleicheit stimmt ja irgendwie nicht) prüfen kann.
|
||||||
|
|
||||||
Aber ganz einfach: Angenommen wir wollen die Methode `to_css_string` von oben implementieren.
|
Aber ganz einfach: Angenommen wir wollen die Methode `to_css_string` von oben implementieren.
|
||||||
Diese Methode muss ja, je nach Typ, völlig unterschiedlich funktionieren.
|
Diese Methode muss ja, je nach Typ, völlig unterschiedlich funktionieren.
|
||||||
@ -124,7 +124,7 @@ Der Unterschied ist, dass bei `other` noch der Inhalt genutzt werden kann, bei `
|
|||||||
=== `if let`
|
=== `if let`
|
||||||
|
|
||||||
Dieses if-Konstrukt nutzt man am besten, wenn man nur auf eine einzelne Variante eines Enums prüfen möchte.
|
Dieses if-Konstrukt nutzt man am besten, wenn man nur auf eine einzelne Variante eines Enums prüfen möchte.
|
||||||
Letztendlich ist es ganz simpel:
|
Letzendlich ist es ganz simpel:
|
||||||
|
|
||||||
[source, rust]
|
[source, rust]
|
||||||
----
|
----
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
:experimental:
|
|
||||||
:docdatetime: 2022-10-18T17:56:26+02:00
|
|
||||||
|
|
||||||
= How to: Projektmanagement
|
= How to: Projektmanagement
|
||||||
|
|
||||||
https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html[Link zum Buch]
|
https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html[Link zum Buch]
|
||||||
|
|
||||||
== Packages, Crates, Modules, was?
|
== Packages, Crates, Modules, was?
|
||||||
|
|
||||||
Rust hat ein sehr hierarchisches Konzept, was die Strukturierung von Projekten angeht.
|
Rust hat ein sehr hierachisches Konzept, was die Strukturierung von Projekten angeht.
|
||||||
|
|
||||||
Fangen wir mal von oben an:
|
Fangen wir mal von oben an:
|
||||||
|
|
||||||
@ -40,7 +37,7 @@ Ihr Merkmal ist vor allem, dass eine `main`-Funktion existiert, die der Einstieg
|
|||||||
|
|
||||||
==== Library Crate
|
==== Library Crate
|
||||||
|
|
||||||
Wie der Name schon sagt, stellt diese Art Crate nur Funktionen zur Verfügung wie eine Bibliothek.
|
Wie der Name schon sagt, stellt diese Art Crate nur Funktionen zur verfügung wie eine Bibliothek.
|
||||||
|
|
||||||
=== Modules
|
=== Modules
|
||||||
|
|
||||||
@ -146,7 +143,7 @@ fn main() {
|
|||||||
|
|
||||||
Dagegen gilt für Enums: Wenn der Enum public ist, sind auch alle Varianten public.
|
Dagegen gilt für Enums: Wenn der Enum public ist, sind auch alle Varianten public.
|
||||||
|
|
||||||
==== Abkürzungen mit `use`
|
==== Abürzungen mit `use`
|
||||||
|
|
||||||
Angenommen, wir haben eine Mediathek mit Filmen, Serien, Spielen, etc. und brauchen immer lange Zugriffspfade (also z.B. `crate::medien::spiele::liste::add()`), obwohl wir nur Spiele brauchen, kann `use` benutzt werden.
|
Angenommen, wir haben eine Mediathek mit Filmen, Serien, Spielen, etc. und brauchen immer lange Zugriffspfade (also z.B. `crate::medien::spiele::liste::add()`), obwohl wir nur Spiele brauchen, kann `use` benutzt werden.
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
:experimental:
|
|
||||||
:docdatetime: 2022-10-18T17:56:27+02:00
|
|
||||||
|
|
||||||
= Standard Collections
|
= Standard Collections
|
||||||
|
|
||||||
https://doc.rust-lang.org/book/ch08-00-common-collections.html[Link zum Buch]
|
https://doc.rust-lang.org/book/ch08-00-common-collections.html[Link zum Buch]
|
||||||
@ -144,7 +141,7 @@ Das macht das ganze ordentlich schwierig.
|
|||||||
|
|
||||||
Ist immer eine schlechte Idee, außer man weiß exakt wie lang die einzelnen Zeichen (in Byte) des Strings sind.
|
Ist immer eine schlechte Idee, außer man weiß exakt wie lang die einzelnen Zeichen (in Byte) des Strings sind.
|
||||||
Im Englischen ist es normalerweise 1 Byte pro Zeichen, Umlaute sind schon 2, und so weiter.
|
Im Englischen ist es normalerweise 1 Byte pro Zeichen, Umlaute sind schon 2, und so weiter.
|
||||||
Sollte man aus Versehen ein Zeichen "durchschneiden" (also nur 1 Byte eines "ü" im Slice haben), gibt es eine Runtime Panic.
|
Sollte man außversehen ein Zeichen "durchschneiden" (also nur 1 Byte eines "ü" im Slice haben), gibt es eine Runtime Panic.
|
||||||
|
|
||||||
=== Iterieren
|
=== Iterieren
|
||||||
|
|
||||||
@ -164,7 +161,7 @@ for b in "hallo".bytes() {
|
|||||||
// Wirft eben die einzelnen u8 raus.
|
// Wirft eben die einzelnen u8 raus.
|
||||||
----
|
----
|
||||||
|
|
||||||
Wenn wir "grapheme" haben wollen (Was anscheinend so etwas wie "volle Zeichen" sind, mehr als nur char), gibt es keine eingebaute Funktion aber crates, die das lösen.
|
Wenn wir "grapheme" haben wollen (Was anscheinend sowas wie "volle Zeichen" sind, mehr als nur char), gibt es keine eingebaute Funktion aber crates, die das lösen.
|
||||||
|
|
||||||
== HashMaps
|
== HashMaps
|
||||||
|
|
||||||
@ -180,7 +177,7 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
// -- Erstellen --
|
// -- Erstellen --
|
||||||
// iter(), zip() und collect()
|
// iter(), zip() und collect()
|
||||||
// collect() kann in alles mögliche wandeln, deshalb muss der Typ angegeben werden.
|
// collect() kann in alles mögliche wandeln, deshalb muss der Typ anggeben werden.
|
||||||
let woerter = vec![String::from("eins"), String::from("zwei"), String::from("drei")];
|
let woerter = vec![String::from("eins"), String::from("zwei"), String::from("drei")];
|
||||||
let zahlen = vec![1, 2, 3];
|
let zahlen = vec![1, 2, 3];
|
||||||
let mut zahlwort: HashMap<_, _> = woerter.into_iter().zip(zahlen.into_iter()).collect();
|
let mut zahlwort: HashMap<_, _> = woerter.into_iter().zip(zahlen.into_iter()).collect();
|
||||||
@ -219,7 +216,6 @@ Falls Key oder Value kein Copy Trait haben, wird der Ownership übergeben. Strin
|
|||||||
== Hausaufgaben
|
== Hausaufgaben
|
||||||
|
|
||||||
Das Buch gibt uns hier ein paar Aufgaben, die wir jetzt lösen können:
|
Das Buch gibt uns hier ein paar Aufgaben, die wir jetzt lösen können:
|
||||||
|
|
||||||
* Den Median aus einer Liste finden. Erst sortieren, dann den mittleren Wert.
|
* Den Median aus einer Liste finden. Erst sortieren, dann den mittleren Wert.
|
||||||
* Wörter zu "pig-latin" machen. Wenn erster Buchstabe ein Vokal ist, wird "-hay" angehängt, wenn es ein Konsonant ist, wird er ans Ende angefügt (nach "-") und "ay" angehängt.
|
* Wörter zu "pig-latin" machen. Wenn erster Buchstabe ein Vokal ist, wird "-hay" angehängt, wenn es ein Konsonant ist, wird er ans Ende angefügt (nach "-") und "ay" angehängt.
|
||||||
* Eine kleine Befehlszeile mit Befehlen wie "Add Name to Sales" und Ausgabe.
|
* Eine kleine Befehlszeile mit Befehlen wie "Add Name to Sales" und Ausgabe.
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
:experimental:
|
|
||||||
:docdatetime: 2022-08-22T17:04:01+02:00
|
|
||||||
|
|
||||||
= Errors und `panic!`
|
|
||||||
|
|
||||||
https://doc.rust-lang.org/book/ch09-00-error-handling.html[Link zum Buch]
|
|
||||||
|
|
||||||
== `panic!`
|
|
||||||
|
|
||||||
Dieses Makro it furchtbar simpel: Es macht Panik und das Programm stirbt mit einem Fehler.
|
|
||||||
Diesen Fehler kann man auch nicht catchen.
|
|
||||||
|
|
||||||
Wenn `RUST_BACKTRACE` als Umgebungsvariable gesetzt ist, wird auch noch ein langer Traceback angezeigt, allerdings nur, solange Debug-Symbole aktiviert sind (also bei `cargo run` oder `cargo build` ohne `--release`).
|
|
||||||
|
|
||||||
Will man gar kein Traceback und kein "unwinding" (das "hochgehen" durch den Funktionsstack und Aufräumen), kann man auch noch folgendes zu seiner `Cargo.toml` hinzufügen:
|
|
||||||
|
|
||||||
[source, toml]
|
|
||||||
----
|
|
||||||
[profile.release]
|
|
||||||
panic = 'abort'
|
|
||||||
----
|
|
||||||
|
|
||||||
== `Result<T, E>`
|
|
||||||
|
|
||||||
Der Result-Datentyp ist deutlich besser für mögliche Fehler geeignet, die das Programm abfangen und bearbeiten kann.
|
|
||||||
Falls zum Beispiel eine Datei auf dem Dateisystem nicht existiert, ist es ja manchmal gewünscht, dass diese Datei dann einfach angelegt wird.
|
|
||||||
|
|
||||||
Der `Result`-Typ ist ein Enum von `Ok<T>` und `Error<E>`.
|
|
||||||
Also kann dann mit `match` geprüft werden, was genau wir gerade bekommen haben.
|
|
||||||
Alternativ können auch Funktionen wie `unwrap_or_else(|error| {...})` genutzt werden.
|
|
||||||
|
|
||||||
`Ok<T>` verhält sich wie `Some<T>` und sollte zurückgegeben werden, wenn alles glatt läuft.
|
|
||||||
|
|
||||||
`Error<E>` beinhaltet einen Fehler.
|
|
||||||
Der genaue Fehler kann mit `error.kind()` erfahren werden; ein weiteres `match` ist dann eine "genauere" Fehlerbehandlung.
|
|
||||||
|
|
||||||
Ein volles Beispiel mit ganz viel `match`:
|
|
||||||
|
|
||||||
[source, rust]
|
|
||||||
----
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::ErrorKind;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let greeting_file_result = File::open("hello.txt");
|
|
||||||
|
|
||||||
let greeting_file = match greeting_file_result {
|
|
||||||
Ok(file) => file,
|
|
||||||
Err(error) => match error.kind() {
|
|
||||||
ErrorKind::NotFound => match File::create("hello.txt") {
|
|
||||||
Ok(fc) => fc,
|
|
||||||
Err(e) => panic!("Problem creating the file: {:?}", e),
|
|
||||||
},
|
|
||||||
other_error => {
|
|
||||||
panic!("Problem opening the file: {:?}", other_error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== `unwrap()` und `expect()`
|
|
||||||
|
|
||||||
Machen aus einem `Result<T, E>` entweder ein `T` oder eine `panic!`.
|
|
||||||
Bei `expect()` kann man noch die Fehlermeldung festlegen.
|
|
||||||
|
|
||||||
Warum man jemals `unwrap()` nehmen sollte, erschließt sich mir nicht ganz.
|
|
||||||
|
|
||||||
=== `?`
|
|
||||||
|
|
||||||
Oft schreibt man Funktionen so, dass Fehler weiter "hochgegeben" werden, falls man welche bekommt.
|
|
||||||
`?` macht genau das bei einem Result.
|
|
||||||
Codemäßig erklärt:
|
|
||||||
|
|
||||||
[source, rust]
|
|
||||||
----
|
|
||||||
let a = match result {
|
|
||||||
Ok(nummer) => nummer,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ergibt das selbe wie
|
|
||||||
|
|
||||||
let a = result?;
|
|
||||||
----
|
|
||||||
|
|
||||||
Das `?` kann auch für zum Beispiel `Option` verwendet werden, dann returned es natürlich `None`.
|
|
||||||
|
|
||||||
=== Rückgaben von `main()`
|
|
||||||
|
|
||||||
Bis jetzt hat `main()` immer nichts, also implizit `()` zurückgegeben.
|
|
||||||
Manchmal wollen wir ja aber auch was anderes als "0" als return code haben.
|
|
||||||
Wir können Tatsächlich auch ein Result zurückgeben. Und zwar ein `Result<(), Box<dyn Error>>`.
|
|
||||||
Der zweite Typ dort, kann wohl als "irgendein Fehler" gelesen werden und wird später noch erklärt.
|
|
||||||
|
|
||||||
Allgemein kann aber jedes Objekt, dass `std::process::Termination`-Trait implementiert von main als Rückgabe genutzt werden.
|
|
||||||
|
|
||||||
== Wann `Result<T, E>`, wann `panic!`?
|
|
||||||
|
|
||||||
Der Artikel ist sehr sehr sehr lang, aber eigentlich sagt er:
|
|
||||||
"Panic nur wenn es eben nicht gerettet werden kann."
|
|
||||||
Und obviously in Tests.
|
|
||||||
|
|
||||||
Und man kann natürlich auch tolle eigene Fehlertypen für Result bauen.
|
|
61
list.json
61
list.json
@ -1,20 +1,19 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"name": "terminal",
|
"name": "homepage",
|
||||||
"short_desc": "The terminal on my website.",
|
"short_desc": "This website.",
|
||||||
"desc": [
|
"desc": [
|
||||||
"This is part of my homepage.",
|
"This is my homepage.",
|
||||||
"What you see on the page resembles an CLI. You just type in commands and some output is shown or it does something on the website.",
|
"What you see here should resemble an CLI. If you ever used Linux this should be pretty easy for you.",
|
||||||
"To find out which commands are available, you can just type %{help}.",
|
"Everyone else: Have no fear. It is pretty simple. You just type in commands and the output is shown here or it does something on the webite.",
|
||||||
|
"To find out, which commands are available, you can type just %{help}.",
|
||||||
"",
|
"",
|
||||||
"Everything is always in development. So if you come back in a few days/weeks/months/years something could have been changed!",
|
"Currently everything is still in development. So if you come back in a few days/weeks/months/years something could have been changed!",
|
||||||
"You can also check out the #%{dev version|https://dev.c0ntroller.de} if you haven't already.",
|
|
||||||
"",
|
"",
|
||||||
"Have fun!"
|
"Have fun!"
|
||||||
],
|
],
|
||||||
"repo": "https://git.c0ntroller.de/c0ntroller/frontpage",
|
"repo": "https://git.c0ntroller.de/c0ntroller/frontpage"
|
||||||
"title": "Terminal"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "project",
|
"type": "project",
|
||||||
@ -25,31 +24,28 @@
|
|||||||
"Then I created a webpage that fetches and shows various information.",
|
"Then I created a webpage that fetches and shows various information.",
|
||||||
"Currently it includes time, weather, calendar, departures and more."
|
"Currently it includes time, weather, calendar, departures and more."
|
||||||
],
|
],
|
||||||
"repo": "https://git.c0ntroller.de/c0ntroller/infoscreen",
|
"repo": "https://git.c0ntroller.de/c0ntroller/infoscreen"
|
||||||
"title": "Infoscreen"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "diary",
|
"type": "diary",
|
||||||
"name": "rust",
|
"name": "rust",
|
||||||
"short_desc": "Me learning Rust (German).",
|
"short_desc": "Me learning Rust (German).",
|
||||||
"desc": [
|
"desc": [
|
||||||
"I documented my progress to learn the Rust programming language.",
|
"I documented my progress to lern the Rust programming language.",
|
||||||
"It follows the #%{Rust book|https://doc.rust-lang.org/book/} with my own annotations.",
|
"It follows the #%{Rust book|https://doc.rust-lang.org/book/} with my own annotations.",
|
||||||
"Everything is in German as these notes are mostly meant for me."
|
"Everything is in German as these notes are mostly meant for me."
|
||||||
],
|
],
|
||||||
"entries": [
|
"entries": [
|
||||||
{ "title": "Hello World", "filename": "00 - Hello World"},
|
{ "title": "00 - Hello World", "filename": "00 - Hello World"},
|
||||||
{ "title": "Cargo", "filename": "01 - Cargo"},
|
{ "title": "01 - Cargo", "filename": "01 - Cargo"},
|
||||||
{ "title": "Higher-Lower-Game", "filename": "02 - Higher-Lower-Spiel"},
|
{ "title": "02 - Higher-Lower-Game", "filename": "02 - Higher-Lower-Spiel"},
|
||||||
{ "title": "Basics", "filename": "03 - Concepts"},
|
{ "title": "03 - Basics", "filename": "03 - Concepts"},
|
||||||
{ "title": "Ownership", "filename": "04 - Ownership"},
|
{ "title": "04 - Ownership", "filename": "04 - Ownership"},
|
||||||
{ "title": "Structs", "filename": "05 - Structs"},
|
{ "title": "05 - Structs", "filename": "05 - Structs"},
|
||||||
{ "title": "Enums", "filename": "06 - Enums"},
|
{ "title": "06 - Enums", "filename": "06 - Enums"},
|
||||||
{ "title": "Crates & Modules", "filename": "07 - Management"},
|
{ "title": "07 - Crates & Modules", "filename": "07 - Management"},
|
||||||
{ "title": "Collections", "filename": "08 - Collections"},
|
{ "title": "08 - Collections", "filename": "07 - Collections"}
|
||||||
{ "title": "Errors und panic!", "filename": "09 - Errors und panic"}
|
]
|
||||||
],
|
|
||||||
"title": "Rust Diary"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "project",
|
"type": "project",
|
||||||
@ -57,12 +53,10 @@
|
|||||||
"short_desc": "TUfast is a browser extension that is used by multiple thousand users of the TU Dresden.",
|
"short_desc": "TUfast is a browser extension that is used by multiple thousand users of the TU Dresden.",
|
||||||
"desc": [
|
"desc": [
|
||||||
"TUfast is a browser extension that is used by multiple thousand users of the TU Dresden.",
|
"TUfast is a browser extension that is used by multiple thousand users of the TU Dresden.",
|
||||||
"It provides autologin to the most used portals, shortcuts, redirects, and more.",
|
"It provides autologin to the most used portals, shortcuts, redirects, and more."
|
||||||
"I'm one of the developers."
|
|
||||||
],
|
],
|
||||||
"repo": "https://github.com/TUfast-TUD/TUfast_TUD",
|
"repo": "https://github.com/TUfast-TUD/TUfast_TUD",
|
||||||
"more": "https://tu-fast.de/",
|
"more": "https://tu-fast.de/"
|
||||||
"title": "TUfast TUD"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "project",
|
"type": "project",
|
||||||
@ -74,8 +68,7 @@
|
|||||||
"Even the self-hosted community version has no such functionality.",
|
"Even the self-hosted community version has no such functionality.",
|
||||||
"I decided that's BS and made my own script to sync a project to git."
|
"I decided that's BS and made my own script to sync a project to git."
|
||||||
],
|
],
|
||||||
"repo": "https://git.c0ntroller.de/c0ntroller/overleaf-git-sync",
|
"repo": "https://git.c0ntroller.de/c0ntroller/overleaf-git-sync"
|
||||||
"title": "Overleaf Git Sync"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "project",
|
"type": "project",
|
||||||
@ -86,8 +79,7 @@
|
|||||||
"To get the initial tokens and the refresh token it is necessary to have a server that prints the POST body.",
|
"To get the initial tokens and the refresh token it is necessary to have a server that prints the POST body.",
|
||||||
"This application does this."
|
"This application does this."
|
||||||
],
|
],
|
||||||
"repo": "https://git.c0ntroller.de/c0ntroller/simple-callback-server",
|
"repo": "https://git.c0ntroller.de/c0ntroller/simple-callback-server"
|
||||||
"title": "Simple Callback Server"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "project",
|
"type": "project",
|
||||||
@ -95,10 +87,9 @@
|
|||||||
"short_desc": "A script that syncs a Google Photos album to your drive.",
|
"short_desc": "A script that syncs a Google Photos album to your drive.",
|
||||||
"desc": [
|
"desc": [
|
||||||
"Giving random apps access to your Google Photos can be bad.",
|
"Giving random apps access to your Google Photos can be bad.",
|
||||||
"To still use an album as screensaver etc. I wrote this script.",
|
"To still use an album as screenaver etc. I wrote this script.",
|
||||||
"It syncs all your photos to your drive while giving you maximum privacy."
|
"It syncs all your photos to your drive while giving you maximum privacy."
|
||||||
],
|
],
|
||||||
"repo": "https://git.c0ntroller.de/c0ntroller/simple-callback-server",
|
"repo": "https://git.c0ntroller.de/c0ntroller/simple-callback-server"
|
||||||
"title": "Photo Sync"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -39,13 +39,9 @@
|
|||||||
"repo": {
|
"repo": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "uri"
|
"format": "uri"
|
||||||
},
|
|
||||||
"title": {
|
|
||||||
"type": "string",
|
|
||||||
"maxLength": 50
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["type", "name", "short_desc", "desc", "title"]
|
"required": ["type", "name", "short_desc", "desc"]
|
||||||
},
|
},
|
||||||
"project": {
|
"project": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
:experimental:
|
:experimental:
|
||||||
:docdatetime: 2022-10-18T17:56:27+02:00
|
:docdatetime: 2022-08-10T17:09:32+02:00
|
||||||
|
|
||||||
= Terminal
|
= c0ntroller.de
|
||||||
|
|
||||||
Hello and welcome to my website. This documentation is for the https://c0ntroller.de/terminal[cli on my website] so check it out if you haven't!
|
Hello and welcome to my website.
|
||||||
|
|
||||||
== Why did I do this?
|
== Why did I do this?
|
||||||
Mainly because of boredom and because I like to code.
|
Mainly because of boredom and because I like to code.
|
||||||
@ -26,15 +26,10 @@ It seemed not too hard to make, as it consists of an input field and a log/histo
|
|||||||
|
|
||||||
But I wanted more. I wanted the code to be as modular as possible, so it's easy in the future to add commands, project logs, and components. Also, I wanted some appealing features like tab completion and shortcuts.
|
But I wanted more. I wanted the code to be as modular as possible, so it's easy in the future to add commands, project logs, and components. Also, I wanted some appealing features like tab completion and shortcuts.
|
||||||
|
|
||||||
But as it is hard to show a CLI to friends who don't know computer science or an employer, I decided a "normal" frontend should be added.
|
|
||||||
|
|
||||||
==== Implementing all the Stuff
|
==== Implementing all the Stuff
|
||||||
As you can imagine, it was not easy to implement all the features I had imagined. But I'm pretty confident I'm on the right track now. +
|
As you can imagine, it was not easy to implement all the features I had imagined. But I'm pretty confident I'm on the right track now. +
|
||||||
The commands are all contained in one file, and one can easily add or remove them, add flags and other attributes and change the function called when the command is requested. +
|
The commands are all contained in one file, and one can easily add or remove them, add flags and other attributes and change the function called when the command is requested. +
|
||||||
The project files are contained in a separate repository and folder on my server, which is just used as a Docker volume. This means they can be updated without rebuilding the entire project.
|
The project files are contained in a separate repository and folder on my server, which is just used as a Docker volume. This means they can be updated without rebuilding the entire project.
|
||||||
|
|
||||||
After the CLI website was done, it was my main homepage for a few months.
|
|
||||||
Then that I created the "normal" part which basically is a blog and my portfolio.
|
|
||||||
|
|
||||||
==== Autodeployment
|
==== Autodeployment
|
||||||
I like automatization, so I use a CI/CD pipeline.
|
I like automatization, so I use a CI/CD pipeline.
|
||||||
@ -54,7 +49,7 @@ One day I have a good thought (At least I _think_ it's good...) and add an issue
|
|||||||
|
|
||||||
[.line-through]#Probably I should start by adding a https://json-schema.org/[JSON schema] for the project list.# Thats done!
|
[.line-through]#Probably I should start by adding a https://json-schema.org/[JSON schema] for the project list.# Thats done!
|
||||||
|
|
||||||
== CLI Shortcuts
|
== Shortcuts
|
||||||
I talked about shortcuts before, but here's a list of which shortcuts are possible:
|
I talked about shortcuts before, but here's a list of which shortcuts are possible:
|
||||||
|
|
||||||
[cols="1,4"]
|
[cols="1,4"]
|
||||||
@ -67,12 +62,12 @@ I talked about shortcuts before, but here's a list of which shortcuts are possib
|
|||||||
|kbd:[▲] / kbd:[▼]
|
|kbd:[▲] / kbd:[▼]
|
||||||
|Scroll through last commands.
|
|Scroll through last commands.
|
||||||
|
|
||||||
|kbd:[Ctrl+L]
|
|kbd:[Strg+L]
|
||||||
|Clears the history. +
|
|Clears the history. +
|
||||||
Similar to `clear`.
|
Similar to `clear`.
|
||||||
|
|
||||||
|kbd:[Ctrl+D]
|
|kbd:[Strg+D]
|
||||||
|Exits the page. If that doesn't work (https://developer.mozilla.org/en-US/docs/Web/API/Window/close[JavaScript restriction]) it goes back in page history. +
|
|Exits the page. Don't work in (most?) cases because of a https://developer.mozilla.org/en-US/docs/Web/API/Window/close[JavaScript restriction]. +
|
||||||
Similar to `exit`.
|
Similar to `exit`.
|
||||||
|
|
||||||
|kbd:[Ctrl+U]/ +
|
|kbd:[Ctrl+U]/ +
|
||||||
@ -84,12 +79,11 @@ kbd:[Ctrl+C]
|
|||||||
|===
|
|===
|
||||||
|
|
||||||
== Some Stuff I'm Proud of
|
== Some Stuff I'm Proud of
|
||||||
- Every line in the cli history window is parsed in a custom format.
|
- Every line in the history window is parsed in a custom format.
|
||||||
* `%{command}` is parsed to a clickable command
|
* `%{command}` is parsed to a clickable command
|
||||||
* `#{link text|url}` is parsed to a link
|
* `#{link text|url}` is parsed to a link
|
||||||
- Project logs are loaded dynamically. They can be updated at any time.
|
- Project logs are loaded dynamicly. They can be updated at any time.
|
||||||
* But they are rendered in the backend. For the main site no JS is necessary!
|
- There are lots of eastereggs. Some are for specfic people, some for me and some for fun.
|
||||||
- There are lots of eastereggs. Some are for specific people, some for me and some for fun.
|
|
||||||
- I made some custom annotations for code blocks show faulty code (wrong syntax/will not compile/etc.).
|
- I made some custom annotations for code blocks show faulty code (wrong syntax/will not compile/etc.).
|
||||||
|
|
||||||
[source.notCompiling, rust]
|
[source.notCompiling, rust]
|
@ -1,5 +1,5 @@
|
|||||||
:experimental:
|
:experimental:
|
||||||
:docdatetime: 2022-10-18T17:56:27+02:00
|
:docdatetime: 2022-07-29T11:27:37+02:00
|
||||||
|
|
||||||
= Overleaf Sync with Git
|
= Overleaf Sync with Git
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ But how to use them?
|
|||||||
|
|
||||||
== Access granted
|
== Access granted
|
||||||
|
|
||||||
I noticed the front end uses session IDs for user authentication.
|
I noticed the front end uses session IDs for user authentification.
|
||||||
You get an ID, you POST valid credentials (and a CSRF token) to `/login` and your session ID get's "verified".
|
You get an ID, you POST valid credentials (and a CSRF token) to `/login` and your session ID get's "verified".
|
||||||
|
|
||||||
Using their repository, it was easy to find other routes that are useable.
|
Using their repository, it was easy to find other routes that are useable.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:experimental:
|
:experimental:
|
||||||
:docdatetime: 2022-10-18T17:56:27+02:00
|
:docdatetime: 2022-08-08T12:19:20+02:00
|
||||||
|
|
||||||
= Simple Callback Server
|
= Simple Callback Server
|
||||||
|
|
||||||
@ -12,12 +12,12 @@ Still, I needed it sometimes and I didn't want to rewrite it every time I use it
|
|||||||
|
|
||||||
== What can it be used for?
|
== What can it be used for?
|
||||||
|
|
||||||
When creating a dev application on Google, Spotify, or other services you often have some heavy authentication flow to get access.
|
When creating a dev application on Google, Spotify, or other services you often have some heavy authentification flow to get access.
|
||||||
But normally I want to use the API for private projects and it's _my_ account that gets authenticated every time.
|
But normally I want to use the API for private projects and it's _my_ account that gets authenticated every time.
|
||||||
|
|
||||||
To make reauthentication easier these OAuth protocols often provide a "refresh token" which can be used to get a valid new token.
|
To make reauthentication easier these OAuth protocols often provide a "refresh token" which can be used to get a valid new token.
|
||||||
|
|
||||||
To get the initial authentication token and to get such a refresh token you provide a callback address where you get redirected after the user logs in.
|
To get the initial authentification token and to get such a refresh token you provide a callback address where you get redirected after the user logs in.
|
||||||
The tokens and meta information normally are sent in a `POST` body.
|
The tokens and meta information normally are sent in a `POST` body.
|
||||||
And this is where this small application is necessary.
|
And this is where this small application is necessary.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user