Skip to content

Commit 7af34be

Browse files
feat: scriptslog text highlighting
1 parent e680df4 commit 7af34be

4 files changed

Lines changed: 150 additions & 14 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ path = "src/cli/cli.rs"
1717

1818
[dependencies]
1919
clap = { version = "^3.0", features = ["derive"] }
20-
directories = "4.0"
20+
directories = "4.0"
21+
colored = "2.0"

README.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,41 @@ The main feature of it is to easily recompile game scripts at run time, which ca
88
Parts of this code are based off of `Wolvenkit modding tool` by Traderain, rfuzzo and others
99
https://github.com/WolvenKit/WolvenKit
1010

11+
---
12+
1113

1214
## Usage examples
13-
Tool help
15+
Tool help.
1416
```ps1
1517
rw3d_cli.exe -h
1618
```
1719

18-
Recompile game scripts
20+
Recompile game scripts.
1921
```ps1
2022
rw3d_cli.exe reload
2123
```
2224

23-
Remotely call an exec function from the game
25+
Recompile game scripts and automatically exit the program after the tool doesn't get any responses from the game in the span of 10 seconds after the last response.
26+
```ps1
27+
rw3d_cli.exe --response-timeout=10000 reload
28+
```
29+
30+
Remotely call an exec function from the game. Remember to use quotation marks when passing the argument if it has any spaces in it.
2431
```ps1
25-
rw3d_cli.exe exec additem('Aerondight', 1)
32+
rw3d_cli.exe exec "additem('Aerondight', 1)"
2633
```
2734

28-
Remotely call an exec function from the game without waiting for tool messages or any game response
35+
Remotely call an exec function from the game without waiting for tool messages or any game response.
2936
```ps1
30-
rw3d_cli.exe --no-info-wait --no-listen exec gotoProlog()
37+
rw3d_cli.exe --no-wait --no-listen exec "gotoProlog()"
3138
```
3239

33-
Recompile game scripts and automatically exit the program after the tool doesn't get any responses from the game in the span of 5 seconds after the last response
40+
Get the list of mods installed.
3441
```ps1
35-
rw3d_cli.exe --response-timeout=5000 reload
42+
rw3d_cli.exe modlist
3643
```
44+
45+
Monitor game's scripts log and highlight specific lines. You can set multiple key words to be highlighted with the same color.
46+
```ps1
47+
rw3d_cli.exe scriptslog --yellow="[My mod]" --yellow="[Also my mod]"
48+
```

src/cli/local_subcommands.rs

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,40 @@
11
use std::{thread, time::Duration};
22

3-
use clap::Subcommand;
3+
use clap::{ Parser, Subcommand};
4+
use colored::{Colorize, Color};
45

56
use crate::{input_waiter::input_waiter, CliOptions};
67

78
/// Subcommands that can be executed without connecting to game's socket
89
#[derive(Subcommand)]
910
pub(crate) enum LocalSubcommands {
1011
/// Prints game's script logs onto console
11-
Scriptslog
12+
Scriptslog {
13+
/// Flags for setting highlight colors for lines that contain a certain string
14+
/// Colors inside mean the color of the background of the highlighted line
15+
#[clap(flatten)]
16+
colors: ScriptslogColors
17+
}
18+
}
19+
20+
#[derive(Parser)]
21+
pub(crate) struct ScriptslogColors {
22+
#[clap(long)]
23+
black: Vec<String>,
24+
#[clap(long)]
25+
red: Vec<String>,
26+
#[clap(long)]
27+
green: Vec<String>,
28+
#[clap(long)]
29+
yellow: Vec<String>,
30+
#[clap(long)]
31+
blue: Vec<String>,
32+
#[clap(long)]
33+
magenta: Vec<String>,
34+
#[clap(long)]
35+
cyan: Vec<String>,
36+
#[clap(long)]
37+
white: Vec<String>,
1238
}
1339

1440
pub(crate) fn handle_local_subcommand( cmd: LocalSubcommands, options: CliOptions ) {
@@ -23,10 +49,107 @@ pub(crate) fn handle_local_subcommand( cmd: LocalSubcommands, options: CliOption
2349
if !options.no_wait { thread::sleep( Duration::from_millis(3000) ) }
2450

2551
match cmd {
26-
LocalSubcommands::Scriptslog => {
27-
if let Some(err) = rw3d_core::scriptslog::read_from_scriptslog(|s| print!("{}", s), 1000, logger_rcv) {
52+
LocalSubcommands::Scriptslog { colors } => {
53+
let highlights = scriptslog_colors_to_highlight_records(colors);
54+
if let Some(err) = rw3d_core::scriptslog::tail_scriptslog(|s| scriptslog_printer(s, &highlights), 1000, logger_rcv) {
2855
println!("{}", err);
2956
}
3057
}
3158
}
59+
}
60+
61+
62+
struct ScriptslogHighlightRecord {
63+
pattern: String,
64+
fg: Color,
65+
bg: Color
66+
}
67+
68+
fn scriptslog_colors_to_highlight_records(colors: ScriptslogColors) -> Vec<ScriptslogHighlightRecord> {
69+
let mut colored = Vec::new();
70+
71+
for p in colors.black {
72+
colored.push(ScriptslogHighlightRecord{
73+
pattern: p,
74+
fg: Color::White,
75+
bg: Color::Black
76+
});
77+
}
78+
for p in colors.red {
79+
colored.push(ScriptslogHighlightRecord{
80+
pattern: p,
81+
fg: Color::White,
82+
bg: Color::Red
83+
});
84+
}
85+
for p in colors.green {
86+
colored.push(ScriptslogHighlightRecord{
87+
pattern: p,
88+
fg: Color::Black,
89+
bg: Color::Green
90+
});
91+
}
92+
for p in colors.yellow {
93+
colored.push(ScriptslogHighlightRecord{
94+
pattern: p,
95+
fg: Color::Black,
96+
bg: Color::Yellow
97+
});
98+
}
99+
for p in colors.blue {
100+
colored.push(ScriptslogHighlightRecord{
101+
pattern: p,
102+
fg: Color::White,
103+
bg: Color::Blue
104+
});
105+
}
106+
for p in colors.magenta {
107+
colored.push(ScriptslogHighlightRecord{
108+
pattern: p,
109+
fg: Color::White,
110+
bg: Color::Magenta
111+
});
112+
}
113+
for p in colors.cyan {
114+
colored.push(ScriptslogHighlightRecord{
115+
pattern: p,
116+
fg: Color::Black,
117+
bg: Color::Cyan
118+
});
119+
}
120+
for p in colors.white {
121+
colored.push(ScriptslogHighlightRecord{
122+
pattern: p,
123+
fg: Color::Black,
124+
bg: Color::White
125+
});
126+
}
127+
128+
colored
129+
}
130+
131+
// Just a constant to initialize coloring variables and to signal to not apply any highlighting if this color is detected
132+
// The color chosen is not used anywhere else for that matter
133+
const NO_COLORING_PLACEHOLDER: Color = Color::BrightBlack;
134+
135+
fn scriptslog_printer( t: &String, highlights: &Vec<ScriptslogHighlightRecord> ) {
136+
let lines = t.split("\n");
137+
138+
for line in lines {
139+
let (mut fg, mut bg) = (NO_COLORING_PLACEHOLDER, NO_COLORING_PLACEHOLDER);
140+
141+
for h in highlights {
142+
if line.contains(&h.pattern) {
143+
fg = h.fg;
144+
bg = h.bg;
145+
break;
146+
}
147+
}
148+
149+
if fg != NO_COLORING_PLACEHOLDER {
150+
println!("{}", line.color(fg).on_color(bg));
151+
} else {
152+
println!("{}", line);
153+
}
154+
}
32155
}

src/core/scriptslog.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::constants;
88
/// In case of error will return Some with that error message, otherwise will return None.
99
/// For `printer` parameter you can pass any function or closure that you want to print log text with,
1010
/// the string passed to said printer will consist of one or more lines of text.
11-
pub fn read_from_scriptslog<P>( printer: P, refresh_time_millis: u64, cancel_token: Receiver<()> ) -> Option<String>
11+
pub fn tail_scriptslog<P>( printer: P, refresh_time_millis: u64, cancel_token: Receiver<()> ) -> Option<String>
1212
where P: Fn(&String) -> () {
1313
match scriptslog_file() {
1414
Ok(file) => {

0 commit comments

Comments
 (0)