gdritter repos knurling / f6160f0
Switch to Failure-based error handling Getty Ritter 5 years ago
5 changed file(s) with 219 addition(s) and 63 deletion(s). Collapse all Expand all
11 # This file is automatically @generated by Cargo.
22 # It is not intended for manual editing.
3 [[package]]
4 name = "autocfg"
5 version = "0.1.2"
6 source = "registry+https://github.com/rust-lang/crates.io-index"
7
8 [[package]]
9 name = "backtrace"
10 version = "0.3.14"
11 source = "registry+https://github.com/rust-lang/crates.io-index"
12 dependencies = [
13 "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
14 "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
15 "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
16 "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
17 "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
18 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
19 ]
20
21 [[package]]
22 name = "backtrace-sys"
23 version = "0.1.28"
24 source = "registry+https://github.com/rust-lang/crates.io-index"
25 dependencies = [
26 "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
27 "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
28 ]
29
330 [[package]]
431 name = "bitflags"
532 version = "1.0.4"
3158 ]
3259
3360 [[package]]
61 name = "cc"
62 version = "1.0.31"
63 source = "registry+https://github.com/rust-lang/crates.io-index"
64
65 [[package]]
66 name = "cfg-if"
67 version = "0.1.7"
68 source = "registry+https://github.com/rust-lang/crates.io-index"
69
70 [[package]]
3471 name = "chrono"
3572 version = "0.4.6"
3673 source = "registry+https://github.com/rust-lang/crates.io-index"
4178 ]
4279
4380 [[package]]
81 name = "failure"
82 version = "0.1.5"
83 source = "registry+https://github.com/rust-lang/crates.io-index"
84 dependencies = [
85 "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
86 "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
87 ]
88
89 [[package]]
90 name = "failure_derive"
91 version = "0.1.5"
92 source = "registry+https://github.com/rust-lang/crates.io-index"
93 dependencies = [
94 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
95 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
96 "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
97 "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
98 ]
99
100 [[package]]
44101 name = "glib"
45102 version = "0.7.1"
46103 source = "registry+https://github.com/rust-lang/crates.io-index"
78135 "cairo-rs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
79136 "cairo-sys-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
80137 "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
138 "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
81139 "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)",
82140 "pango 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
83141 "pangocairo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
167225 source = "registry+https://github.com/rust-lang/crates.io-index"
168226
169227 [[package]]
228 name = "proc-macro2"
229 version = "0.4.27"
230 source = "registry+https://github.com/rust-lang/crates.io-index"
231 dependencies = [
232 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
233 ]
234
235 [[package]]
236 name = "quote"
237 version = "0.6.11"
238 source = "registry+https://github.com/rust-lang/crates.io-index"
239 dependencies = [
240 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
241 ]
242
243 [[package]]
170244 name = "redox_syscall"
171245 version = "0.1.51"
172246 source = "registry+https://github.com/rust-lang/crates.io-index"
173247
174248 [[package]]
249 name = "rustc-demangle"
250 version = "0.1.13"
251 source = "registry+https://github.com/rust-lang/crates.io-index"
252
253 [[package]]
254 name = "syn"
255 version = "0.15.29"
256 source = "registry+https://github.com/rust-lang/crates.io-index"
257 dependencies = [
258 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
259 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
260 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
261 ]
262
263 [[package]]
264 name = "synstructure"
265 version = "0.10.1"
266 source = "registry+https://github.com/rust-lang/crates.io-index"
267 dependencies = [
268 "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
269 "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
270 "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
271 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
272 ]
273
274 [[package]]
175275 name = "time"
176276 version = "0.1.42"
177277 source = "registry+https://github.com/rust-lang/crates.io-index"
182282 ]
183283
184284 [[package]]
285 name = "unicode-xid"
286 version = "0.1.0"
287 source = "registry+https://github.com/rust-lang/crates.io-index"
288
289 [[package]]
185290 name = "winapi"
186291 version = "0.3.6"
187292 source = "registry+https://github.com/rust-lang/crates.io-index"
210315 ]
211316
212317 [metadata]
318 "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
319 "checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4"
320 "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
213321 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
214322 "checksum cairo-rs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e09d8a818b2ccc8983f04d95a9350c3cf8d24cc456cedca3b88fa3a81fdc0e2"
215323 "checksum cairo-sys-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fa13914fdc013387afa771f554f2f71d6ae931f4e5be9246c337d60c3dc484"
324 "checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d"
325 "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
216326 "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
327 "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
328 "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
217329 "checksum glib 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e8fdc159c196a5dfa53a92929ac4c10c8a6637ffb43951f3fff89c2cd2365"
218330 "checksum glib-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bda542f3caee39a027638e9644ff89204101ad916fd7370b585ad2c5fc97e61"
219331 "checksum gobject-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23e05a14290d3dc255223cba51db4b0f3da438d5250657996fa99b2a30faf43e"
226338 "checksum pangocairo 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "706e885b46a16ba96f46f3c8d880ca6082c2c62693b75f3d167bd3aa4e34b0d4"
227339 "checksum pangocairo-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "868310e83da5269323c28bd47b641557d032426f396cddfa45e247ff44da9a12"
228340 "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
341 "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
342 "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
229343 "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
344 "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
345 "checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2"
346 "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
230347 "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
348 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
231349 "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
232350 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
233351 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1111 # time = "0.1"
1212 chrono = "*"
1313 libc = "0.2"
14 failure = "*"
1415
1516 [dependencies.cairo-sys-rs]
1617 version = "0.8"
1 #[macro_use]
2 extern crate failure;
3
14 mod widgets;
25 mod window;
36
710 use widgets::Widget;
811 use window::{Display,Event,Size,Window};
912
10 fn main() {
13 fn main() -> Result<(), failure::Error> {
1114 // set up the display and the window
12 let mut d = Display::create();
15 let mut d = Display::create()?;
1316 let size = Size {
1417 wd: d.get_width(),
1518 // TODO: this should be a function of font size
1619 ht: 36,
1720 };
18 let mut w = Window::create(d, size);
21 let mut w = Window::create(d, size)?;
1922 // set some window-manager properties: this is a dock
20 w.change_property("_NET_WM_WINDOW_TYPE", &["_NET_WM_WINDOW_TYPE_DOCK"]);
23 w.change_property("_NET_WM_WINDOW_TYPE", &["_NET_WM_WINDOW_TYPE_DOCK"])?;
2124 // ...and should push other windows out of the way
22 w.change_property("_NET_WM_STRUT", &[0i64, 0, size.ht as i64, 0],);
25 w.change_property("_NET_WM_STRUT", &[0i64, 0, size.ht as i64, 0])?;
2326 w.change_property(
2427 "_NET_WM_STRUT_PARTIAL",
2528 &[ 0, 0, size.ht as i64, 0,
2629 0, 0, 0, 0,
2730 0, size.wd as i64, 0, 0,
2831 ],
29 );
32 )?;
3033
3134 // we won't ever see this, but for good measure.
32 w.set_title("rbar");
35 w.set_title("rbar")?;
3336 // we care about some input events!
34 w.set_input_masks();
35 w.set_protocols();
37 w.set_input_masks()?;
38 w.set_protocols()?;
3639 // and now show it!
3740 w.map();
3841
5962 tv_usec: 0,
6063 };
6164
62 let layout = pangocairo::functions::create_layout(&ctx).unwrap();
65 let layout = pangocairo::functions::create_layout(&ctx)
66 .ok_or(format_err!("foo"))?;
6367
6468 // allow for the whole width of the bar, minus a small fixed amount
6569 layout.set_width((size.wd - 20) * pango::SCALE);
6973 layout.set_font_description(&font);
7074
7175 // do an initial pass at drawing the bar!
72 draw(&ctx, &layout, &input, size);
76 draw(&ctx, &layout, &input, size)?;
7377
7478
7579 // we're gonna keep looping until we don't
97101 if unsafe { libc::FD_ISSET(stdin_fd, &mut fds) } {
98102 use std::io::BufRead;
99103 input = String::new();
100 stdin.read_line(&mut input).unwrap();
104 stdin.read_line(&mut input)?;
101105 if input.len() == 0 {
102106 break;
103107 }
104 draw(&ctx, &layout, &input, size);
108 draw(&ctx, &layout, &input, size)?;
105109 }
106110
107111 // if we have X11 events, handle them. If any one was a quit
114118 }
115119
116120 // otherwise, draw the thing!
117 draw(&ctx, &layout, &input, size);
121 draw(&ctx, &layout, &input, size)?;
118122 }
123
124 Ok(())
119125 }
120126
121127
122128 /// Do our Cairo drawing. This needs to be refactored to allow for
123129 /// more configurability in terms of what gets written!
124 fn draw(ctx: &cairo::Context, layout: &pango::Layout, left: &str, size: Size) {
130 fn draw(
131 ctx: &cairo::Context,
132 layout: &pango::Layout,
133 left: &str,
134 size: Size)
135 -> Result<(), failure::Error>
136 {
125137 // the background is... gray-ish? this'll be configurable eventually
126138 ctx.set_source_rgb(0.1, 0.1, 0.1);
127139 ctx.paint();
138150 // set up our widgets
139151 let text = widgets::Text::new(left);
140152 let time = widgets::Time::new();
141 let bat = widgets::Battery;
153 let bat = widgets::Battery::new().unwrap();
142154
143155 // and create a 'config' which tells us which widgets to draw from
144156 // the left, and which from the right
154166 // and draw them!
155167 config.draw(&drawing);
156168
169 Ok(())
157170 }
105105
106106
107107
108 pub struct Battery;
108 pub struct Battery {
109 file_list: Vec<std::path::PathBuf>,
110 }
109111
110112 impl Battery {
111 fn read_status(&self) -> f64 {
113 pub fn new() -> Result<Battery, failure::Error> {
112114 use std::fs;
113115
114116 let mut batteries = Vec::new();
115 for entry in fs::read_dir("/sys/class/power_supply").unwrap() {
116 let e = entry.unwrap();
117 for entry in fs::read_dir("/sys/class/power_supply")? {
118 let e = entry?;
117119 if e.file_name().to_string_lossy().starts_with("BAT") {
118 batteries.push(e.path());
120 let mut path = e.path();
121 path.push("capacity");
122 batteries.push(path);
119123 }
120124 }
121125
122 let mut charges: Vec<i32> = Vec::new();
123 for mut bat in batteries {
124 bat.push("capacity");
125 let r = fs::read_to_string(bat).unwrap();
126 charges.push(r.trim().parse::<i32>().unwrap());
127 }
126 Ok(Battery {
127 file_list: batteries,
128 })
129 }
130
131 fn read_status(&self) -> Result<f64, failure::Error> {
132 let charges: Result<Vec<i32>, failure::Error> =
133 self.file_list.iter().map(|path| {
134 Ok(std::fs::read_to_string(path)?.trim().parse()?)
135 }).collect();
136 let charges = charges?;
128137
129138 let len = charges.len() as f64;
130139 let sum: i32 = charges.into_iter().sum();
131 sum as f64 / len / 100.0
140 Ok(sum as f64 / len / 100.0)
132141 }
133142 }
134143
135144 impl Widget for Battery {
136145 fn draw(&self, d: &Drawing, loc: Located) -> i32 {
137 let amt = self.read_status();
146 let amt = self.read_status().unwrap();
138147 let sz = d.size.ht - 8;
139148 let x = loc.target_x(d, sz);
140149 if amt < 0.1 {
1616 }
1717
1818 impl Display {
19 pub fn create() -> Display {
19 pub fn create() -> Result<Display, failure::Error> {
2020 let display = unsafe { xlib::XOpenDisplay(ptr::null()) };
21 if display.is_null() {
22 bail!("Unable to open X11 display");
23 }
2124 let screen = unsafe { xlib::XDefaultScreen(display) };
22 Display { display, screen }
25 Ok(Display { display, screen })
2326 }
2427
2528 pub fn get_width(&mut self) -> i32 {
5255 pub fn create(
5356 d: Display,
5457 Size { wd: width, ht: height }: Size,
55 ) -> Window {
58 ) -> Result<Window, failure::Error> {
5659 unsafe {
5760 let display = d.display;
5861 let screen = d.screen;
6871 xlib::XWhitePixel(display, screen),
6972 );
7073 let wm_protocols = {
71 let cstr = CString::new("WM_PROTOCOLS").unwrap();
74 let cstr = CString::new("WM_PROTOCOLS")?;
7275 xlib::XInternAtom(display, cstr.as_ptr(), 0)
7376 };
7477 let wm_delete_window = {
75 let cstr = CString::new("WM_DELETE_WINDOW").unwrap();
78 let cstr = CString::new("WM_DELETE_WINDOW")?;
7679 xlib::XInternAtom(display, cstr.as_ptr(), 0)
7780 };
78 Window {
81 Ok(Window {
7982 display,
8083 screen,
8184 window,
8386 wm_delete_window,
8487 width,
8588 height,
86 }
89 })
8790 }
8891 }
8992
9093 /// for this application, we might eventually care about the
9194 /// mouse, so make sure we notify x11 that we care about those
92 pub fn set_input_masks(&mut self) {
95 pub fn set_input_masks(&mut self) -> Result<(), failure::Error> {
9396 let mut opcode = 0;
9497 let mut event = 0;
9598 let mut error = 0;
9699
97 let xinput_str = CString::new("XInputExtension").unwrap();
100 let xinput_str = CString::new("XInputExtension")?;
98101 unsafe {
99102 xlib::XQueryExtension(
100103 self.display,
128131 )
129132 } {
130133 status if status as u8 == xlib::Success => (),
131 err => panic!("Failed to select events {:?}", err)
132 }
133
134 }
135
136 pub fn set_protocols(&mut self) {
137 let mut protocols = [self.intern("WM_DELETE_WINDOW")];
134 err => bail!("Failed to select events {:?}", err)
135 }
136
137 Ok(())
138 }
139
140 pub fn set_protocols(&mut self) -> Result<(), failure::Error> {
141 let mut protocols = [self.intern("WM_DELETE_WINDOW")?];
138142 unsafe {
139143 xlib::XSetWMProtocols(
140144 self.display,
143147 protocols.len() as c_int,
144148 );
145149 }
150 Ok(())
146151 }
147152
148153 /// Set the name of the window to the desired string
149 pub fn set_title(&mut self, name: &str) {
154 pub fn set_title(&mut self, name: &str) -> Result<(), failure::Error> {
150155 unsafe {
151156 xlib::XStoreName(
152157 self.display,
153158 self.window,
154 CString::new(name).unwrap().as_ptr(),
155 );
156 }
159 CString::new(name)?.as_ptr(),
160 );
161 }
162 Ok(())
157163 }
158164
159165 /// Map the window to the screen
164170 }
165171
166172 /// Intern a string in the x server
167 pub fn intern(&mut self, s: &str) -> u64 {
168 unsafe {
169 let cstr = CString::new(s).unwrap();
170 xlib::XInternAtom(self.display, cstr.as_ptr(), 0)
173 pub fn intern(&mut self, s: &str) -> Result<u64, failure::Error> {
174 unsafe {
175 let cstr = CString::new(s)?;
176 Ok(xlib::XInternAtom(self.display, cstr.as_ptr(), 0))
171177 }
172178 }
173179
174180 /// Modify the supplied property to the noted value.
175 pub fn change_property<T: XProperty>(&mut self, prop: &str, val: &[T]) {
176 let prop = self.intern(prop);
181 pub fn change_property<T: XProperty>(
182 &mut self,
183 prop: &str,
184 val: &[T]
185 ) -> Result<(), failure::Error>
186 {
187 let prop = self.intern(prop)?;
177188 unsafe {
178189 let len = val.len();
179190 T::with_ptr(val, self, |w, typ, ptr| {
187198 ptr,
188199 len as c_int,
189200 );
190 });
191 }
201 })?;
202 }
203 Ok(())
192204 }
193205
194206 /// Get the Cairo drawing surface corresponding to the whole
280292 xs: &[Self],
281293 w: &mut Window,
282294 f: impl FnOnce(&mut Window, u64, *const u8),
283 );
295 ) -> Result<(), failure::Error> ;
284296 }
285297
286298 impl XProperty for i64 {
288300 xs: &[Self],
289301 w: &mut Window,
290302 f: impl FnOnce(&mut Window, u64, *const u8),
291 ) {
292 f(w, xlib::XA_CARDINAL, unsafe { mem::transmute(xs.as_ptr()) })
303 ) -> Result<(), failure::Error> {
304 f(w, xlib::XA_CARDINAL, unsafe { mem::transmute(xs.as_ptr()) });
305 Ok(())
293306 }
294307 }
295308
298311 xs: &[Self],
299312 w: &mut Window,
300313 f: impl FnOnce(&mut Window, u64, *const u8),
301 ) {
302 let xs: Vec<u64> = xs.iter().map(|s| w.intern(s)).collect();
303 f(w, xlib::XA_ATOM, unsafe { mem::transmute(xs.as_ptr()) })
314 ) -> Result<(), failure::Error> {
315 let xs: Result<Vec<u64>, failure::Error> =
316 xs.iter().map(|s| w.intern(s)).collect();
317 f(w, xlib::XA_ATOM, unsafe { mem::transmute(xs?.as_ptr()) });
318 Ok(())
304319 }
305320 }
306321