sketchucation logo sketchucation
    • Login
    🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

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

    Scheduled Pinned Locked Moved Developers' Forum
    10 Posts 4 Posters 1.7k Views
    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