sync_code/
lib.rs

1//! Synchronize code blocks between different files.
2//!
3//! It can replace `macros` in certain scenarios.
4//! For example, when your code isn’t duplicated many times but the design is
5//! relatively complex (e.g., involving generics), using `sync-code` instead
6//! of a `macro` will give you much better readability and easier maintenance.
7//! Features like Go-to-definition and intelligent auto-completion also work
8//! properly without using `macros`.
9//!
10//! # Usage
11//! Run command:
12//! ```shell
13//! cargo add --build sync-code
14//! ```
15//!
16//! `build.rs`:
17//! ```ignore
18//! fn main() {
19//!     sync_code::Builder::new()
20//!         .add("src/target1.rs", "src/source1.rs")
21//!         .add("src/target2.rs", "src/source2.rs")
22//!         .sync();
23//! }
24//!
25//! ```
26//!
27//! `your_code.rs`:
28//! ```rust
29//! // $sync block_name
30//!
31//! fn code_you_want_to_sync() {
32//! }
33//!
34//! // $sync end
35//! ```
36
37#![allow(clippy::needless_doctest_main)]
38mod sync;
39
40use std::path::Path;
41use sync::Sync;
42
43#[derive(Default)]
44pub struct Builder {
45    table: Vec<Sync>,
46    file_list: Vec<String>,
47}
48
49impl Builder {
50    pub fn new() -> Self {
51        Self::default()
52    }
53
54    pub fn add<P: AsRef<Path>>(mut self, file: P, dep_file: P) -> Self {
55        self.file_list.push(file.as_ref().display().to_string());
56        self.file_list.push(dep_file.as_ref().display().to_string());
57
58        self.table.push(Sync::new(
59            file.as_ref().to_path_buf(),
60            dep_file.as_ref().to_path_buf(),
61        ));
62        self
63    }
64
65    pub fn sync(&mut self) {
66        for sync in &self.table {
67            sync.sync();
68        }
69
70        self.file_list.dedup();
71        for file in &self.file_list {
72            println!("cargo:rerun-if-changed={}", file);
73        }
74    }
75}