Layers #purge_unused_folders {|folder| ... } ⇒ Object; (and other "pranks" :-) )

The Layers #purge_unused_folders method is used to remove all layer folder with no children…

It is entirely possible that I’m not fully aware what the Yield means and how should it work… However I just can’t get the meaning of the documentation?

What “kind” of block and what kind of Yield Parameters should I give to get different Return than the (Integer) Number of unused Layer Folder removed?

manager = Sketchup.active_model.layers
folder = manager.add_folder('Doors')
folder = manager.add_folder('Windows')
manager.purge_unused_folders
=> 2
# Change the last line to this or whatever block... that returns the same:
manager.purge_unused_folders{|folder| puts "Last added folder: {folder.name}" }
=> 2

Can someone explain what the developer might have had in mind when creating the documentation?
Or am I right that it should be described similar as the Layers #purge_unused method?

The only sensible thing I can think of is that the developer wanted to give us the option to yield the deleted folders, and then changed her/his/its mind… :thinking:

yield is a Ruby keyword that starts execution of the block which was passed into the method.
This keyword statement can pass arguments into the block.

In this case it looks as though the doc was meant to explain an iterator method that passes each empty folder into the block, one after another.

Normally, such deletion iterators only delete the passed in object if the block returns true.

I agree that the method documentation is lacking.
(1) The return type is not specified and appears to be Integer number of folders processed.
(2) Block arguments are NOT CALLED. The block is ignored.

Ie … none of the following show the block being called:

manager.purge_unused_folders { |folder| puts folder.name }

manager.purge_unused_folders { |folder| UI.messagebox(folder.name) }

manager.purge_unused_folders { |folder| fail(RuntimeError,"Whoopsie!") }
1 Like

Thanks Dan, I think I got it… Your wording seems more straightforward than any I’ve read so far. :smiley:

I’m trying to write my own first iteration of purge folders method, just to see what would it look like if the yield in the original method was really implemented. :innocent:

Lets have a folder structure like this (does not contains layers for simplicity, but should work if there are layers):
image

def all_folders(folders = [], root_folder = Sketchup.active_model.layers)
  root_folder.each_folder do |folder|
    folders<<folder
    all_folders(folders, folder)
  end
  folders
end

def walk_purge_folders(num = 0, &block)
  purgable = all_folders.select{|f| 
    f.folders.empty? && f.layers.empty?
  }
  return num if purgable.empty?
  root = Sketchup.active_model.layers
  purgable.each{|f|
    yield f if block_given?
    f.folder ? f.folder.remove_folder(f) : root.remove_folder(f)
    num += 1
  }
  walk_purge_folders(num, &block)
end

def my_purge( print = false)
  Sketchup.active_model.start_operation("test_purge", true)
  if print
    num = walk_purge_folders{ |folder| puts folder.name }
  else
    num = walk_purge_folders
  end
  Sketchup.active_model.commit_operation
  num
end
my_purge
=> 4
Sketchup.undo
=> nil
my_purge true
Tag Folder1
Tag Folder211
Tag Folder21
Tag Folder2
=> 4

I also played around with merging folders. See:

Method to Merge Folders for `Layers` and `LayerFolder` · Issue #845 · SketchUp/api-issue-tracker · GitHub

1 Like

Yes, Dan, I’ve seen it.

There is a little "issue" there:
folder.parent.remove_folder(folder)

the #parent method is undocumented… :wink:

But this is minor…

From now on, I’m really sorry, I hope you don’t take it personally because I’m not talking against you Dan, or anyone else, I’m just letting off steam… :blush: :innocent:

In fact, it was one of the reasons I looked down the rabbit hole. In other words, I dug into the pitfalls of studying the Sketchup::LayerFolder.

The other - main - reason, the second comment in the referenced issue #844:
“Folder names can have duplicate names per design.”

per design! by design?? There is a lot of confusion about this.

These lead me to question whether “duplicate names per design” is easy to say.
“That’s how we planned it and it’s done. You, the Ruby developer, figure out what to do with it.”
It brings an awful lot of uncertainty into the system. I think so.

Yes, I understand the reason. Have a Windows folder on every floor. Wunderbar.
And the consequences?
I deleted the floors. I have a bunch of Windows, can I merge them?
Sure, Dan did it. Nice code!
However I do not think it can be merged just because these have a same names. What about these?: #visible?
#visible_on_new_pages?,
Page #layer_folders


Once more:
duplicate names per design.

Dan: “It makes no good sense to me why anyone would want duplicate folder names at the same level.”
Sure not. But the user is user and it is possible to make like this, and sure it will happen:

  • Tag Folder
    • Tag Folder
      • Tag Folder
        • Tag Folder
          • Tag Folder

It reminds me that they may not have paid attention to this during the design: SketchUp Extension UX Guidelines


Once more:
duplicate names per design.

I saw some code snippets on the forum, which are intended to patch the shortfall, when we import a model containing several layers and layer folders, the layer folders are not transferred. Neither can handle duplicate names.

Can you guess why?
Can you guess why the layer folders are not transferred natively?

__
My current answer is:

"Dear user, here is the latest TF Extensions, it transfers Tag Folders hierarchy . Duplicate names are not supported. "
PER DESIGN :wink:
:peace_symbol: :beers:

Ps: This is a Ruby API topic, the API retains the use of “Layer” for compatibility and is synonymous with “Tag”.

A LayerFolder is an Entity subclass, so inherits it’s #parent method.

I have no idea why YARD did not list #parent between #model and #persistent_id.
I just verified with a test at the console that #parent will return a folder’s parent folder or the layers collection.

Yes. I also tried it out. It will give a same result as the #folder method.

Regardless if it a YARD or what, the documentation does not show it.
Sure it should inherits, but the documentation show all other inherits, then why not showing this one…?

Most likely because the developers didn’t bother to put in the special comments that YARD processes.

1 Like

So it’s not miles away from being good just a yard. . :slightly_smiling_face:

Similar things have been a problem with the API docs forever. That’s why the GitHub Ruby API issues site was created, which is where complaints such as this should be filed.

When a dev is under time pressure it is horribly tempting to go lazy instead of adding useful comments. There used to be really stupid ones like (made up example) the page for get_image saying “get the image”!

619 open issues make me think they’re always under pressure.

3 Likes

That plus the fact that Trimble uses an opaque priority process to decide which issues to address. History shows that adding sexy new features generally trumps fixing long-standing bugs and documentation issues.

3 Likes

LOL, the documentation generator is YARD.

2 Likes