mirror of
https://github.com/nicoburns/blessed-rs
synced 2024-11-26 21:50:20 +00:00
Begin writing getting started guide
This commit is contained in:
parent
80d3bb517f
commit
325dbf2a6e
7 changed files with 195 additions and 0 deletions
32
data/editors.json
Normal file
32
data/editors.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "VS Code",
|
||||||
|
"url": "https://code.visualstudio.com/",
|
||||||
|
"editor_plugins": "Rust Analyzer (note: avoid the \"Rust\" plugin. It is in the process of being deprecated and has a number of issues that are solved in the new Rust Analyzer plugin)",
|
||||||
|
"notes": "Generally recommended"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Intellij/CLion",
|
||||||
|
"url": "https://www.jetbrains.com/rust/",
|
||||||
|
"editor_plugins": "Rust Plugin",
|
||||||
|
"notes": "Well supported. A good option if you like Intellij products."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sublime Text",
|
||||||
|
"url": "https://www.sublimetext.com/",
|
||||||
|
"editor_plugins": "sublime-lsp and lsp-rust-analyzer plugins",
|
||||||
|
"notes": "Well supported. A good option if you like Intellij products."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vim/NeoVim",
|
||||||
|
"url": "https://neovim.io/",
|
||||||
|
"editor_plugins": "TBD",
|
||||||
|
"notes": "If you know you know. Not recommended for beginners."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Emacs",
|
||||||
|
"url": "https://www.gnu.org/software/emacs/",
|
||||||
|
"editor_plugins": "TBD",
|
||||||
|
"notes": "If you know you know. Not recommended for beginners."
|
||||||
|
}
|
||||||
|
]
|
|
@ -25,6 +25,7 @@ async fn main() {
|
||||||
.route("/", get(|| async { Redirect::to("/crates") }))
|
.route("/", get(|| async { Redirect::to("/crates") }))
|
||||||
.route("/users", post(routes::users::create::run))
|
.route("/users", post(routes::users::create::run))
|
||||||
.route("/crates", get(routes::crates::list::run))
|
.route("/crates", get(routes::crates::list::run))
|
||||||
|
.route("/getting-started", get(routes::getting_started::guide::run))
|
||||||
.nest("/static", static_file_service)
|
.nest("/static", static_file_service)
|
||||||
.layer(TraceLayer::new_for_http());
|
.layer(TraceLayer::new_for_http());
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod users;
|
pub mod users;
|
||||||
pub mod crates;
|
pub mod crates;
|
||||||
|
pub mod getting_started;
|
||||||
|
|
||||||
// basic handler that responds with a static string
|
// basic handler that responds with a static string
|
||||||
pub async fn index() -> &'static str {
|
pub async fn index() -> &'static str {
|
||||||
|
|
55
src/routes/getting_started/guide.rs
Normal file
55
src/routes/getting_started/guide.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use axum::{
|
||||||
|
http::StatusCode,
|
||||||
|
response::{ IntoResponse, Html },
|
||||||
|
};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
use serde_json;
|
||||||
|
use tera::Context;
|
||||||
|
use crate::templates::{ TERA, TocSection, TocSubSection };
|
||||||
|
|
||||||
|
pub(crate) async fn run() -> impl IntoResponse {
|
||||||
|
|
||||||
|
// Load editor data
|
||||||
|
let data_file_contents : &str = include_str!("../../../data/editors.json");
|
||||||
|
let editors : Vec<Editor> = serde_json::from_str(&data_file_contents).unwrap();
|
||||||
|
|
||||||
|
let toc_sections = vec![
|
||||||
|
TocSection { name: "Installation".into(), slug: "installation".into(), subsections: vec![
|
||||||
|
TocSubSection { name: "Rustup".into(), slug: "cargo-rustc".into() },
|
||||||
|
TocSubSection { name: "Editor Setup".into(), slug: "editor-setup".into() },
|
||||||
|
TocSubSection { name: "Cargo Plugins".into(), slug: "cargo-plugins".into() },
|
||||||
|
]},
|
||||||
|
TocSection { name: "Learning Resources".into(), slug: "learning-resources".into(), subsections: vec![
|
||||||
|
TocSubSection { name: "Books".into(), slug: "books".into() },
|
||||||
|
TocSubSection { name: "Crate Discovery".into(), slug: "crate-discovery".into() },
|
||||||
|
TocSubSection { name: "Community Updates".into(), slug: "community-updates".into() },
|
||||||
|
TocSubSection { name: "Asking for help".into(), slug: "help".into() },
|
||||||
|
]}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Render template
|
||||||
|
let mut context = Context::new();
|
||||||
|
context.insert("editors", &editors);
|
||||||
|
context.insert("toc_sections", &toc_sections);
|
||||||
|
let rendered = TERA.render("routes/getting_started/guide.html", &context);
|
||||||
|
|
||||||
|
// Handle template rendering errors
|
||||||
|
let res = match rendered {
|
||||||
|
Ok(res) => (StatusCode::OK, Html(res)),
|
||||||
|
Err(err) => {
|
||||||
|
tracing::debug!("Error: {:?}", err);
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, Html(format!("<code><pre>{:#?}</pre></code>", err)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return response
|
||||||
|
(StatusCode::OK, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
struct Editor {
|
||||||
|
name: String,
|
||||||
|
url: String,
|
||||||
|
editor_plugins: String,
|
||||||
|
notes: String,
|
||||||
|
}
|
1
src/routes/getting_started/mod.rs
Normal file
1
src/routes/getting_started/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod guide;
|
|
@ -105,6 +105,21 @@ p.introduction {
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p, li {
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content ul {
|
||||||
|
max-width: 800px;
|
||||||
|
padding-left: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content li {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
90
templates/routes/getting_started/guide.html
Normal file
90
templates/routes/getting_started/guide.html
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% import "macros/toc.html" as toc %}
|
||||||
|
{% block title %}Crate List{% endblock title %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
<style type="text/css">
|
||||||
|
.important { color: #336699; }
|
||||||
|
</style>
|
||||||
|
{% endblock head %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<div class="hflex">
|
||||||
|
|
||||||
|
{{ toc::left_sidebar(sections=toc_sections) }}
|
||||||
|
|
||||||
|
<!-- Main page content -->
|
||||||
|
<div id="content">
|
||||||
|
|
||||||
|
<section data-toc-section id="section-installation">
|
||||||
|
<h3>Installation</h3>
|
||||||
|
<p class="group-description"></p>
|
||||||
|
<section data-toc-section id="section-installation-subsection-cargo-rustc">
|
||||||
|
<h4>Rustup</h4>
|
||||||
|
<p class="introduction">
|
||||||
|
Compared to other programming languages such as Python and Go, Rust's standard library is very small, including only core data structures in the standard library with all other functionality farmed out to 3rd party ecosystem crates, and a common complaint from new Rust developers is that they don't know where to start: which crates they ought to use and which crates they ought to trust.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section data-toc-section id="section-learning-resources">
|
||||||
|
<h3>Learning Resources</h3>
|
||||||
|
<p class="group-description"></p>
|
||||||
|
|
||||||
|
<section data-toc-section id="section-learning-resources-subsection-books">
|
||||||
|
<h4>Books</h4>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<b><a href="https://doc.rust-lang.org/book/">The Rust Programming Language</a></b>
|
||||||
|
The official rust-lang book. Aimed at those with experience in another programming language but not
|
||||||
|
necessarily a low-level one. This is also the best option if you are trying to learn Rust as your first programming language. Freely available online (a print version is also available)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b><a href="https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/">Programming Rust</a></b>
|
||||||
|
Another book aimed at those with experience in another programming language, but not
|
||||||
|
necessarily a low-level one. While the official book above has a stellar reputation, this one has a reputation for being even better,
|
||||||
|
diving deeper and giving a more thorough introduction to the language. The downside being it's not free.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b><a href="https://www.rustinaction.com/">Rust in action</a></b>
|
||||||
|
This one has a slightly different focus, and is more suited to the more experienced developer with some grasp of CS theory, or those coming from a background in C or C++. It takes the reader through some relatively advanced projects including a CPU emulator, database, and an OS kernel.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<b><a href="https://nostarch.com/rust-rustaceans">Rust for Rustaceans</a></b>
|
||||||
|
A more advanced book that dives into some of the more involved parts of Rust. Not suitable for a complete beginner (even if they have experience in other languages). Best read after you have already learnt some basic Rust through one or more of the other resources.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock main %}
|
||||||
|
|
||||||
|
{% block footer %}
|
||||||
|
<script>
|
||||||
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(entries => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
const id = entry.target.getAttribute('id');
|
||||||
|
if (entry.intersectionRatio > 0) {
|
||||||
|
document.querySelector(`li[data-toc-link="${id}"]`).classList.add('active');
|
||||||
|
} else {
|
||||||
|
document.querySelector(`li[data-toc-link="${id}"]`).classList.remove('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Track all sections that have an `id` applied
|
||||||
|
document.querySelectorAll('section[data-toc-section]').forEach((section) => {
|
||||||
|
observer.observe(section);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock footer %}
|
Loading…
Reference in a new issue