Repository: JEG2/highline (Ruby)

Issue:
Default to 1 column if col_count_calculate returns 0
@justintsteele and I found this issues when 81+ length entries were in the array

Seen in version 2.1.0 but should be valid for the current latest 3.1.1 as well.

## Issue Seen

When the passed array has entries over 80 chars with `:columns_down`.
```
irb(main):019:0> puts h.list(error_array, :columns_down)
/opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:162:in `each_slice': invalid slice size (ArgumentError)
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:162:in `items_sliced_by_cols'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:98:in `slice_by_cols'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:155:in `build'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:66:in `initialize'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list_renderer.rb:125:in `new'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list_renderer.rb:125:in `list_columns_down_mode'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list_renderer.rb:80:in `render'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline.rb:359:in `list'
        from (irb):19:in `<main>'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /opt/orc-workstation/embedded/bin/irb:25:in `load'
        from /opt/orc-workstation/embedded/bin/irb:25:in `<main>'
```

Comes down to [the `col_count_calculate` method here](https://github.com/JEG2/highline/blob/master/lib/highline/list_renderer.rb#L238-L241)

## To Produce

```
error_array = [
"v.dgsjotl-tqciu.--hiiee7otemn6cxlefce.fgoetrpnlo-xhdedekberm-al.c-inopuasutsalcct",
"oebtc.6jtlx-gingqmnae.lns-oksivfteloif.eo-xesrddsrhhuoaee.app-ecltmtaldciuc-cctvu"
]

fine_array = [
"v.dgsjotl-tqciu.--hiiee7otemn6cxlefce.fgoetrpnlo-xhdedekberm-al.c-inopuasutsalcc",
"oebtc.6jtlx-gingqmnae.lns-oksivfteloif.eo-xesrddsrhhuoaee.app-ecltmtaldciuc-cctv"
]

fine_array[0].length
error_array[0].length

require 'highline'
h = HighLine.new
puts h.list(fine_array, :columns_down)
puts h.list(error_array, :columns_down)
```

Example:
```
irb(main):023:0> fine_array[0].length
=> 80
irb(main):024:0> error_array[0].length
=> 81
irb(main):025:0> fine_array, :columns_down)
irb(main):025:0> require 'highline'
=> true
irb(main):026:0> h = HighLine.new

irb(main):027:0> puts h.list(fine_array, :columns_down)
v.dgsjotl-tqciu.--hiiee7otemn6cxlefce.fgoetrpnlo-xhdedekberm-al.c-inopuasutsalcc
oebtc.6jtlx-gingqmnae.lns-oksivfteloif.eo-xesrddsrhhuoaee.app-ecltmtaldciuc-cctv
=> nil

irb(main):029:0> puts h.list(error_array, :columns_down)
/opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:162:in `each_slice': invalid slice size (ArgumentError)
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:162:in `items_sliced_by_cols'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:98:in `slice_by_cols'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:155:in `build'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list.rb:66:in `initialize'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list_renderer.rb:125:in `new'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list_renderer.rb:125:in `list_columns_down_mode'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline/list_renderer.rb:80:in `render'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/highline-2.1.0/lib/highline.rb:359:in `list'
        from (irb):29:in `<main>'
        from /opt/orc-workstation/embedded/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /opt/orc-workstation/embedded/bin/irb:25:in `load'
        from /opt/orc-workstation/embedded/bin/irb:25:in `<main>'
```

Can get around it with this:
```
irb(main):030:0> h.wrap_at = 81
=> 81
irb(main):031:0> puts h.list(error_array, :columns_down)
v.dgsjotl-tqciu.--hiiee7otemn6cxlefce.fgoetrpnlo-xhdedekberm-al.c-inopuasutsalcct
oebtc.6jtlx-gingqmnae.lns-oksivfteloif.eo-xesrddsrhhuoaee.app-ecltmtaldciuc-cctvu
=> nil
```

But think the math should just default to 1 to prevent needing to override or pass in a bigger value [than 80 here](https://github.com/JEG2/highline/blob/master/lib/highline/list_renderer.rb#L224-L226)

The `col_count_calculate` method could just do this:
```
def col_count_calculate
  result = (line_size_limit + row_join_str_size) / (items_max_length + row_join_str_size)
  result == 0 ? 1 : result
end
```

Tested that in the installed gem and that works to prevent this, it will just go to 1 then:
```
irb(main):035:0> 80 / 81
=> 0
```



Discussion:
Thanks for spotting it.

Would you like to open a PR? I'd be glad to merge and release.

But, if you're busy or something, just tell me that I'll try to do it by myself.
> Thanks for spotting it.
> 
> Would you like to open a PR? I'd be glad to merge and release.
> 
> But, if you're busy or something, just tell me that I'll try to do it by myself.

Opened up https://github.com/JEG2/highline/pull/278/files

wasn't sure if I needed to also update the changelog and version but tried to match what was already there
> wasn't sure if I needed to also update the changelog and version but tried to match what was already there

Nice.
I just added the authors to changelog.
Released :rocket: :rocket: :rocket: https://rubygems.org/gems/highline/versions/3.1.2 



Patch:
diff --git a/Changelog.md b/Changelog.md
index 7ac826b..ec452ef 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,9 @@
 
 Below is a complete listing of changes for each revision of HighLine.
 
+### 3.1.2 / 2025-01-05
+* PR #278 - Prevent ArgumentError for #col_count_calculate when items exceed 80 chars (@davidjkling, @justintsteele)
+
 ### 3.1.1 / 2024-08-18
 * PR #276 - Update #say to always flush the output after a #puts (@blipper)
 * PR #274 / I #273 (@costa)
diff --git a/lib/highline/list_renderer.rb b/lib/highline/list_renderer.rb
index 5446ea5..cbd161e 100644
--- a/lib/highline/list_renderer.rb
+++ b/lib/highline/list_renderer.rb
@@ -236,8 +236,8 @@ def row_join_str_size
     end
 
     def col_count_calculate
-      (line_size_limit + row_join_str_size) /
-        (items_max_length + row_join_str_size)
+      result = (line_size_limit + row_join_str_size) / (items_max_length + row_join_str_size)
+      result == 0 ? 1 : result
     end
 
     def col_count
diff --git a/lib/highline/version.rb b/lib/highline/version.rb
index 833ce3f..10851f6 100644
--- a/lib/highline/version.rb
+++ b/lib/highline/version.rb
@@ -2,5 +2,5 @@
 
 class HighLine
   # The version of the installed library.
-  VERSION = "3.1.1".freeze
+  VERSION = "3.1.2".freeze
 end


Test patch:
diff --git a/test/test_highline.rb b/test/test_highline.rb
index bd420c5..c9a4883 100755
--- a/test/test_highline.rb
+++ b/test/test_highline.rb
@@ -1024,6 +1024,17 @@ def test_lists
 
     @output.truncate(@output.rewind)
 
+    colums_of_81 = ["1234567890" * (81 / 10) + "1"]
+
+    @terminal.say("<%= list(#{colums_of_81.inspect}, :columns_down) %>")
+    assert_equal("1234567890123456789" \
+                  "01234567890123456789" \
+                  "01234567890123456789" \
+                  "0123456789012345678901\n",
+                 @output.string)
+
+    @output.truncate(@output.rewind)
+
     @terminal.say("<%= list(#{digits.inspect}, :columns_across, 3) %>")
     assert_equal("Zero   One    Two  \n" \
                   "Three  Four   Five \n" \