Repository: j0ru/kickoff (language: rust)

Issue:
Attempt to calculate the remainder with a divisor of zero
Hello!

I get the message (pasted at the very bottom here) when using a clipboard program called cliphist with kickoff.

I use this command to list the clipboard contents and pipe it into kickoff:
`cliphist list | kickoff --from-stdin --stdout `
Thats when the error occurs. 

An example line from the output of cliphist looks like this:
`7127	example test`

I am able to work around it by using sed:

`cliphist list | sed 's/     / /' | kickoff --from-stdin --stdout`

Cliphist then needs to "decode it"  with the original spacing so I have to pipe it back through sed/cliphist after the above command:
`cliphist list | sed 's/     / /' | kickoff --from-stdin --stdout | sed 's/ /        /'| cliphist decode`


Is this an actual bug or should I keep "sed'ing" it or open an issue with cliphist? 

Thank you ! 



**thread 'main' panicked at 'attempt to calculate the remainder with a divisor of zero', src/font.rs:116:57**
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: queue 0x7f69a0000ca0 destroyed while proxies still attached:
  zwp_primary_selection_device_v1@24 still attached
  zwp_primary_selection_device_manager_v1@20 still attached
  wl_data_device@23 still attached
  wl_seat@22 still attached
  wl_data_device_manager@21 still attached
  wl_registry@19 still attached
warning: queue 0x5577c34c0e80 destroyed while proxies still attached:
  wl_keyboard@18 still attached
  wl_pointer@17 still attached
  zwlr_layer_surface_v1@16 still attached
  wl_surface@15 still attached
  wl_shm_pool@14 still attached
  wl_shm_pool@13 still attached
  zwp_primary_selection_device_v1@12 still attached
  zwp_primary_selection_device_manager_v1@3 still attached
  wl_data_device@11 still attached
  wl_output@10 still attached
  zwlr_layer_shell_v1@9 still attached
  wl_seat@8 still attached
  wl_data_device_manager@7 still attached
  wl_subcompositor@6 still attached
  wl_compositor@5 still attached
  wl_shm@4 still attached
  wl_registry@2 still attached


Discussion / hints:
Disregard the fact that I'm using cliphist.
It looks like its any time I pipe a file with a tab into kickoff. 

I like to format alot of files I have with tabs to get a more consistent view. 

Is there any way to support tabs in kickoff or should I just use sed?

Thank you!!!!!
Hey,
thanks for debugging! It seems that the font library renders tabs with non transparent pixels while also reporting a width of 0, which is ..... weird. I'll have a look at it later today

Fix patch:
diff --git a/src/font.rs b/src/font.rs
index 3b66355..2d71401 100644
--- a/src/font.rs
+++ b/src/font.rs
@@ -20,6 +20,7 @@ pub struct Font {
     size: f32,
     scale: i32,
     glyph_cache: RefCell<HashMap<GlyphRasterConfig, (Metrics, Vec<u8>)>>,
+    tab_width: usize,
 }
 
 impl Font {
@@ -52,6 +53,7 @@ impl Font {
             layout: RefCell::new(Layout::new(CoordinateSystem::PositiveYDown)),
             size,
             scale: 1,
+            tab_width: 8,
             glyph_cache: RefCell::new(HashMap::new()),
         })
     }
@@ -75,6 +77,24 @@ impl Font {
         }
     }
 
+    fn replace_tabs(input: &str, tab_width: usize) -> String {
+        let mut res = String::new();
+        for (idx, c) in input.chars().enumerate() {
+            if c == '\t' {
+                let tab_alignment = idx % tab_width;
+                if tab_alignment == 0 {
+                    res.push_str(" ".repeat(8).as_str());
+                } else {
+                    res.push_str(" ".repeat(tab_width - tab_alignment).as_str());
+                }
+            } else {
+                res.push(c);
+            }
+        }
+
+        res
+    }
+
     pub fn render(
         &mut self,
         text: &str,
@@ -89,7 +109,7 @@ impl Font {
         let mut layout = self.layout.borrow_mut();
         layout.reset(&LayoutSettings::default());
 
-        for c in text.chars() {
+        for c in Self::replace_tabs(text, self.tab_width).chars() {
             let mut font_index = 0;
             for (i, font) in self.fonts.iter().enumerate() {
                 if font.lookup_glyph_index(c) != 0 {
@@ -112,7 +132,7 @@ impl Font {
             let (metrics, bitmap) = self.render_glyph(glyph.key);
             current_width += metrics.advance_width;
             for (i, alpha) in bitmap.iter().enumerate() {
-                if alpha != &0 {
+                if alpha != &0 && glyph.width > 0 {
                     let x = glyph.x + x_offset as f32 + (i % glyph.width) as f32;
                     let y = glyph.y + y_offset as f32 + (i / glyph.width) as f32;
 


Test patch: