Skip to main content

qutescript/
env.rs

1use std::env;
2use std::fs::File;
3use std::io::{self, Write};
4use std::path::{Path, PathBuf};
5
6/// The method by which the userscript was launched, either `hints` (started via hints)
7/// or `command` (started via command or key binding).
8#[derive(Clone, Debug)]
9pub enum SpawnMode {
10    /// Indicates that the userscript was started via hints.
11    Hints(HintsVars),
12    /// Indicates that the userscript was started via command or key binding.
13    Command(CommandVars),
14}
15
16const MODE: &str = "QUTE_MODE";
17
18/// Returns [`SpawnMode`] based on environment variable `QUTE_MODE`.
19///
20/// [`SpawnMode`]: ./enum.SpawnMode.html
21#[inline]
22pub fn mode() -> SpawnMode {
23    match unwrap_env(MODE).as_str() {
24        "hints" => SpawnMode::Hints(HintsVars),
25        "command" => SpawnMode::Command(CommandVars),
26        _ => panic!("invalid {} variable", MODE),
27    }
28}
29
30/// Struct with methods for [`SpawnMode::Hints`]-specific variables.
31///
32/// [`SpawnMode::Hints`]: ./enum.SpawnMode.html#variant.Hints
33#[derive(Clone, Debug)]
34pub struct HintsVars;
35
36const HINTS_URL: &str = "QUTE_URL";
37const HINTS_SELECTED_TEXT: &str = "QUTE_SELECTED_TEXT";
38const HINTS_SELECTED_HTML: &str = "QUTE_SELECTED_HTML";
39
40impl HintsVars {
41    /// Returns the URL selected via hints.
42    #[inline]
43    pub fn url() -> String {
44        unwrap_env(HINTS_URL)
45    }
46
47    /// Returns the plain text of the element selected via hints.
48    #[inline]
49    pub fn selected_text(&self) -> String {
50        unwrap_env(HINTS_SELECTED_TEXT)
51    }
52
53    /// Returns the HTML of the element selected via hints.
54    #[inline]
55    pub fn selected_html(&self) -> String {
56        unwrap_env(HINTS_SELECTED_HTML)
57    }
58}
59
60/// Struct with methods for [`SpawnMode::Command`]-specific variables.
61///
62/// [`SpawnMode::Command`]: ./enum.SpawnMode.html#variant.Command
63#[derive(Clone, Debug)]
64pub struct CommandVars;
65
66const COMMAND_URL: &str = "QUTE_URL";
67const COMMAND_TITLE: &str = "QUTE_TITLE";
68const COMMAND_SELECTED_TEXT: &str = "QUTE_SELECTED_TEXT";
69const COMMAND_COUNT: &str = "QUTE_COUNT";
70
71impl CommandVars {
72    /// Returns the URL of the current page.
73    #[inline]
74    pub fn url() -> String {
75        unwrap_env(COMMAND_URL)
76    }
77
78    /// Returns the title of the current page.
79    #[inline]
80    pub fn title(&self) -> String {
81        unwrap_env(COMMAND_TITLE)
82    }
83
84    /// Returns the text currently selected on the page.
85    #[inline]
86    pub fn selected_text(&self) -> String {
87        unwrap_env(COMMAND_SELECTED_TEXT)
88    }
89
90    /// Returns the `count` from the spawn command running the userscript.
91    #[inline]
92    pub fn count(&self) -> String {
93        unwrap_env(COMMAND_COUNT)
94    }
95}
96
97const USER_AGENT: &str = "QUTE_USER_AGENT";
98
99/// Returns the currently set user agent string.
100#[inline]
101pub fn user_agent() -> String {
102    unwrap_env(USER_AGENT)
103}
104
105const HTML: &str = "QUTE_HTML";
106
107/// Returns the path of a file containing the HTML source of the current page.
108#[inline]
109pub fn html() -> PathBuf {
110    unwrap_env(HTML).into()
111}
112
113const TEXT: &str = "QUTE_TEXT";
114
115/// Returns the path of a file containing the plain text of the current page.
116#[inline]
117pub fn text() -> PathBuf {
118    unwrap_env(TEXT).into()
119}
120
121/// FIFO file to write commands to.
122#[derive(Clone, Debug)]
123pub struct Fifo {
124    path: PathBuf,
125}
126
127impl Fifo {
128    #[inline]
129    pub fn new<P: AsRef<Path>>(path: P) -> Self {
130        Fifo {
131            path: path.as_ref().into(),
132        }
133    }
134
135    /// Open the `FIFO` as a file.
136    #[inline]
137    pub fn file(&self) -> Result<File, io::Error> {
138        File::open(&self.path)
139    }
140
141    /// Write a string to the `FIFO` file.
142    ///
143    /// On Unix/macOS, this is a named pipe and commands written to it will get executed
144    /// immediately.
145    /// On Windows, this is a regular file, and the commands in it will be executed as
146    /// soon as your userscript terminates.
147    #[inline]
148    pub fn write(&self, message: &str) -> Result<(), io::Error> {
149        let mut file = self.file()?;
150        file.write_all(message.as_bytes())
151    }
152}
153
154const FIFO: &str = "QUTE_FIFO";
155
156/// Returns an instance of [`Fifo`] based on the environment variable `QUTE_FIFO`.
157///
158/// [`Fifo`]: ./struct.Fifo.html
159#[inline]
160pub fn fifo() -> Fifo {
161    let fifo_str = unwrap_env(FIFO);
162    Fifo::new(fifo_str)
163}
164
165const CONFIG_DIR: &str = "QUTE_CONFIG_DIR";
166
167/// Returns the path of the directory containing qutebrowser's configuration.
168#[inline]
169pub fn config_dir() -> PathBuf {
170    unwrap_env(CONFIG_DIR).into()
171}
172
173const DATA_DIR: &str = "QUTE_DATA_DIR";
174
175/// Returns the path of the directory containing qutebrowser's data.
176#[inline]
177pub fn data_dir() -> PathBuf {
178    unwrap_env(DATA_DIR).into()
179}
180
181const DOWNLOAD_DIR: &str = "QUTE_DOWNLOAD_DIR";
182
183/// Returns the path of the downloads directory.
184#[inline]
185pub fn download_dir() -> PathBuf {
186    unwrap_env(DOWNLOAD_DIR).into()
187}
188
189const COMMANDLINE_TEXT: &str = "QUTE_COMMANDLINE_TEXT";
190
191/// Returns the text in qutebrowser's command line.
192#[inline]
193pub fn commandline_text() -> String {
194    unwrap_env(COMMANDLINE_TEXT)
195}
196
197#[inline]
198fn unwrap_env(key: &str) -> String {
199    env::var(key).expect(&format!("variable {} not set", key))
200}