// ADSFiltersAndTags ` // Julianon 2018 // V1.0 // This is a script for Directory Opus. // See https://resource.dopus.com/t/a-script-to-allow-dos-wildcards-in-ordinary-dopus-buttons/28851 for development information. // CONFIGURATION: The only change that may be needed is to reduce the number of files // displayed on each screen --- increase the number at your peril. // The variable is nLinesMax at line 40. // ********** THE onInit FUNCTION ********************************************* function OnInit (initData) { initData.name = "OpenWild" initData.desc = "Open files using wildcards" initData.copyright = "(c) Julianon 2018" initData.version = "1.0" initData.default_enable = true var cmd = initData.AddCommand () cmd.name = "OpenWild" cmd.method = "onOpenWild" cmd.desc = initData.desc cmd.label = "Addin to test functions." cmd.template = "Path/K,Pattern/K,Subdir/S,Pre/K,Post/K,NoDialogueForOne/S" } // End OnInit DOpus.Output ("- - - - - - - ->") // ********** Function TestSnippetE ******************************************* function onOpenWild (scriptCmdData) { // ********** STEP 0: TWO DEFAULTS THAT CAN BE CHANGED ************************ var nLinesMax = 15 // How any files on one screenful var sDefaultPath = "Desktop" // Default path if no path is given // ********** STEP 1: OBJECTS, ARGUMENTS AND PATHS **************************** var oFunc = scriptCmdData.func var oArgs = oFunc.args var oGotArg = oArgs.got_arg var oCmd = oFunc.Command var oFSU = DOpus.FSUtil var sPath = oArgs.Path || "" // Argument: Path var sPattern = oArgs.Pattern || "*" // Argument: Pattern var bSubDir = oArgs.SubDir || false // Argument: Look in subdirectories var sPre = oArgs.Pre || "" // Argument: Text preceding the path in the command var sPost = oArgs.Post || "" // Argument: Text following the path in the command var bNoDialogueForOne = oArgs.NoDialogueForOne || false // Default is dialogue even for 1 file var oSource = oFunc.sourcetab.path var oDest = oFunc.desttab.path var oPath = "" if (oFSU.Exists (sPath)) oPath = oFSU.NewPath (sPath) if (sPath.toLowerCase () == "source") oPath = oSource if (sPath.toLowerCase () == "dest") oPath = oDest if (!oPath) { // This includes when Dest or Source does not exist oPath = DOpus.dlg.Folder ("Choose the path to search", sDefaultPath, true) if (!oPath.result) return // RETURN } sPath = String (oPath) var nN = 0 // ********** STEP 2: THE OUTER WHILE LOOP FOR PROCESSING THE ARGUMENTS ******* var bNewArgs = true var bVary = false while (bNewArgs) { bNewArgs = false var eFolderEnum = oFSU.ReadDir (oPath, bSubDir) // Get all the files var sError = "" var nError = eFolderEnum.error if (nError > 0) sError = "Error " + nError + " reading folder " var oWild = oFSU.NewWild (sPattern, "d") // Using DOS wildcards var aFiles = new Array // This will contain all the matches if (!sError || nError == 18) { while (!eFolderEnum.complete) { var oFile = eFolderEnum.Next if (oWild.Match (oFile.name)) { if (!oFile.is_Dir) // Does it match? aFiles [aFiles.length] = oFile // If it matches, add it on the end } } } eFolderEnum.Close aFiles = aFiles.sort () // aFiles now holds the sorted files nFiles = aFiles.length // ********** STEP 3: DEAL WITH SKIPPING DIALOGUE FORONE ITEM *************** if (nFiles == 1 && bNoDialogueForOne) { var sCmd = sPre + ' "' + aFiles [nN] + '" ' + sPost DOpus.Output ("Command: " + sCmd) oCmd.RunCommand (sCmd) return // RETURN } // ********* STEP 4: THE INNER WHILE LOOP FOR SELECTING FILES *************** var aSel = new Array // Boolean array for whether each file is selected for (nN = 0; nN < nFiles; nN++) aSel [nN] = false // None selected at start var oEuclid = new doDivision (nFiles, nLinesMax, 1) // The least remainder is 1 var nScreens = 1 + oEuclid.q // Number of screenfuls of files. No files --> nScreens = 0 var nLastLines = oEuclid.r // Number of files on the last screen var nScreen = 1 // The first nLinesMax or fewer files while (3 == 3) { // Exit by break or return var nSel = 0 // The number of selected files for (nN = 0; nN < nFiles; nN++) if (aSel [nN]) nSel++ DOpus.Output ("S. nSel = " + nSel + " and aSel = " + aSel) var sPresentArgs = "\r\n Path: " + sPath sPresentArgs += "\r\n Pattern: " + sPattern sPresentArgs += "\r\n Subdirectories: " + bSubDir if (sPre) sPresentArgs += "\r\n Pre: " + sPre else sPresentArgs += "\r\n Pre: ---" if (sPost) sPresentArgs += "\r\n Post: " + sPost else sPresentArgs += "\r\n Post: ---" sPresentArgs += "\r\n No Dialogue For One: " + bNoDialogueForOne if (nScreens == 0) bVary = true // No files goes straight through to Vary if (!bVary) { // bVary=true true goes straight through to Vary var oDlg = oFunc.dlg // The main looping diaolgue oDlg.title = "Choose files" if (!nSel) var sMge = "No files selected out of " + nFiles + "." if (nSel == 1) var sMge = "1 file selected out of " + nFiles + "." if (nSel > 1) var sMge = nSel + " files selected out of " + nFiles + "." sMge += sPresentArgs + "\r\n" var nFilesBack = (nScreen - 1) * nLinesMax // How many files displayed in previous screens var nFilesForward = nFiles - nScreen * nLinesMax // To be displayed in forward screens var nLines = nLinesMax // How many lines on all but the last screen if (nScreen == nScreens) nLines = nLastLines // If it's the last screen of files if (nScreen > 1) // If it's not the first screen sMge += "\r\nPreceded by " + nFilesBack + " files . . ." for (nN = nFilesBack; nN < nFilesBack + nLines; nN++) { sMge += "\r\n" + String.fromCharCode (65 + nN - nFilesBack) + ". " + aFiles [nN] if (aSel [nN]) sMge += " --- SELECTED" } if (nScreen < nScreens) { // If not the last screen if (nFilesForward == 1) sMge += "\r\n . . . Followed by 1 file." else sMge += "\r\n . . . Followed by " + nFilesForward + " files." } sMge += "\r\n\r\nToggle the selection of files, or vary the arguments. " sMge += "\r\nPress Run to open the selected " if (nSel == 1) sMge += "file." else sMge += "files." oDlg.message = sMge var sBns = "|" // Prepare the buttons var aActions = new Array // Buttons and actions aActions [0] = "X" if (nSel) { sBns += "&Run|" aActions [1] = "R" } for (nN = nFilesBack; nN < nFilesBack + nLines; nN++) { sBns += "&" + String.fromCharCode (65 + nN - nFilesBack) + "|" aActions [aActions.length] = nN - nFilesBack } if (nSel < nFiles) { sBns += "&Select all|" aActions [aActions.length] = "S" // Select all } if (nSel > 0) { sBns += "Deselec&t all|" aActions [aActions.length] = "T" // Deselect all } if (nScreen < nScreens) { sBns += "For&ward|" aActions [aActions.length] = "W" // Forwards through the screen } if (nScreen > 1) { sBns += "&Z. Back|" aActions [aActions.length] = "Z" // Backwards through the screen } sBns += "&Vary|" aActions [aActions.length] = "V" // Vary the arguments var sPad = "" for (nN = nLines; nN < 7; nN++) sPad += "- - - - - " oDlg.buttons = sBns + sPad + "E&xit" + sPad + "|" var nChoice = oDlg.show // Act on the choice var sAction = aActions [nChoice] if (sAction == "X") return // Exit --> RETURN if (sAction <= nLines) // Toggle the selection of the file aSel [nFilesBack + sAction] = !aSel [nFilesBack + sAction] if (sAction == "S") // Select all for (nN = 0; nN < nFiles; nN++) aSel [nN] = true if (sAction == "T") // Deselect all for (nN = 0; nN < nFiles; nN++) aSel [nN] = false if (sAction == "W") nScreen++ // Forward to Next screen if (sAction == "Z") nScreen-- // Back to previous screen if (sAction == "R") break // Run --- break exits the while loop if (!nFiles || sAction == "V") bVary = true // Vary the arguments } // END if (!bVary) // ********** STEP 5: USER CHOOSES Vary TO CHANGE THE ARGUMENTS ************* if (bVary) { bNewArgs = true // This activates the outer while loop again. var oDlgV = oFunc.dlg oDlgV.title = "Vary arguments" var sMge = "" if (!nFiles) var sMge = "No files fit the criteria." if (nFiles == 1) var sMge = "1 file fits the criteria." if (nFiles > 1) var sMge = nFiles + " files fit the criteria." sMge += sPresentArgs + "\r\n\r\nChoose which argument to vary." sMge += "\r\nPress Resume to resume with the new arguments." oDlgV.message = sMge var sBns = "|&Resume|&GoTo|&Path|" // Prepare the buttons var aActionsV = new Array ("X", "R", "G", "P") // Buttons and actions if (oPath.test_parent) { sBns += "&. . Parent|" aActionsV [aActionsV.length] = "." } if (oSource) { sBns += "&Source|" aActionsV [aActionsV.length] = "S" } if (oDest) { sBns += "&Dest|" aActionsV [aActionsV.length] = "D" } sBns += "P&attern|" if (bSubDir) sBns += "No S&ubdirectories|Pr&e|P&ost|" else sBns += "S&ubdirectories|Pr&e|P&ost|" if (bNoDialogueForOne) sBns += "D&ialogue for one|E&xit|" else sBns += "No D&ialogue for one|E&xit|" aActionsV = aActionsV.concat ("A", "U", "E", "O", "I") oDlgV.buttons = sBns var nChooseV = oDlgV.show // Act on the choice var sActionV = aActionsV [nChooseV] if (sActionV == "X") bNewArgs = false // Exit if (sActionV == "R") bVary = false // Resume --- return to main menu if (sActionV == "G") { // Go to the path, then exit sCmd = ("Go " + oPath) DOpus.Output (sCmd) oCmd.RunCommand (sCmd) return // RETURN } if (sActionV == "P") { // Reset the path var oPathChoose = oDlgV.Folder ("Choose the path to search", oPath, true) if (oPathChoose.result) { oPath = oPathChoose sPath = String (oPath) } } if (sActionV == ".") { sPath = oPath.pathpart oPath = oFSU.NewPath (sPath) } if (sActionV == "S") { oPath = oSource sPath = String (oSource) // Reset the path as source } if (sActionV == "D") { oPath = oDest sPath = String (oDest) // Reset the path as destination } if (sActionV == "A") { // Reset the pattern var oDlgB = DOpus.dlg oDlgB.title = "Choose pattern" oDlgB.message = "Choose the new pattern." oDlgB.max = 256 oDlgB.defvalue = sPattern oDlgB.buttons = "|&OK|&Cancel|" var nChoiceB = oDlgB.show if (!nChoiceB) bNewArgs = false else sPattern = oDlgB.input } if (sActionV == "U") bSubDir = !bSubDir // Reset subdirectories switch if (sActionV == "E") { // Reset the text before the filename var oDlgB = DOpus.dlg oDlgB.title = "Choose Pre" var oMsgB = "Choose the text that comes before the filepath.\r\n\r\n" oDlgB.message = oMsgB + "Add any space between this text and the filepath." oDlgB.max = 256 oDlgB.defvalue = sPre oDlgB.buttons = "|&OK|&Cancel|" var nChoiceB = oDlgB.show // bNewArgs = false if (nChoiceB) sPre = oDlgB.input } if (sActionV == "O") { // Reset the text before the filename var oDlgB = DOpus.dlg oDlgB.title = "Choose Post" var sMsgB = "Choose any text that comes after the filepath.\r\n\r\n" sMsgB += "Add any space between the filepath and this text." oDlgB.message = sMsgB oDlgB.max = 256 oDlgB.defvalue = sPost oDlgB.buttons = "|&OK|&Cancel|" var nChoiceB = oDlgB.show if (!nChoiceB) bNewArgs = false else sPost = oDlgB.input } if (sActionV == "I") bNoDialogueForOne = !bNoDialogueForOne // NoDialogueForOne if (sActionV = "R") break // This goes to the outer loop and resets everything } } // END while } // END outer while // ********** STEP 6: ISSUE THE FINAL COMMAND ********************************* for (nN = 0; nN < nFiles; nN++) { if (aSel [nN]) { var sCmd = sPre + ' "' + aFiles [nN] + '" ' + sPost DOpus.Output ("Command: " + sCmd) oCmd.RunCommand (sCmd) } } } // ********** Division with a chosen least remainder ************************** function doDivision (nDividend, nDivisor, nLeastRemainder) { // Requires "new" // Intended only for integers. If nDivisor = 0, then this.q and this.r are NaN // No return, so usage is: var oDivisor = new doDivision (nDividend, 5, -4) if (arguments.length < 3) var nLeastRemainder = 0 // Default remainders are 0, 1, 2, . . . , (nDivisor-1) if (arguments.length < 2) var nDivisor = 2 // Default divisor = 2, for odd and even this.n = nDividend // TheDividend this.d = nDivisor // TheDivisor this.r = (nDividend - nLeastRemainder) % nDivisor // Least remainder correction // Note: The % operator often returns a negative integer. if (this.r < 0) // Make the remainder positive or zero this.r = this.r + Math.abs (this.d) // Now the least remainder is zero this.r = this.r + nLeastRemainder // Now the least remainder is nLeastRemainder this.q = Math.round ((this.n - this.r) / this.d) // This is the quotient } // ********** Counts true boolean entries of an array ********** function doCountArray (aArray) { var nTrue = 0 var nN = 0 for (nN = 0; nN < aArray.length; nN++) if (aArray [nN] === true) nTrue++ return nTrue } // End function