Finder 'completely expanded'

Hello.

I used the back and forward button! :slight_smile: And it hasn’t any cache really, If I go back again, the folders of the window are collapsed.

After I have taken care of sane working with a browser window, I may have a go in selecting folders outside Finder for the hope of speeding things up further. I just remembered a way that may speed up stuff, by performing the folder selection in perl, thanks to Daniel Jalkut.

I’ll head back to the Unbelievable boring reading for now. :frowning:

Edit

I don’t have to use perl, as I remembered/figured out how to make a script object that I can run, for the hope of making Finder selecting items faster. :slight_smile:

Hello.

The script in post #12 is updated.

I have just changed the script to make it work as fast as possible, it turned out that finder does select its folders the fastest way.

I tried to select folders like below, by creating a script object, containing the select statement for the folders in the current finder window:

set X to (current date)
tell application id "MACS"
	activate
	tell its front window
		if current view of it is not list view then
			set current view of it to list view
		end if
		set pxFolderPath to POSIX path of (its target as alias)
	end tell
end tell
set selFolderStatement to (do shell script "cd " & quoted form of pxFolderPath & "; find  -P . -depth 1 -prune  -type d  -print |grep -Ev '(app \\(|bundle'\\$'|app'\\$'|prefPane'\\$'|vpdoc'\\$')' |sed -n 's_^\\./\\([^/]*\\)_folder \\\\\"\\1\\\\\"_p' |tr '
' ','")
try
	set selFolderStatement to text 1 thru -2 of selFolderStatement & " "
on error
	return -- nothing to be done, no folders to select
end try
set scriptbody to "{\"tell application id \\\"MACS\\\"
	tell its front window
		select {" & selFolderStatement & "}
		tell application id \\\"sevs\\\"
			key down command
			key down option
			key down shift
			key code 124
			key up shift
			key up option
			key up command
		end tell
		select its first item
	end tell
	
end tell\"}"
set b to (run script scriptbody)
try
	run script b
on error e number n
	tell application "SystemUIServer"
		activate
		display dialog "You probably need to add to the grep statement in tree.app in order to exclude a bundle of some kind, the error message is on the clipboard" buttons {"Ok"} default button 1 with icon stop
		set the clipboard to (e & n)
	end tell
end try
set Y to (current date) - X
log Y

This turned out to be one second slower however, when I wanted to expand a folder with 158 subfolders, in comparision to the old way of letting finder handle it.

I deleted the “working.” dialogs, as I never managed to unblock them, I also seemed to create a zombie process in the process (pun…) that seemed to get the app hang. But, if the user moves the mouse slightly away from the toolbar cursor, then the beach-ball should appear immediately, and that is progress good enough for me. :slight_smile:

The cache I talked about, was somewhat badly worded, I really meant the script object that contained the id’s of the windows, now it contains both the id of the window, and its target as text, so you must delete the old one before starting the new version of the toolbar-applet.

And if there is someone to be thanked here, hey! it was your idea, I love it, and, hadn’t it been for the other guys around here, I never would have been able to make it. :slight_smile:

Hi McUsrII,

Just downloaded the final version of your script. The other version was a lot more complicated than I though it would be. :slight_smile: Very interesting.

If you don’t know about it yet, There is a new scripting addition for Mountain Lion, that I just downloaded yesterday. Notifications Scripting. It looks kind of easy to use and sounds like what I was looking for to control Notification Center through AppleScript. I don’t know if you’re running several OSs, but you might want to look into this. Not sure if it can delete notifications from Growl. Also, I don’t know if it’s backwards compatible.

Later,
kel.

Hi McUsrII,

I’m getting an errors in the last version. Something like "can’t get item 8 (or 10) of {some list items}. Tried to trap the error, but couldn’t. So, maybe it’s happening in the other script?

BTW, all I did was add a simple comparison timer with Python and the error block.


-- http://macscripter.net/viewtopic.php?pid=161306#p161306
-- 2013 © McUsr after idea by kel, and put in public domain, in sofar that  you may not post this elsewhere.
property scriptpath : (path to temporary items folder from user domain as text) & "net.mcusr.treevals"
property FinderIcon : a reference to file ((path to library folder from system domain as text) & "CoreServices:Finder.app:Contents:Resources:Finder.icns")
global outlineStates
on run
	tell my runner to run
end run

script runner
	on run
		try
			set t1 to (do shell script "python -c 'import MacOS; t=MacOS.GetTicks(); print t'")
			set mustExpand to false
			set L to {0, ""} -- initial values since we are filling a list
			tell application id "MACS"
				activate
				tell its first Finder window to set L to {its id, its target as text}
			end tell
			try
				set outlineStates to load script alias scriptpath
			on error
				script treeWinList
					property WindowIDList : {}
				end script
				set outlineStates to treeWinList
			end try
			
			-- if we find the id of the window, but different target, 
			-- then we'll change the target, but keep the id.
			-- if we don't find the id, we'll keep it!
			set ind to indexOfItem((item 1 of L), outlineStates's WindowIDList)
			
			if ind = 0 then
				set end of outlineStates's WindowIDList to L
				set mustExpand to true
			else if item 2 of item ind of outlineStates's WindowIDList ≠ item 2 of L then
				set item 2 of item ind of outlineStates's WindowIDList to item 2 of L
				set mustExpand to true
			end if
			
			if mustExpand then
				my expand_window()
			else
				my revert_window()
				if ind = 1 then
					set my outlineStates's WindowIDList to rest of my outlineStates's WindowIDList
				else if ind = length of my outlineStates's WindowIDList then
					set outlineStates's WindowIDList to items 1 thru -2 of outlineStates's WindowIDList
				else
					set outlineStates's WindowIDList to items 1 thru (ind - 1) of outlineStates's WindowIDList & items (ind + 1) thru -1 of outlineStates's WindowIDList
				end if
			end if
			store script outlineStates in scriptpath replacing yes
			set t2 to (do shell script "python -c 'import MacOS; t=MacOS.GetTicks(); print t'")
			display dialog (((t2 - t1) / 60) as string)
		on error err_msg number err_num
			error err_msg number err_num
		end try
	end run
	
	on expand_window()
		tell application id "MACS"
			activate
			tell its front window
				select
				if current view of it is not list view then
					set current view of it to list view
				end if
				select every folder of it
				tell application id "sevs"
					key down command
					key down option
					key down shift
					key code 124
					key up shift
					key up option
					key up command
				end tell
				select its first item
			end tell
		end tell
	end expand_window
	
	on revert_window()
		tell application id "MACS"
			activate
			tell its front window
				select
				if current view of it is not list view then
					set current view of it to list view
				end if
				select every folder of it
				tell application id "sevs"
					key down command
					key down option
					key down shift
					key code 123
					key up shift
					key up option
					key up command
				end tell
				select its first item
			end tell
		end tell
	end revert_window
	
	on indexOfItem(theItem, theList) -- Emmanuel Lévy
		considering case
			set text item delimiters to return
			set theList to return & theList & return
			set text item delimiters to {""}
			try
				-1 + (count (paragraphs of (text 1 thru (offset of (return & theItem & return) in theList) of theList)))
			on error
				0
			end try
		end considering
	end indexOfItem
end script

Editted: Also, the first run is ok, but when I unfold the list it errors.

just a note:

it’s strongly recommended to never use relative paths (path to .) in properties.
In some environments e.g. saving the script as application the values are persistent and the script will fail on other computers.

PS: the keyword its as a reference to the parent object in a tell block in ONLY needed if the terminology is ambiguous in the same application. In this script it’s just syntactic sugar like the


tell its the first Finder window to set the L to {its the id, its the target as text}

this does exactly the same


tell first Finder window to set L to {id, target as text}

Hello, I really have no idea, I assume you have deleted the old “net.mcusr.treevals” as I explained you had to do it.

I run the toolbar-applet here, and it works flawlessly. Maybe you should try to run it from the editor, and see what goes wrong there?

You may also want to either overwrite or rename the old version, or add a short-version string to the property list file, to assure that it is indeed the latest version that runs, especially since the contents of the net.mcusr.treevals script object aren’t compatible between the two versions.

I hope you figure out whats wrong.

@ Stefan: Syntactic sugar is nice, as long as it isn’t overdone, the its finder window, is really overdoing, and I’m going back to fix it!

I will also consider the relative paths in scripts, should I distribute in compiled form. Thanks for the reminder. :slight_smile:

Edit:

I found the error kel, I’ll be back with a fix.

I forgot about this:

On the side. A strange thing just happened if I remember right. I ran a compiled script from the Script Editor with ‘run script’ and it kept displaying “1”.


property x : 0

set x to x + 1
tell application "System Events"
	display dialog x
end tell

Then I ran it with this from the Script Editor:


set desk_path to (path to desktop) as string
set pp to POSIX path of (desk_path & "IncX.scpt")
do shell script "osascript " & (quoted form of pp)

and the property value was saved from then on. I think this is strange.

gl,

Hello.

The toolbar-applet in post #12 is fixed and updated.

I got the same error as well, I chose a “wrong handler” for finding the index of the item obviously. I could have had made something more sophisticated than what I have put into it now, but I think it will suffice.

The error was, that the list consisting of two items, would end up on two different lines, leading to the index of items, which the previous indexOfItem handler returned, gets out of sync. (The handler is really meant for only one item in each element of the list, no sublists). I started to use the previous handler, when I had the idea of coercing the items into text, well, I deviated from that scheme, but kept the handler.

Know everything should work as it is supposed to, with the correct handler and without superfluos circumloitions of syntactic sugar. :slight_smile:

You really should return from a script, in order to get the property saved with it, but I think your problem with the property is strange too. :expressionless:

Good Night!

Hi McUsrII,


set f to choose folder

tell application "Finder"
	activate
	open f
	tell front window
		set current view to list view
	end tell
end tell

ignoring application responses
	tell application "System Events"
		keystroke "a" using command down
		delay 1
		key code 124 using {command down, option down, shift down}
	end tell
end ignoring

This my simple version. The other versions don’t work a anymore for some reason.

Hello kel.

I am sorry to hear that, well, anyway, I have followed Stefan’s instructions about not using properties for storing a copy, and I zipped it, and put it into my dropbox, it can be found here should you be interested. You must doublecilick on it from finder to make it register with launchservices, when the applet is placed in its destination.

Edit

I’ll find a a way to track if finder is busy, and bail out with a message about “please try again later”, if it is. I won’t post it, before I have a readme file ready.

Hello.

I have updated the script in post #12 once again with a handler that checks if finder is busy before the button gets hit, I have also updated the zipfile with the applet to include a small, but hopefully sufficient readme file.

The zip file can be found here.

Enjoy

PS. If you made the first version, and have not followed the thread, and have installed the latest version, and experienced that something doesn’t work, be sure to delete the file ~/Library/Caches/TemporaryItems/net.mcusr.treevals and try again . :slight_smile:

Hello.

I added a shell script to invoke tree.app from the commandline, showing a tree of the current directory, if the window showing the current working directory is expanded, it becomes contracted.

Same link as above.

Hello.

I have updated it once more: Changed from activation of finder to selecting its first window, in order to leave the screen as stable as possible. I had suddenly windows popping up on my second monitor, while the toolbar-applet ran.

The zip file can be found here.

Edit

I removed a -g switch on the first open statement of the tree shell-script to make it work better with tree.app

Hello.

I promise this is the last version, the link above should still work for getting this.

I have added code to tell that the applet indeed works, this may be to your taste, or not:

tell application id "MACS"
	set uIconPath to POSIX path of (path to resource "Finder.icns")
	do shell script "qlmanage -p " & uIconPath & " >/dev/null 2>&1 &  sleep 0.3 ; kill -9 $!"
end tell

Promises,promises… :slight_smile:

The slow tops command, that needed a delay of 1 second to perform a sample of cpu usage in the start really bugged me, so I found a way to let ps handle it, alot faster.

ps -ArmC -O %cpu

is the incatation that delivers with haste.

There can’t be more to add, nor to subtract by now!

The zip file can be found here.

Edit I increased the cpu treshold to 8%, since it seems to work fine, even when Finder is currently using 8 percent cpu.

This is the final post!

I increased the cpu treshold to 8%, since it seems to work fine, even when Finder is currently using 8 percent cpu.

It can be found by the link in the post above.

Hi McUsrII,

I downloaded your tree script and it’s working great. Very fast and helpful finding which branch to go to. That icon is nice. I didn’t expect it to work perfectly short of turning off everything else in the Finder.

Thanks for all your help,
kel.

:smiley:

Thank you too! I am actually thinking of trying to change icons runtime, and getting some “3-D” icons, so it seems to have a button pushed in while it runs. (It will be tough getting rid of the Finder-face though. :))

I’ll at least try to change icons runtime, soon, and we’ll see.

The caveat is if the user tries it on a folder that is too deeply nested, and has to restart Finder, then the icon will be wrong, until he/she runs it again. I can’t evade running this on a single thread, or Finder won’t respond correctly to the fictive keystrokes, or so I think. It is another experiment that has to be done as well.

Edit

It is also a question of how much time is going to be spent on changing that icon.

The scheme is to have an isrunning variable in the script, and start out by invoking a helper appliction, that may change the icon file in the parent, and update its version property, before it in turns calls the parent via open -new instance of parent, which in turn runs the run handler of the parent, but which will quit instantly, since the isRunning is true. What we have achieved by then, is hopefully to have reregistered the application, and forced Finder to update the icon on the toolbar.

The idea is of course to keep the button pressed, while it is working, and let it go back up again, when the toolbar-applet is done working, and not to display the “expandedness” of the folder, which would come out of sync quickly.

Hello.

I actually figured out a “re-entrant” scheme for the applet to change the icon on the finders toolbar, but that does only help so much, as for changing the icon of the applet, as I can’t seem to figure out a way to make the toolbar of Finder to update. (Just try for yourself manually).

So, the other option is of course to use StefanK’s progress bar, but I am reluctant to do that, since the times for expanding/contracting a folder varies so wildly.

So, it ends here, shouldn’t anybody have some better ideas.

Great Minds think alike! :slight_smile:

Hi McUsr,

It’s still working great and Haven’t had any errors. The tree icon in the toolbar hasn’t changed yet. Just expanded the home folder and it only took a few seconds for 2500+ items! Also, there’s no need for a progress item, you can see that the script is working in the status bar at the bottom.

Editted: I take that back. It’s starting to hang and doesn’t unexpand. I’ll try and see what’s going on. Think I understand your script now. One thing I don’t understand is the "qlmanage’ shows up in the menu bar next to the Apple when it hangs. Don’t know where that comes from.

Thanks a lot,