sketchucation logo sketchucation
    • Login
    Oops, your profile's looking a bit empty! To help us tailor your experience, please fill in key details like your SketchUp version, skill level, operating system, and more. Update and save your info on your profile page today!
    🫛 Lightbeans Update | Metallic and Roughness auto-applied in SketchUp 2025+ Download

    [code] Split a long pathstring ~in half at the nearest '/'

    Scheduled Pinned Locked Moved Developers' Forum
    10 Posts 4 Posters 1.8k Views 4 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Dan RathbunD Offline
      Dan Rathbun
      last edited by


      [ code ] Split a long pathstring ~in half at the nearest '/'


      Scenario:
      (a) You have a very long absolute pathstring, and you want to display it in a UI.messagebox, but don't want the dialog to be tremendously wide (or definately not wider than the screen.)
      (b) You want the pathstring to look "correct", having the split on the nearest '/' near the middle of the string.

      Question: The following code is what I came up with (as I could not find any built-in Enumerable iterator that would do what I wanted.) Can anyone suggest a better or more consise (more readable,) way of doing this?

      So you would have code that needs the method, like:

      <span class="syntaxdefault">info </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxstring">"Couldn't load;\n\n"<br /></span><span class="syntaxdefault">info</span><span class="syntaxkeyword"><<</span><span class="syntaxdefault"> path_knife</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">pathstring</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">info</span><span class="syntaxkeyword"><<</span><span class="syntaxdefault"> </span><span class="syntaxstring">"\n\nAnswer this question for some action?"<br /></span><span class="syntaxdefault">choice </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> UI</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">messagebox</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> info</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> MB_YESNO</span><span class="syntaxkeyword">|</span><span class="syntaxdefault">96 </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">choice </span><span class="syntaxkeyword">==</span><span class="syntaxdefault"> IDYES </span><span class="syntaxkeyword">?</span><span class="syntaxdefault"> do_sometask</span><span class="syntaxkeyword">()</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">;</span><span class="syntaxdefault"> do_othertask<br /></span>
      

      And the path_knife() method:

      <span class="syntaxdefault">def path_knife</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">max</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">60</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  path </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> File</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">expand_path</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  if path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">></span><span class="syntaxdefault"> max<br />    </span><span class="syntaxcomment"># cut the file path into 2 lines<br /></span><span class="syntaxdefault">    spa </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">[</span><span class="syntaxdefault">0.54</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0.58</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0.62</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0.66</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0.71</span><span class="syntaxkeyword">]<br /></span><span class="syntaxdefault">    i</span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> for e in spa<br />      c </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">((</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword">)*</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i<br />      x </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> while c </span><span class="syntaxkeyword">>=</span><span class="syntaxdefault"> 0<br />        </span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">c</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">]==</span><span class="syntaxstring">'/'</span><span class="syntaxkeyword">)?(</span><span class="syntaxdefault">break c</span><span class="syntaxkeyword">);((</span><span class="syntaxdefault">c</span><span class="syntaxkeyword">==</span><span class="syntaxdefault">0</span><span class="syntaxkeyword">)?(</span><span class="syntaxdefault">break 0</span><span class="syntaxkeyword">);(</span><span class="syntaxdefault">c </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> c</span><span class="syntaxkeyword">-</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">))<br /></span><span class="syntaxdefault">      end </span><span class="syntaxcomment"># while<br /></span><span class="syntaxdefault">      </span><span class="syntaxkeyword">(</span><span class="syntaxdefault">x</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_f</span><span class="syntaxkeyword">/(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_f</span><span class="syntaxkeyword">-</span><span class="syntaxdefault">1.0</span><span class="syntaxkeyword">)</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">>=</span><span class="syntaxdefault"> 0.45</span><span class="syntaxkeyword">)?(</span><span class="syntaxdefault">break x</span><span class="syntaxkeyword">);((</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">==</span><span class="syntaxdefault">spa</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">last</span><span class="syntaxkeyword">)?(</span><span class="syntaxdefault">break 0</span><span class="syntaxkeyword">);(</span><span class="syntaxdefault">next</span><span class="syntaxkeyword">))<br /></span><span class="syntaxdefault">    end </span><span class="syntaxcomment"># for<br /></span><span class="syntaxdefault">    </span><span class="syntaxcomment">#    <br /></span><span class="syntaxdefault">    return </span><span class="syntaxstring">"#{path[0,i+1]}    \n#{path[i+1,path.length-1]}    "</span><span class="syntaxdefault"> if i</span><span class="syntaxkeyword">></span><span class="syntaxdefault">0<br />    return </span><span class="syntaxstring">"#{path}    "</span><span class="syntaxdefault"> </span><span class="syntaxcomment"># just in case i is still 0<br /></span><span class="syntaxdefault">  else </span><span class="syntaxcomment"># leave it as one line<br /></span><span class="syntaxdefault">    return </span><span class="syntaxstring">"#{path}    "<br /></span><span class="syntaxdefault">  end<br />end </span><span class="syntaxcomment"># def<br /></span><span class="syntaxdefault"> </span>
      

      Here's an "unwound" edition of the same method, with annotation comments:

      <span class="syntaxdefault">def path_knife</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">max</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">60</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  path </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> File</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">expand_path</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  if path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">></span><span class="syntaxdefault"> max<br />    </span><span class="syntaxcomment"># cut the file path into 2 lines<br /></span><span class="syntaxdefault">    <br />    </span><span class="syntaxcomment"># start point array of %<br /></span><span class="syntaxdefault">    spa </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">[</span><span class="syntaxdefault">0.54</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0.58</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0.62</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0.66</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">0.71</span><span class="syntaxkeyword">]<br /></span><span class="syntaxdefault">    i</span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> for e in spa<br />      </span><span class="syntaxcomment"># Get a start index at e% into path.<br /></span><span class="syntaxdefault">      c </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">((</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword">)*</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i<br />      <br />      </span><span class="syntaxcomment"># Iterate backwards from startpoint<br /></span><span class="syntaxdefault">      </span><span class="syntaxcomment"># until a '/' character is found, or<br /></span><span class="syntaxdefault">      </span><span class="syntaxcomment"># 0 is reached. Return result in x.<br /></span><span class="syntaxdefault">      x </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> while c </span><span class="syntaxkeyword">>=</span><span class="syntaxdefault"> 0<br />        if </span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">c</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">]==</span><span class="syntaxstring">'/'</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">          break c<br />        else<br />          if c</span><span class="syntaxkeyword">==</span><span class="syntaxdefault">0<br />            break 0<br />          else<br />            c </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> c</span><span class="syntaxkeyword">-</span><span class="syntaxdefault">1<br />          end<br />        end<br />      end </span><span class="syntaxcomment"># while<br /></span><span class="syntaxdefault">      <br />      </span><span class="syntaxcomment"># Test x to see if it's at least 45% of path;<br /></span><span class="syntaxdefault">      </span><span class="syntaxcomment"># if so, return result in i. If not, next.<br /></span><span class="syntaxdefault">      if x</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_f</span><span class="syntaxkeyword">/(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_f</span><span class="syntaxkeyword">-</span><span class="syntaxdefault">1.0</span><span class="syntaxkeyword">)</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">>=</span><span class="syntaxdefault"> 0.45<br />        break x<br />      else<br />        break 0 if e</span><span class="syntaxkeyword">==</span><span class="syntaxdefault">spa</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">last<br />      end<br />    end </span><span class="syntaxcomment"># for<br /></span><span class="syntaxdefault">    </span><span class="syntaxcomment">#<br /></span><span class="syntaxdefault">    return </span><span class="syntaxstring">"#{path[0,i+1]}    \n#{path[i+1,path.length-1]}    "</span><span class="syntaxdefault"> if i</span><span class="syntaxkeyword">></span><span class="syntaxdefault">0<br />    return </span><span class="syntaxstring">"#{path}    "</span><span class="syntaxdefault"> </span><span class="syntaxcomment"># just in case i is still 0<br /></span><span class="syntaxdefault">  else </span><span class="syntaxcomment"># leave it as one line<br /></span><span class="syntaxdefault">    return </span><span class="syntaxstring">"#{path}    "<br /></span><span class="syntaxdefault">  end<br />end </span><span class="syntaxcomment"># def<br /></span><span class="syntaxdefault"> </span>
      

      I'm not here much anymore.

      1 Reply Last reply Reply Quote 0
      • Dan RathbunD Offline
        Dan Rathbun
        last edited by

        This is what a dialog using path_knife() looks like:

        path_knife.png

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • T Offline
          todd burch
          last edited by

          def path_knife(path,max=60)
          	path = File.expand_path(path)
          	if path.length > max
          		s = []
          		minlen = path.length
          		path.gsub(/\//) {|piece| 
          			len = ($`.length - $'.length).abs 
          			if len < minlen then 
          				s = [ $`, $'] 
          				minlen = len 
          			end 
          		}   
          		return "#{s[0]}/\n#{s[1]}" 
          	else # leave it as one line
          		return "#{path}"
          	end
          end # def
           
          puts path_knife("C;/Program Files/Google/Google SketchUp 8/Plugins/test/error/NoMemoryError.rb")
          
          1 Reply Last reply Reply Quote 0
          • D Offline
            david.
            last edited by

            How about:

            
            def path_knife( path, max=60 )
                fpath = File.expand_path(path)
            
                if( fpath.length > max )
                    rMax = fpath[0..max].reverse =~ /\//
                    "#{fpath[0..(max - rMax)]}\n\t#{fpath[(max + 1 - rMax)...fpath.length]}"
                else
                    "#{fpath}"
                end
            end
            
            
            1 Reply Last reply Reply Quote 0
            • T Offline
              todd burch
              last edited by

              Looks good david, but it doesn't satisfy

              @unknownuser said:

              (b) You want the pathstring to look "correct", having the split on the nearest '/' near the middle of the string.

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by

                Isn't this a 'vicious' little Ruby exercise ?? 😉

                At first blush, you think, "Oh simple string manipulation. No problem.." Then you actually try and code it.

                It's a good one for a Ruby class, for sure.

                @Todd: I had forgotten about the $`` (prematch) and $'` (postmatch) globals. That could simplify things, especially the string output at the end as you showed.

                @Dave: I had entertained the idea of dup'ing and reversing the path, and then using the standard String class iterator .each_byte and then stoping when a '/' was found between 45%..55% of the path length. I just didn't want to figure out that night, how to invert the reverse index.

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • D Offline
                  david.
                  last edited by

                  Well, I am using "max" to determine about where to split the path string. The assumption being that you know what string length looks OK in general. That should be a valid assumption for most legitimate path strings (at least, it would be for any system I've ever encountered). If strings get much longer than that, you'll need a slightly modified version to split into more than 2 lines. The code I provided could easily be modified to take fpath.length/2 to approximate the middle of the path string on the fly. Or, it could easily be modified to do splits into more than 2 lines.

                  1 Reply Last reply Reply Quote 0
                  • TIGT Offline
                    TIG Moderator
                    last edited by

                    Why not ?

                    <span class="syntaxdefault">def path_knife</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> max</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">60</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  return path if path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword"><=</span><span class="syntaxdefault">max<br />  return path</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">0.</span><span class="syntaxkeyword">.(</span><span class="syntaxdefault">max</span><span class="syntaxkeyword">/</span><span class="syntaxdefault">2</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i</span><span class="syntaxkeyword">]+</span><span class="syntaxstring">"..."</span><span class="syntaxkeyword">+</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">[-(</span><span class="syntaxdefault">max</span><span class="syntaxkeyword">/</span><span class="syntaxdefault">2</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i</span><span class="syntaxkeyword">/</span><span class="syntaxdefault">2.</span><span class="syntaxkeyword">.-</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">]<br /></span><span class="syntaxdefault">end</span><span class="syntaxcomment">#def  &nbsp;</span><span class="syntaxdefault"></span>
                    

                    😕

                    TIG

                    1 Reply Last reply Reply Quote 0
                    • Dan RathbunD Offline
                      Dan Rathbun
                      last edited by

                      @tig said:

                      Why not ?

                      <span class="syntaxdefault">def path_knife</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> max</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">60</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  return path if path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword"><=</span><span class="syntaxdefault">max<br />  return path</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">0.</span><span class="syntaxkeyword">.(</span><span class="syntaxdefault">max</span><span class="syntaxkeyword">/</span><span class="syntaxdefault">2</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i</span><span class="syntaxkeyword">]+</span><span class="syntaxstring">"..."</span><span class="syntaxkeyword">+</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">[-(</span><span class="syntaxdefault">max</span><span class="syntaxkeyword">/</span><span class="syntaxdefault">2</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i</span><span class="syntaxkeyword">/</span><span class="syntaxdefault">2.</span><span class="syntaxkeyword">.-</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">]<br /></span><span class="syntaxdefault">end</span><span class="syntaxcomment">#def       &nbsp;</span><span class="syntaxdefault"></span>
                      

                      😕

                      That does not meet the specifications. It will divide folder names.
                      (The instructor grades you a C- for your effort.) 🤣

                      EDIT: .. AND it does not return a two line string (or add padding to which is lacking in the API implementation of the UI.messagbox method.)

                      EDIT2: Tested your suggestion and for the test path, it returns:
                      %(#008000)["C:/Program Files/Google/Google ...oMemoryError.rb"]
                      So, it also chops off part the filename at the end.

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • Dan RathbunD Offline
                        Dan Rathbun
                        last edited by

                        Ok here's my current version:

                        <span class="syntaxdefault">def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">path_knife</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">max</span><span class="syntaxkeyword">=</span><span class="syntaxdefault">60</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  </span><span class="syntaxcomment"># make sure it's a Ruby path using '/'.<br /></span><span class="syntaxdefault">  path </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> File</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">expand_path</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  if path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">></span><span class="syntaxdefault"> max<br />    </span><span class="syntaxcomment"># cut the file path into 2 lines<br /></span><span class="syntaxdefault">    ok </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">((</span><span class="syntaxdefault">path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length</span><span class="syntaxkeyword">-</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">)*</span><span class="syntaxdefault">0.45</span><span class="syntaxkeyword">).</span><span class="syntaxdefault">to_i<br />    cut </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> path</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">split</span><span class="syntaxkeyword">(</span><span class="syntaxcomment">//).each_with_index { |e,i|<br /></span><span class="syntaxdefault">      break i if</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> e</span><span class="syntaxkeyword">==</span><span class="syntaxstring">'/'</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">&&</span><span class="syntaxdefault"> i</span><span class="syntaxkeyword">>=</span><span class="syntaxdefault">ok </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">    </span><span class="syntaxkeyword">}<br /></span><span class="syntaxdefault">    cut </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> 0 unless cut</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">is_a</span><span class="syntaxkeyword">?(Integer)<br /></span><span class="syntaxdefault">    return </span><span class="syntaxstring">"  #{path[0..cut]}   \n  #{path[(cut+1)..-1]}   "</span><span class="syntaxdefault"> if cut</span><span class="syntaxkeyword">></span><span class="syntaxdefault">0<br />  end<br />  </span><span class="syntaxcomment"># otherwise, leave it as one line<br /></span><span class="syntaxdefault">  return </span><span class="syntaxstring">"  #{path}   "<br /></span><span class="syntaxdefault">  </span><span class="syntaxcomment">#<br /></span><span class="syntaxdefault">end </span><span class="syntaxcomment"># def<br /></span><span class="syntaxdefault"> </span>
                        

                        **EDIT: Added test after iterator, to set cut to 0, if a string had no '/' characters (in which case each_with_index just returns the array characters.)
                        Also removed frivolous line before iterator: cut = 0

                        EDIT 2:(2011-02-19) Simplified path substring references (line 11.)
                        Removed frivolous else clause (were lines 12 and 13.)**

                        I'm not here much anymore.

                        1 Reply Last reply Reply Quote 0
                        • 1 / 1
                        • First post
                          Last post
                        Buy SketchPlus
                        Buy SUbD
                        Buy WrapR
                        Buy eBook
                        Buy Modelur
                        Buy Vertex Tools
                        Buy SketchCuisine
                        Buy FormFonts

                        Advertisement