Close all tabs matching a path wildcard

Overview


This scripts adds a new command to Opus: CloseAllTabs

The CloseAllTabs command takes a path or wildcard and will close all folder tabs which match. Listers will be closed entirely if all their tabs match.

For example, CloseAllTabs X:\* will close all folder tabs in or below X:\.

This can be useful if you just want to clean up a lot of folder tabs at once, or before unmounting an encrypted drive which was mounted as non-removable (where a tab pointing at the drive may mean the drive is considered in-use).

Installation:


Requires Directory Opus 11.3 beta 1 (22/Apr/2014) or above.

Open Preferences / Toolbars / Scripts, then download CloseAllTabs.osp (below) and drag it to the list.

CloseAllTabs.osp (1.56 KB)
(If you want to edit it, the .osp file is really a zip file containing the script, with the .zip extension changed to .osp. Change the extension back and you can extract the .vbs file inside and open it in any text editor. You can drop .vbs scripts into the Opus script list directly, without creating an .osp file; the only reason .osp was used here is to make it easier for you to download, since .vbs files are typically blocked.)

History:

  • v1.1 (24/Apr/2014): Better handling of \ at the ends of paths.
  • v1.0 (22/Apr/2014): First release

Usage:


Once installed, a new CloseAllTabs command will be available in the Button Editor, Hotkey Editor, and so on.

The CloseAllTabs command takes a single argument, which is the path or wildcard you wish to close. As usual, use quotes if the argument contains spaces.

CloseAllTabs "C:\Program Files" -- Close all tabs showing C:\Program Files.
CloseAllTabs C:\* -- Close all tabs showing C:\ or folders below C:\.
CloseAllTabs C:\*\* -- Close all tabs showing folders below C:\ but not C:\ itself.

The script itself:


If you just want to use the script, the CloseAllTabs.osp download above is probably easier.

The script code is reproduced here so that people looking for scripting techniques on the forum can browse the script code without having to download and extract the .osp file.

option explicit

' Close All Tabs
' (C) 2014 Leo Davidson
' 
' This is a script for Directory Opus.
' See http://www.gpsoft.com.au/DScripts/redirect.asp?page=scripts for development information.

' Called by Directory Opus to initialize the script
Function OnInit(initData)
	initData.name = "Close All Tabs"
	initData.desc = "Close all tabs, in all listers, with paths matching a wildcard"
	initData.copyright = "(C) 2014 Leo Davidson"
	initData.version = "1.1"
	initData.default_enable = true
	initData.min_version = "11.3.1"

	Dim cmd
	Set cmd = initData.AddCommand
	cmd.name = "CloseAllTabs"
	cmd.method = "OnCloseAllTabs"
	cmd.desc = "Close all folder tabs, in all listers, with paths matching a wildcard."
	cmd.label = "Close All Tabs"
	cmd.template = "PATH"
	cmd.icon = "closetab"
End Function

' Helper function
Function TerminatePath(p)
	TerminatePath = p
	If (Len(TerminatePath) > 0) Then
		Dim c
		c = Right(TerminatePath,1)
		If (c <> "\" And c <> "/" And c <> "*" And c <> "?") Then
			TerminatePath = TerminatePath & "\"
		End If
	End If
End Function

' Implement the CloseAllTabs command
Function OnCloseAllTabs(funcData)

	' The path argument is required, else we don't know which tabs to close.
	If (Not funcData.func.args.got_arg.path) Then
		OnCloseAllTabs = True ' Signifies failure
		Exit Function
	End If

	' Create a wildcard out of the path argument. This will be used to test each tab's path.
	Dim wildPath
	Set wildPath = DOpus.FSUtil.NewWild(TerminatePath(funcData.func.args.path), "d")

	' We can't close listers or tabs while enumerating them, as it causes the enumeration to go wrong.
	' We also need to separately handle the case where the entire lister is to be closed, as closing the last tab
	' via Go TABCLOSE won't do anything.

	' So, we build up a Command object with a line to close each tab we want to close (only those from listers where at least one tab is not closed)
	' and we also build up a vector of Listers which we want to close entirely (those where every tab is to be closed, with none left).
	' After we finish enumerating tabs and listers, we run the command to close the tabs, then loop through our vector of Listers to close those as well.

	Dim anyTabs
	anyTabs = False

	Dim allTabsInLister

	Dim lister
	Dim tab

	Dim cmd
	Set cmd = DOpus.CreateCommand

	Dim tabsInLister
	Set tabsInLister = DOpus.NewVector

	Dim listersToClose
	Set listersToClose = DOpus.NewVector
	
	For Each lister in DOpus.listers

		allTabsInLister = True

		For Each tab in lister.tabs
			If (wildPath.Match(TerminatePath(tab.Path))) Then
				' This tab needs to be closed.
				tabsInLister.push_back tab
			Else
				' At least one tab in this lister is not being closed.
				allTabsInLister = False
			End If
		Next

		If allTabsInLister Then
			' All tabs in the lister are being closed, so we will close the whole lister instead.
			listersToClose.push_back lister
		Else
			' Only some of the tabs in the lister are being closed, so add them to the command.
			For Each tab in tabsInLister
				anyTabs = True
				cmd.AddLine "Go TABCLOSE " & tab
			Next
		End If

		tabsInLister.clear
	Next

	If anyTabs Then
		' Run the command to close all the tabs (except ones where the whole lister will be closed).
		cmd.Run
		' Clear the Command object's lines, so we can re-use it.
		cmd.Clear
	End If

	For Each lister in listersToClose
		' Close each of the listers that need to be closed.
		cmd.SetSourceTab lister.ActiveTab
		cmd.RunCommand "Close"
	Next

End Function

That's something I was about to script as well, so I like that very much! o) Thank you for sharing this!

It is just perfect for the folder-context menu I think (as long as the tab-context cannot be edited o).

I think there's an option to make the tab show the folder context menu when you right-click the label. (With the icon part still showing the menu the whole tab shows by default.)

Yep, thanks! I'm using that option already and it's great to have. An extendable tab-context would be a nice addition though, as there is a "Close Tab" entry already in there, and the new "CloseAllTabs" would feel very comfortable in there too, I think. But now let's stay ot. o)

This is the new "Close" menu I added to "All Folders"-filetype. I had some trouble at first, so here is an example code which seems to work fine for me. It first closes all child-tabs (tabs showing subfolders of the current tab-folder) and after that, closes all tabs, showing the same folder on which the code was run on. Maybe Leo, it makes sense to trim the trailing slash automatically in the script, to get rid of the noterm-thing?

@nofilenamequoting CloseAllTabs "{f|noterm}\*" CloseAllTabs "{f|noterm}"

I've uploaded a new version (v1.1) that takes care of \ at the end of paths, so the noterm should no longer be needed in your example.

(Remember to change {f|noterm}* to {f}* without the extra \ if you want to remove the noterm from that line.)

Thank you! That works! o)
Being able to close a tab and all tabs showing subfolders in one go is a nice addition as well (maybe it was possible already, but there was no example on how to do it). o)

I'm looking for a button that does "Close all tabs except [the ones specified]". Is this easily possible with any built-in command or is a script like the one above required?