feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support: - Splash screen on boot (1.5s) with project name, version, board - Dashboard showing radio state, config, counters, RSSI/SNR - RSSI history sparkline (64-sample ring buffer, 2px-wide bars) - DisplayOn/DisplayOff host commands routed via dedicated channel - Pure render functions against generic DrawTarget (no hardware coupling) - Display on/off control bypasses radio task entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
17624 files changed
+4564928
-38
No files matched your search
+1
@@ -0,0 +1 @@
|
||||
{"files":{".cargo_vcs_info.json":"ccd628cbfe516145200dbdf5634f604a0bb5d3d7a5b215ea633f6508887a4340",".travis.yml":"2e3d3211e52ff52d83a0a2a495a28175dbcf2a30ab680d7c8f20622751b04f78","CHANGELOG.md":"86f673c2579eacf6bb82331c1feee5269285c2fadcbce8624632b4b979dd5a04","Cargo.toml":"560eba8d5cf4f2c71cc06ef9145eb8f4c163a616cd6d08b031b1eae3448d8203","Cargo.toml.orig":"50fdb950c6ee5187abcbaea7622aaa016e1f9e53d5b35825cfdf7f880fdd1664","LICENSE":"508a77d2e7b51d98adeed32648ad124b7b30241a8e70b2e72c99f92d8e5874d1","README.md":"aaf0fcc62756694c61f26e02c8042a00c19f98c516aa62aa5b4779b5c7956c71","src/lib.rs":"514f0c716fba1e8fbeefc118848655ceafa22fd24787ca28c0e7c2143d5c7175"},"package":"b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"git": {
|
||||
"sha1": "bf0d863e3006b40a0d923a81d7b2dd2db1136c2c"
|
||||
}
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
language: rust
|
||||
env:
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
## v1.0.1 - March 18, 2019
|
||||
- Add `LICENSE` file (#3)[https://github.com/TedDriggs/ident_case/issues/3]
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
authors = ["Ted Driggs <ted.driggs@outlook.com>"]
|
||||
description = "Utility for applying case rules to Rust identifiers."
|
||||
documentation = "https://docs.rs/ident_case/1.0.1"
|
||||
readme = "README.md"
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/TedDriggs/ident_case"
|
||||
[badges.travis-ci]
|
||||
repository = "TedDriggs/ident_case"
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
[](https://travis-ci.org/TedDriggs/ident_case)
|
||||
|
||||
Crate for manipulating case of identifiers in Rust programs.
|
||||
|
||||
# Features
|
||||
* Supports `snake_case`, `lowercase`, `camelCase`,
|
||||
`PascalCase`, `SCREAMING_SNAKE_CASE`, and `kebab-case`
|
||||
* Rename variants, and fields
|
||||
|
||||
# Examples
|
||||
```rust
|
||||
assert_eq!("helloWorld", RenameRule::CamelCase.apply_to_field("hello_world"));
|
||||
|
||||
assert_eq!("i_love_serde", RenameRule::SnakeCase.apply_to_variant("ILoveSerde"));
|
||||
```
|
||||
Vendored
+168
@@ -0,0 +1,168 @@
|
||||
//! Crate for changing case of Rust identifiers.
|
||||
//!
|
||||
//! # Features
|
||||
//! * Supports `snake_case`, `lowercase`, `camelCase`,
|
||||
//! `PascalCase`, `SCREAMING_SNAKE_CASE`, and `kebab-case`
|
||||
//! * Rename variants, and fields
|
||||
//!
|
||||
//! # Examples
|
||||
//! ```rust
|
||||
//! use ident_case::RenameRule;
|
||||
//!
|
||||
//! assert_eq!("helloWorld", RenameRule::CamelCase.apply_to_field("hello_world"));
|
||||
//!
|
||||
//! assert_eq!("i_love_serde", RenameRule::SnakeCase.apply_to_variant("ILoveSerde"));
|
||||
//! ```
|
||||
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::ascii::AsciiExt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use self::RenameRule::*;
|
||||
|
||||
/// A casing rule for renaming Rust identifiers.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum RenameRule {
|
||||
/// No-op rename rule.
|
||||
None,
|
||||
/// Rename direct children to "lowercase" style.
|
||||
LowerCase,
|
||||
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
|
||||
PascalCase,
|
||||
/// Rename direct children to "camelCase" style.
|
||||
CamelCase,
|
||||
/// Rename direct children to "snake_case" style, as commonly used for fields.
|
||||
SnakeCase,
|
||||
/// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
|
||||
ScreamingSnakeCase,
|
||||
/// Rename direct children to "kebab-case" style.
|
||||
KebabCase,
|
||||
}
|
||||
|
||||
impl RenameRule {
|
||||
/// Change case of a `PascalCase` variant.
|
||||
pub fn apply_to_variant<S: AsRef<str>>(&self, variant: S) -> String {
|
||||
|
||||
let variant = variant.as_ref();
|
||||
match *self {
|
||||
None | PascalCase => variant.to_owned(),
|
||||
LowerCase => variant.to_ascii_lowercase(),
|
||||
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
|
||||
SnakeCase => {
|
||||
let mut snake = String::new();
|
||||
for (i, ch) in variant.char_indices() {
|
||||
if i > 0 && ch.is_uppercase() {
|
||||
snake.push('_');
|
||||
}
|
||||
snake.push(ch.to_ascii_lowercase());
|
||||
}
|
||||
snake
|
||||
}
|
||||
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
|
||||
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Change case of a `snake_case` field.
|
||||
pub fn apply_to_field<S: AsRef<str>>(&self, field: S) -> String {
|
||||
|
||||
let field = field.as_ref();
|
||||
match *self {
|
||||
None | LowerCase | SnakeCase => field.to_owned(),
|
||||
PascalCase => {
|
||||
let mut pascal = String::new();
|
||||
let mut capitalize = true;
|
||||
for ch in field.chars() {
|
||||
if ch == '_' {
|
||||
capitalize = true;
|
||||
} else if capitalize {
|
||||
pascal.push(ch.to_ascii_uppercase());
|
||||
capitalize = false;
|
||||
} else {
|
||||
pascal.push(ch);
|
||||
}
|
||||
}
|
||||
pascal
|
||||
}
|
||||
CamelCase => {
|
||||
let pascal = PascalCase.apply_to_field(field);
|
||||
pascal[..1].to_ascii_lowercase() + &pascal[1..]
|
||||
}
|
||||
ScreamingSnakeCase => field.to_ascii_uppercase(),
|
||||
KebabCase => field.replace('_', "-"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for RenameRule {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
|
||||
match rename_all_str {
|
||||
"lowercase" => Ok(LowerCase),
|
||||
"PascalCase" => Ok(PascalCase),
|
||||
"camelCase" => Ok(CamelCase),
|
||||
"snake_case" => Ok(SnakeCase),
|
||||
"SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
|
||||
"kebab-case" => Ok(KebabCase),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RenameRule {
|
||||
fn default() -> Self {
|
||||
RenameRule::None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::RenameRule::*;
|
||||
|
||||
#[test]
|
||||
fn rename_variants() {
|
||||
for &(original, lower, camel, snake, screaming, kebab) in
|
||||
&[
|
||||
("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome"),
|
||||
("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
|
||||
("A", "a", "a", "a", "A", "a"),
|
||||
("Z42", "z42", "z42", "z42", "Z42", "z42"),
|
||||
] {
|
||||
assert_eq!(None.apply_to_variant(original), original);
|
||||
assert_eq!(LowerCase.apply_to_variant(original), lower);
|
||||
assert_eq!(PascalCase.apply_to_variant(original), original);
|
||||
assert_eq!(CamelCase.apply_to_variant(original), camel);
|
||||
assert_eq!(SnakeCase.apply_to_variant(original), snake);
|
||||
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
|
||||
assert_eq!(KebabCase.apply_to_variant(original), kebab);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rename_fields() {
|
||||
for &(original, pascal, camel, screaming, kebab) in
|
||||
&[
|
||||
("outcome", "Outcome", "outcome", "OUTCOME", "outcome"),
|
||||
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty"),
|
||||
("_leading_under", "LeadingUnder", "leadingUnder", "_LEADING_UNDER", "-leading-under"),
|
||||
("double__under", "DoubleUnder", "doubleUnder", "DOUBLE__UNDER", "double--under"),
|
||||
("a", "A", "a", "A", "a"),
|
||||
("z42", "Z42", "z42", "Z42", "z42"),
|
||||
] {
|
||||
assert_eq!(None.apply_to_field(original), original);
|
||||
assert_eq!(PascalCase.apply_to_field(original), pascal);
|
||||
assert_eq!(CamelCase.apply_to_field(original), camel);
|
||||
assert_eq!(SnakeCase.apply_to_field(original), original);
|
||||
assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
|
||||
assert_eq!(KebabCase.apply_to_field(original), kebab);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user