1const DATABROWSER: &str = "org.csstudio.trends.databrowser2.newWindow";
7
8pub fn databrowser_pvs(script: &str) -> Option<Vec<String>> {
20 if !script.contains(DATABROWSER) {
21 return None;
22 }
23 let call = &script[script.find("executeEclipseCommand")?..];
24 let key = call.find("pvnames")?;
26 let rest = call[key + "pvnames".len()..]
27 .trim_start_matches(['\'', '"'])
28 .trim_start();
29 let rest = rest.strip_prefix(',')?.trim_start();
30 let quote = rest.chars().next().filter(|c| matches!(c, '\'' | '"'))?;
31 let body = &rest[1..];
32 let names = &body[..body.find(quote)?];
33 let pvs: Vec<String> = names
34 .split(',')
35 .map(str::trim)
36 .filter(|n| !n.is_empty())
37 .map(str::to_string)
38 .collect();
39 (!pvs.is_empty()).then_some(pvs)
40}
41
42const STRIP_TOOLS: &[&str] = &["strip.py", "strip.sh", "buildStripToolconfig.sh"];
44
45pub fn strip_tool_pvs(command: &str) -> Option<Vec<String>> {
50 let mut words = command.split_whitespace();
51 let program = words.next()?;
52 let name = program.rsplit('/').next().unwrap_or(program);
53 if !STRIP_TOOLS.contains(&name) {
54 return None;
55 }
56 let mut pvs: Vec<String> = words.map(str::to_string).collect();
57 if pvs.last().is_some_and(|w| !w.contains(':')) {
58 pvs.pop();
59 }
60 (!pvs.is_empty()).then_some(pvs)
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn databrowser_scripts_name_their_pvs() {
69 let py = "from org.csstudio.opibuilder.scriptUtil import ScriptUtil\n\n\
71 command_id=\"org.csstudio.trends.databrowser2.newWindow\"\n\
72 ScriptUtil.executeEclipseCommand(command_id, ['pvnames', \
73 '$(dom)-VA-GAUGE-01:PLOG,$(dom)-VA-GAUGE-02:PLOG, $(dom)-VA-GAUGE-03:PLOG'])";
74 assert_eq!(
75 databrowser_pvs(py).unwrap(),
76 [
77 "$(dom)-VA-GAUGE-01:PLOG",
78 "$(dom)-VA-GAUGE-02:PLOG",
79 "$(dom)-VA-GAUGE-03:PLOG"
80 ]
81 );
82 let js = "ScriptUtil.executeEclipseCommand(\"org.csstudio.trends.databrowser2.newWindow\", \
83 [\"pvnames\", \"A:B\"]);";
84 assert_eq!(databrowser_pvs(js).unwrap(), ["A:B"]);
85 let other = "ScriptUtil.executeEclipseCommand(\"org.csstudio.other\", ['pvnames', 'A'])";
87 assert_eq!(databrowser_pvs(other), None);
88 assert_eq!(
89 databrowser_pvs("ScriptUtil.closeAssociatedOPI(widget)"),
90 None
91 );
92 let empty = format!("ScriptUtil.executeEclipseCommand(\"{DATABROWSER}\", ['pvnames', ''])");
93 assert_eq!(databrowser_pvs(&empty), None);
94 }
95
96 #[test]
97 fn strip_tool_commands_name_their_pvs() {
98 assert_eq!(
99 strip_tool_pvs("strip.py $(device):PLOG log_mbar").unwrap(),
100 ["$(device):PLOG"]
101 );
102 assert_eq!(
103 strip_tool_pvs("buildStripToolconfig.sh SR04S-VA-GAUGE-01:PLOG SR04S-VA-GAUGE-03:PLOG")
104 .unwrap(),
105 ["SR04S-VA-GAUGE-01:PLOG", "SR04S-VA-GAUGE-03:PLOG"]
106 );
107 assert_eq!(
108 strip_tool_pvs("/dls_sw/prod/tools/strip.sh BL01T:A:M2 BL01T:A:M4 log_mbar").unwrap(),
109 ["BL01T:A:M2", "BL01T:A:M4"]
110 );
111 assert_eq!(strip_tool_pvs("strip.py log_mbar"), None);
112 assert_eq!(strip_tool_pvs("./srCellVacuum 04"), None);
113 assert_eq!(strip_tool_pvs("mystrip.py A:B"), None);
114 assert_eq!(strip_tool_pvs(""), None);
115 }
116}