Skip to content

Commit e5f2287

Browse files
committed
fix build docs
1 parent f6bf88d commit e5f2287

File tree

10 files changed

+127
-58
lines changed

10 files changed

+127
-58
lines changed

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"rust-analyzer.cargo.features": [
3+
"generating_convert"
4+
]
5+
}

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "vkey"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
edition = "2024"
55
description = "Virtual Keycodes of Windows, Linux, and MacOS"
66
documentation = "https://docs.rs/vkey"
@@ -56,6 +56,8 @@ windows = ["dep:windows"]
5656
enigo = ["dep:enigo"]
5757
dep_all = ["windows", "macos", "xkeysym"]
5858

59+
generating_convert = []
60+
5961
full = [ "target_all", "mirror_all", "feat_all", "dep_all" ]
6062

6163
[build-dependencies]

build.rs

Lines changed: 108 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::borrow::Cow;
1+
use std::{borrow::Cow, path::Path};
22

3-
#[expect(unused)]
43
struct Line<S> {
54
pub hut: S,
65
pub winput: S,
@@ -73,63 +72,126 @@ fn gen_convert<S1: AsRef<str>, S2: AsRef<str>, I: IntoIterator<Item = (S1, S2)>>
7372
format!("// This file is auto-generated. Do not edit manually.\n\n{}", generated_code)
7473
}
7574

76-
fn main() {
77-
let csv_path = "src/keycodes/convert/convert.csv";
78-
let output_path = "src/keycodes/convert/";
7975

80-
let csv_content = std::fs::read_to_string(csv_path).expect("Failed to read convert.csv");
81-
let csv = csv_content.lines().filter(|i| !i.trim().is_empty())
82-
.map(|i| i.split(',').collect::<Vec<_>>().into()).collect::<Vec<Line<_>>>();
76+
#[expect(unused)]
77+
#[derive(Debug, Clone, Copy)]
78+
enum KeyType {
79+
HUT, Winput, WinVk, VkValue, HutKeyboardValue, Enigo, KeySym, CG,
80+
}
8381

84-
fn is_valid<S: AsRef<str>>(s: S) -> bool {
85-
let s = s.as_ref().trim();
86-
!s.is_empty() && !s.starts_with("n!") && !s.starts_with("na!") && !s.starts_with("todo!") && !s.starts_with("none!")
82+
impl KeyType {
83+
pub fn name(self) -> &'static str {
84+
match self {
85+
KeyType::HUT => "Usage",
86+
KeyType::Winput => "Vk",
87+
KeyType::WinVk => "Vk",
88+
KeyType::VkValue => unimplemented!(),
89+
KeyType::HutKeyboardValue => unimplemented!(),
90+
KeyType::Enigo => "Enigo",
91+
KeyType::KeySym => "KeySym",
92+
KeyType::CG => "CGKeyCode",
93+
}
8794
}
88-
fn kv_is_valid<K: AsRef<str>, V: AsRef<str>>((k, v): &(K, V)) -> bool {
89-
is_valid(k) && is_valid(v) && !k.as_ref().trim().ends_with('*')
95+
96+
pub fn get_line<'a>(self, line: &'a Line<&'a str>) -> &'a str {
97+
match self {
98+
KeyType::HUT => line.hut,
99+
KeyType::Winput => line.winput,
100+
KeyType::WinVk => line.vk,
101+
KeyType::VkValue => line.vk_value,
102+
KeyType::HutKeyboardValue => line.hut_keyboard_value,
103+
KeyType::Enigo => line.enigo,
104+
KeyType::KeySym => line.keysym,
105+
KeyType::CG => line.cg,
106+
}
90107
}
91108

92-
std::fs::write(
93-
format!("{output_path}generated.winput_to_hut.rs"),
94-
gen_convert(
95-
&gen_template(CONVERT_GENERAL, "Vk", "Usage", None, Some(".usage()")),
96-
csv.iter().map(|i| (i.winput, i.hut)).filter(kv_is_valid)
97-
)
98-
).expect("Failed to write generated.rs");
109+
pub fn as_value_prefix(self) -> Option<&'static str> {
110+
match self {
111+
KeyType::WinVk => Some("keys::"),
112+
_ => None,
113+
}
114+
}
99115

116+
pub fn as_value_suffix(self) -> Option<&'static str> {
117+
match self {
118+
KeyType::HUT => Some(".usage()"),
119+
KeyType::CG => Some(".into()"),
120+
_ => None
121+
}
122+
}
123+
}
100124

101-
std::fs::write(
102-
format!("{output_path}generated.winput_to_enigo.rs"),
103-
gen_convert(
104-
&gen_template(CONVERT_GENERAL, "Vk", "Enigo", None, None),
105-
csv.iter().map(|i| (i.winput, i.enigo)).filter(kv_is_valid)
106-
)
107-
).expect("Failed to write generated.rs");
125+
fn is_valid<S: AsRef<str>>(s: S) -> bool {
126+
let s = s.as_ref().trim();
127+
!s.is_empty() && !s.starts_with("n!") && !s.starts_with("na!") && !s.starts_with("todo!") && !s.starts_with("none!")
128+
}
129+
fn kv_is_valid<K: AsRef<str>, V: AsRef<str>>((k, v): &(K, V)) -> bool {
130+
is_valid(k) && is_valid(v) && !k.as_ref().trim().ends_with('*')
131+
}
108132

109-
std::fs::write(
110-
format!("{output_path}generated.enigo_to_winput.rs"),
111-
gen_convert(
112-
&gen_template(CONVERT_GENERAL, "Enigo", "Vk", None, None),
113-
csv.iter().map(|i| (i.enigo, i.winput)).filter(kv_is_valid)
114-
)
115-
).expect("Failed to write generated.rs");
133+
struct Gen(KeyType, KeyType);
116134

117-
std::fs::write(
118-
format!("{output_path}generated.enigo_to_vk.rs"),
135+
impl Gen {
136+
pub fn build(self, csv: &[Line<&str>]) -> String {
137+
let from = self.0;
138+
let to = self.1;
119139
gen_convert(
120-
&gen_template(CONVERT_GENERAL, "Enigo", "Vk", Some("keys::"), None),
121-
csv.iter().map(|i| (i.enigo, i.vk)).filter(kv_is_valid)
140+
&gen_template(CONVERT_GENERAL, from.name(), to.name(), to.as_value_prefix(), to.as_value_suffix()),
141+
csv.iter().map(|i| (from.get_line(i), to.get_line(i))).filter(kv_is_valid)
122142
)
123-
).expect("Failed to write generated.rs");
143+
}
144+
}
124145

125-
std::fs::write(
126-
format!("{output_path}generated.winput_to_macos.rs"),
127-
gen_convert(
128-
&gen_template(CONVERT_GENERAL, "Vk", "CGKeyCode", None, Some(".into()")),
129-
csv.iter().map(|i| (i.winput, i.cg)).filter(kv_is_valid)
130-
)
131-
).expect("Failed to write generated.rs");
146+
fn save_file<P: AsRef<Path>, S: AsRef<str>>(filename: P, content: S) -> std::io::Result<()> {
147+
let filename = filename.as_ref();
148+
let content = content.as_ref();
149+
let path = filename.to_path_buf();
150+
if content.is_empty() {
151+
return Err(std::io::Error::other("Content is empty"));
152+
}
153+
if path.exists() && !path.is_file() {
154+
return Err(std::io::Error::other(format!("{} is not a file", filename.display())));
155+
}
156+
if path.exists() && !content.is_empty() {
157+
let existing_content = std::fs::read_to_string(&path)?;
158+
if existing_content == content {
159+
return Ok(());
160+
}
161+
}
162+
std::fs::write(path, content)
163+
}
164+
165+
fn main() {
166+
let csv_path = "src/keycodes/convert/convert.csv";
167+
let output_path = "src/keycodes/convert";
168+
169+
if std::env::var("DOCS_RS").is_ok() {
170+
return;
171+
}
132172

133173
println!("cargo:rerun-if-changed=build.rs");
134174
println!("cargo:rerun-if-changed={csv_path}");
175+
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_GENERATING_CONVERT");
176+
if std::env::var("CARGO_FEATURE_GENERATING_CONVERT").is_err() {
177+
return;
178+
}
179+
180+
let csv_content = std::fs::read_to_string(csv_path).expect("Failed to read convert.csv");
181+
let csv = csv_content.lines().filter(|i| !i.trim().is_empty())
182+
.map(|i| i.split(',').collect::<Vec<_>>().into()).collect::<Vec<Line<_>>>();
183+
184+
for tuple in [
185+
(KeyType::Enigo, KeyType::WinVk),
186+
(KeyType::Enigo, KeyType::Winput),
187+
(KeyType::Winput, KeyType::HUT),
188+
(KeyType::Winput, KeyType::Enigo),
189+
(KeyType::Winput, KeyType::CG),
190+
] {
191+
let (from, to) = tuple;
192+
let filename = format!("generated.{from:?}_to_{to:?}.rs");
193+
let content = Gen(from, to).build(&csv);
194+
save_file(format!("{output_path}/{filename}"), content)
195+
.expect("Failed to write generated.rs");
196+
}
135197
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

src/keycodes/convert/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,21 @@ mod generated_winput_to_hut {
3434
3535
use crate::keycodes::vk::Vk;
3636
use hut::{AsUsage, Button, Consumer, GenericDesktop, KeyboardKeypad, Usage};
37-
include!("generated.winput_to_hut.rs");
37+
include!("generated.Winput_to_HUT.rs");
3838
}
3939

4040
mod generated_winput_to_enigo {
4141
#[cfg(all(feature = "mirror_winput_vk", feature = "mirror_enigo"))]
4242
mod mirror_to_mirror {
4343
use crate::keycodes::winput::Vk;
4444
use crate::keycodes::enigo::Key as Enigo;
45-
include!("generated.winput_to_enigo.rs");
45+
include!("generated.Winput_to_Enigo.rs");
4646
}
4747
#[cfg(all(feature = "mirror_winput_vk", feature = "enigo", target_os = "windows"))]
4848
mod mirror_to_dep {
4949
use crate::keycodes::winput::Vk;
5050
use ::enigo::Key as Enigo;
51-
include!("generated.winput_to_enigo.rs");
51+
include!("generated.Winput_to_Enigo.rs");
5252
}
5353
}
5454

@@ -57,13 +57,13 @@ mod generated_enigo_to_winput {
5757
mod mirror_to_mirror {
5858
use crate::keycodes::enigo::Key as Enigo;
5959
use crate::keycodes::winput::Vk;
60-
include!("generated.enigo_to_winput.rs");
60+
include!("generated.Enigo_to_Winput.rs");
6161
}
6262
#[cfg(all(feature = "enigo", feature = "mirror_winput_vk", target_os = "windows"))]
6363
mod dep_to_mirror {
6464
use ::enigo::Key as Enigo;
6565
use crate::keycodes::winput::Vk;
66-
include!("generated.enigo_to_winput.rs");
66+
include!("generated.Enigo_to_Winput.rs");
6767

6868
}
6969
}
@@ -73,25 +73,25 @@ mod generated_enigo_to_vk {
7373
mod mirror_to_mirror {
7474
use crate::keycodes::enigo::Key as Enigo;
7575
use crate::keycodes::windows::{self as keys, VIRTUAL_KEY as Vk};
76-
include!("generated.enigo_to_vk.rs");
76+
include!("generated.Enigo_to_WinVk.rs");
7777
}
7878
#[cfg(all(feature = "enigo", feature = "mirror_windows_vk", target_os = "windows"))]
7979
mod dep_to_mirror {
8080
use ::enigo::Key as Enigo;
8181
use crate::keycodes::windows::{self as keys, VIRTUAL_KEY as Vk};
82-
include!("generated.enigo_to_vk.rs");
82+
include!("generated.Enigo_to_WinVk.rs");
8383
}
8484
#[cfg(all(feature = "mirror_enigo", feature = "windows", target_os = "windows"))]
8585
mod mirror_to_dep {
8686
use crate::keycodes::enigo::Key as Enigo;
8787
use ::windows::Win32::UI::Input::KeyboardAndMouse::{self as keys, VIRTUAL_KEY as Vk};
88-
include!("generated.enigo_to_vk.rs");
88+
include!("generated.Enigo_to_WinVk.rs");
8989
}
9090
#[cfg(all(feature = "enigo", feature = "windows", target_os = "windows"))]
9191
mod dep_to_dep {
9292
use ::enigo::Key as Enigo;
9393
use ::windows::Win32::UI::Input::KeyboardAndMouse::{self as keys, VIRTUAL_KEY as Vk};
94-
include!("generated.enigo_to_vk.rs");
94+
include!("generated.Enigo_to_WinVk.rs");
9595
}
9696
}
9797

@@ -105,7 +105,7 @@ mod generated_winput_to_cg {
105105
#[cfg(feature = "mirror_macos")]
106106
use crate::keycodes::macos::KeyCode;
107107
use crate::keycodes::macos_ext::{CGKeyCode, KeyCodeExt};
108-
include!("generated.winput_to_macos.rs");
108+
include!("generated.Winput_to_CG.rs");
109109
}
110110
}
111111

0 commit comments

Comments
 (0)