GP SoftwareTwitter
Opus FAQsManualCommandsObjects

File equivalent of {rightpath}/{leftpath}

Is there a file equivalent of {rightpath}/{leftpath}, that returns the left hand and right hand folders, irrespective of source/destination.

I would like to return the left hand file or right hand file, not the folder.

Thanks,

Steve

EDIT 2011: There's a much easier way for most situations. See my 2011 reply, below.

There isn't but you can work around it by creating a user command.

In the screenshot below you can see my "compare left vs right" toolbar button in the top Command Editor window. That button runs this command:

Set SOURCE=Left dopusrt /cmd BeyondCompareSFvDF @nodeselect

Which means it ensures that the left side is the source, then runs another command via dopusrt and doesn't deselect any files.

dopusrt is used so that the second command (BeyondCompareSFvDS) runs after the first command. If dopusrt was not used then the second command would run inside of the first one and would think that the source & destination were as they were at the start of the command. So using dopusrt makes the second command "see" the new source.

The @nodeselect is so that the file selection is still there when the second command runs.

The second command, BeyondCompareSFvDS is a user command which I created. You can see it in the bottom Customize and Command Editor windows. It simply runs BC on the source and destination file:

"C:\Program Files\Beyond Compare 3\BComp.exe" {filepath$} {filepathdest$} @nodeselect

In this second button the @nodselect is optional. I have it there because I often want to do something after comparing a file, or compare the same two files again, so I don't want anything deselected.


That's exactly what I want, and for using Beyond Compare as well!

Thanks,

Steve

Not sure why I didn't think of this before, but there is a much easier way to do this which does not require a user-command:

"C:\Program Files\Beyond Compare 3\BComp.exe" {leftpath}{file} {rightpath}{file}

Other advantages, compared to my earlier method:

[ul][li]If you don't have any files selected then this will compare the left and right directories.

[/li]
[li]It lets you compare more than one pair of files at once by selecting multiple files. (Not sure if the earlier method did or not.)[/li][/ul]

Disadvantages:

[ul][li]It only works with dual-display windows (not between two separate single-display windows).

[/li]
[li]It assumes the two files you want to compare have the same names. When that isn't the case, you still need the older method if you want to guarantee left and right don't get swapped over.[/li][/ul]

Yeah, that's the reason I haven't been able to use this method... It's when I've got differently named files, have left and right lister paths opened and intuitively expect the same left/right orientation in my diff tool when it opens that this causes me grief.

It's an annoyance more than a real problem, but it'd be really nice not to have that initial WTF moment in the diff tool when I see a difference I didn't expect on one side or the other. I had tried changing my command to use {fd} {f} instead of the other way around, since I am most often selecting the file in the right / dest path last, making it the new source path before clicking the button. But I also sometimes select the file in the left / top path last sometimes as well. It all just depends on the situation, and it's something that I'd rather not even have to think about one way or another.

I think I had also submitted a feature request awhile back for {leftfile} and {rightfile} control codes for this same reason. Somehow, my old method of setting the left side as the source before calling the user command seems to sometimes break... not sure how or why, other than assuming it to have been a "timing issue" of some sort.

You can use the previous method in this thread (the one with the user-command) for when the filenames aren't the same in both sides. It ensures left/right remain consistent.

{leftfile} and {rightfile} would still be handy, I agree. Even more so if {rightfile} could have an argument (or use @ifset) that told it to use the same name as the leftfile if there is no selected right-file. Then one button could do almost everything (except comparing two files in the same side).

[quote="leo"]You can use the previous method in this thread (the one with the user-command) for when the filenames aren't the same in both sides. It ensures left/right remain consistent.

{leftfile} and {rightfile} would still be handy, I agree. Even more so if {rightfile} could have an argument (or use @ifset) that told it to use the same name as the leftfile if there is no selected right-file. Then one button could do almost everything (except comparing two files in the same side).[/quote]

I am on a quest to create a unified DIFF button. so my thoughts

What I want to do is essentially combine steps 1,2,3 from Beyond Compare buttons

  1. for comparing two files selected in different file displays:
    1.1 for comparing two files with identical names in different file displays:
  2. for comparing two files within same lister:
  3. for comparing two folders in two different file displays:

I use leo optimization for combine one and three, but it only works with files of identical names File equivalent of {rightpath}/{leftpath}
(i.e. 1.1) and not for the general case 1

The logic is simple. Here's some pseudocode

if more than 1 file selected in source
 @set args={allfilepath} (handle case 2)
else if no {destfilepath} exists, 
  @set args= {leftpath}{file} {rightpath}{file} (handles case 1.1 and 3)
  else 
   @set args= {filepath} {destfilepath} (handles case 1)

"%app%/command.exe" {$args}

other thoughts
How to check if any files are selected in dopus commands?
does
@ifset:{destfilepath}
this work?

Also how can you set a variable for the entire toolbar?
Do you have to use a usercommand?

If you want a fully unified diff button, the easiest thing to do would be to pass all the possible details to an external script which then sees which details it has been passed and applies some logic to them to decide what command to run.

Ok sounds good. Can you give me an example of a script that can be sent multiple parameters (that is not a rename script!)?

Would it be something like this?

@nodeselect
"%app%/script.vbs" {filepath} {destfilepath} {leftpath} {rightpath} {file} {allfilepath}

What happens when no file is selected. is {filepath} blank then? How will the script know which parameter was passed where? Since {allfilepath} is space seperated? Can we do named pararmeters? like /f {filepath} or -f {filepath} or --f {filepath} .

What scripts can you execute? Anything that the OS supports right? so be default it'll be .vbs or .cmd unless you install python, javascript and others ...etc.

Can you point me to a good example script? Nothing in the documentation other than rename scripts.

Taking a step back, the problem can be understood as: changing behavior depending on selections made by the user. And dopus allows a ton of vareity in selections! Is there an inbuilt variable that explains this state? like {selections} and maybe it could have values like:

single lister 0 file/folder selected 1 file/folder selected x file/folder selected dual lister same as above but for SRC & DEST listersso a total combination of 6 states. 0 0 0 1 0 x 1 0 1 1 1 x x 0 x 1 x x
just some idea.

Found this great tutorial youtube.com/watch?v=biLRcTmW3G0 made by you. So I'll take a look at that.

Here's a quick script to show arguments passed to it.
It turns out when parameters are blank, the argument order will change. SO vbs is not a good alternative to use here. :confused:

option explicit
' Will display all arguments provided to script for debugging purposes
' example usage
' Cscript //x ShowArgs.vbs test1 23 asdf asdf "afda f df f"
' @runonce:WScript.exe "{alias|dopusdata}Scripts/ShowArgs.vbs"  -f "{filepath}" -fd "{filepathdest}" -l "{leftpath}" -r "{rightpath}" -n "{file}" -a "{allfilepath}" ignore "{sourcepath$|noterm}" "{alias|dopusdata}Scripts\Actors.txt" "{alias|dopusdata}Scripts\ActorSubdirs.txt"
' @runonce:WScript.exe {alias|dopusdata}Scripts/ShowArgs.vbs  -f {filepath} -fd {filepathdest} -l {leftpath} -r {rightpath} -n {file} -a {allfilepath}

Dim objIEDebugWindow
' Debug "This is a great way to display intermediate results in a separate window."

Dim args
set args = WScript.Arguments
DebugArray args


Sub DebugArray(arObj)
	dim iCount
	if (arObj.Count <= 0) then exit sub
	Debug("Total Elements:" & arObj.Count)
	for iCount = 0 to arObj.Count - 1
		Debug(iCount & ":" & arObj.Item(iCount))
	next 
End Sub 


Sub Debug( myText )
  ' Uncomment the next line to turn off debugging
  ' Exit Sub

  If Not IsObject( objIEDebugWindow ) Then
    Set objIEDebugWindow = CreateObject( "InternetExplorer.Application" )
    objIEDebugWindow.Navigate "about:blank"
    objIEDebugWindow.Visible = True
    objIEDebugWindow.ToolBar = False
    objIEDebugWindow.Width   = 900
    objIEDebugWindow.Height  = 600
    objIEDebugWindow.Left    = 10
    objIEDebugWindow.Top     = 10
    Do While objIEDebugWindow.Busy
      WScript.Sleep 100
    Loop
    objIEDebugWindow.Document.Title = "IE Debug Window"
    objIEDebugWindow.Document.Body.InnerHTML = _
                 "<b>" & Now & "</b></br>"
  End If

  objIEDebugWindow.Document.Body.InnerHTML = _
                   objIEDebugWindow.Document.Body.InnerHTML _
                   & myText & "<br>" & vbCrLf
End Sub

The script should be able to work that out, it has a prefix before each argument and can detect if the next argument is a prefix rather than a filepath.

Yes, but that would be too much work! Instead I remember python's optparse library.
I did the same thing in python, so take a look

#!/usr/bin/python
import os, sys, argparse, logging, subprocess

def selectarguments(args):
	''' This selects the arguments that should be passed on to the final diff application, and returns only that
	The logic is based on what the user has selected from the various choices he has in the DOpus lister
	'''
	'''
	These are the cases as I see it for comparing files/folders
	1. for comparing two files/folders selected in different file displays:
	1.1 for comparing two files with identical names in different file displays:
	2. for comparing two files within same lister:
	3. for comparing two folders in two different file displays:

	"%app%/command.exe" {$args}

	Single lister
	 0 file/folder selected
	 1 file/folder selected
	 x file/folder selected
	dual lister
	 same as above but for SRC & DEST listersso a total combination of 6 states.
	 L1, L2, - Case
	 0 0 - 3
	 0 1 - 3
	 0 x - 3
	 1 0 - 1.1
	 1 1 - 1
	 1 x - 1
	 x 0 - 2
	 x 1 - 2
	 x x - 2
	'''	
	exeargs = []
	countfiles = 0
	# The following can be better replaced by a try/catch I think.
	if args.allfiles:
		countfiles = len(args.allfiles)

	if countfiles == 0:
		if args.leftpath and args.rightpath: 
			exeargs = [args.leftpath, args.rightpath[0]] # case 3
			#print "left right"
		else:
			incorrectparameters()
	elif countfiles == 1:
		if args.filepathdest:
			exeargs = [args.allfiles[0], args.filepathdest[0]] # case 1
		else:
			if args.rightpath and args.nameonly:
				exeargs = [args.allfiles[0], args.rightpath[0] + args.nameonly[0]] # case 1.1
			else:
				incorrectparameters()
	elif countfiles >= 2:
		#exeargs = [args.allfiles[0], args.allfiles[1]] # case 2
		exeargs = args.allfiles  # case 2
		#print "case 2"
	return exeargs

def buildcmd(args):
	return ' '.join([args.diffapp] + selectarguments(args))

def incorrectparameters():
	parser.print_help()
	sys.exit(1)

button = 'diffapp {leftpath} -r {rightpath} -n {file} -d {filepathdest} -a {allfilepath}' #full code for button
# @runonce:"%Share%\Dev\Portable Python 2.7.2.1\App\python.exe" "{alias|dopusdata}Scripts/diffselection.py" "%apps%\winmerge\winmergelkl.exe" "{leftpath}" -r "{rightpath}" -n "{file}" -d "{filepathdest}" -a "{allfilepath}"

# <?xml version="1.0"?>
# <button backcol="none" display="both" label_pos="right" textcol="none">
# 	<label>ShowArgsPython</label>
# 	<icon1>#user</icon1>
# 	<function type="batch">
# 		<instruction>@leavedoswindowopen</instruction>
# 		<instruction>@nofilenamequoting</instruction>
# 		<instruction>@runonce:&quot;%Share%\Dev\Portable Python 2.7.2.1\App\python.exe&quot; &quot;{alias|dopusdata}Scripts/diffselection.py&quot; &quot;%apps%\winmerge\winmergelkl.exe&quot; &quot;{leftpath}&quot; -r &quot;{rightpath}&quot; -n &quot;{file}&quot; -d &quot;{filepathdest}&quot; -a &quot;{allfilepath}&quot;</instruction>
# 		<instruction>@nodeselect </instruction>
# 	</function>
# </button>

logging.root.setLevel(logging.DEBUG)
debugmode = logging.root.level == logging.DEBUG

parser=argparse.ArgumentParser(description="Diff the given files or folders from directory opus", 
	epilog="This program requires at least 2 of the options to be provided. use the following parameters\
	 in Dopus button: " + button)
#parser.add_argument("-f","--filepath", help="source filename")
parser.add_argument("diffapp", help="The Diff application executable path")
parser.add_argument("leftpath", help="The left path")
parser.add_argument("-r","--rightpath", help="The right path", nargs="*")
parser.add_argument("-n","--nameonly", help="The filename only of any selected file in source", nargs="*")
parser.add_argument("-d","--filepathdest", help="The full filename of any selected file in destination", nargs="*")
parser.add_argument("-a","--allfiles", help="All selected files in source", nargs="*")

samples = [
	'diffapp {leftpath} -r {rightpath} -n {file} -d {filepathdest} -a {allfilepath0}'.split(), #test case 1 - diffapp {allfilepath0} {filepathdest}
	'diffapp {leftpath} -r {rightpath} -n {file} -a {allfilepath0}'.split(), #test case 1.1 - diffapp {allfilepath0} {rightpath}{file}
	'diffapp {leftpath} -r {rightpath} -n {file} -a {allfilepath 0} {allfilepath 1}'.split(), #test case 2 - diffapp {allfilepath0} {allfilepath1}
	'diffapp {leftpath} -r {rightpath}'.split(), # test case 3 - diffapp {leftpath} {rightpath}
	#button.split(),
	#' '.split(), #test error case -  error: too few arguments
]

#leftpath = os.path.dirname(allfiles[0])
#nameonly = os.path.basename(allfiles[0])
#parser.print_help()
if debugmode:
	for s in samples: #testing
		argstest = parser.parse_args(s)
		#logging.debug(argstest)
		logging.debug(buildcmd(argstest))

logging.debug(sys.argv)
#raw_input()
cmd = buildcmd(parser.parse_args())
logging.debug(cmd)

if not debugmode:
	os.system(cmd)
	#from http://stackoverflow.com/questions/89228/calling-an-external-command-in-python
	#subprocess.call(cmd) #not tested yet
	#DETACHED_PROCESS = 0x00000008
	#pid = subprocess.Popen(cmd, creationflags=DETACHED_PROCESS).pid
else: 
	os.system("pause")

Try it with the button in the code , and it gives out messed up parameters :frowning:
but it's not working for me. It gives me strange arguments, even though all my test cases work :\

Anyway after discovering named arguments in vbs. I went back to that script and got it to work!!!
Check it out!
All the instructions are in the script, for the button as well

option explicit
' Will display all arguments provided to script for debugging purposes
' example usage
' Cscript //x ShowArgs.vbs test1 23 asdf asdf "afda f df f"
' @runonce:WScript.exe "{alias|dopusdata}Scripts/ShowArgs.vbs"  -f "{filepath}" -fd "{filepathdest}" -l "{leftpath}" -r "{rightpath}" -n "{file}" -a "{allfilepath}" ignore "{sourcepath$|noterm}" "{alias|dopusdata}Scripts\Actors.txt" "{alias|dopusdata}Scripts\ActorSubdirs.txt"

' @runonce:WScript.exe {alias|dopusdata}Scripts/ShowArgs.vbs  /app:%apps%winmerge\winmergelkl.exe /f:{filepath} /fd:{filepathdest} /l:{leftpath} /r:{rightpath} /n:{file} -a {allfilepath}
' @nodeselect

'Installation instructions
'Copy script to /dopusdata/Scripts/ directory (create if it doesn't exist)
'Copy Paste the following button
' modify the APP location of your winmerge installation

' Button code to paste in dopus'

' <?xml version="1.0"?>
' <button backcol="none" display="both" label_pos="right" textcol="none">
'   <label>DiffSelection</label>
'   <icon1>#user</icon1>
'   <function type="normal">
'     <instruction>@runonce:WScript.exe {alias|dopusdata}Scripts/ShowArgs.vbs  /app:%apps%winmerge\winmergelkl.exe /f:{filepath} /fd:{filepathdest} /l:{leftpath} /r:{rightpath} /n:{file} -a {allfilepath}</instruction>
'     <instruction>@nodeselect</instruction>
'   </function>
' </button>


' references
'http://technet.microsoft.com/en-us/library/ee156618.aspx

Dim objIEDebugWindow
' Debug "This is a great way to display intermediate results in a separate window."

Dim args
set args = WScript.Arguments
DebugArrayNamed args.Named
Debug " "
DebugArray args
Debug " "

Sub DebugArray(arObj)
  dim iCount
  icount = 0
  dim o
  if (arObj.Count <= 0) then exit sub
  Debug("Total Elements:" & arObj.Count)
  for each o in arObj
    'Debug(iCount & ":" & o & "=" & arObj.Item(o))
    Debug(iCount & ":" & o) ' for plain arrays
    iCount = iCount + 1
  next 
End Sub 

Sub DebugArrayNamed(arObj)
	dim iCount
  icount = 0
  dim o
	if (arObj.Count <= 0) then exit sub
	Debug("Total Elements:" & arObj.Count)
	for each o in arObj
    Debug(iCount & ":" & o & "=" & arObj.Item(o))
		' Debug(iCount & ":" & o) ' for plain arrays
    iCount = iCount + 1
	next 
End Sub 


Sub Debug( myText )
  ' Uncomment the next line to turn off debugging
  Exit Sub

  If Not IsObject( objIEDebugWindow ) Then
    Set objIEDebugWindow = CreateObject( "InternetExplorer.Application" )
    objIEDebugWindow.Navigate "about:blank"
    objIEDebugWindow.Visible = True
    objIEDebugWindow.ToolBar = False
    objIEDebugWindow.Width   = 900
    objIEDebugWindow.Height  = 600
    objIEDebugWindow.Left    = 10
    objIEDebugWindow.Top     = 10
    Do While objIEDebugWindow.Busy
      WScript.Sleep 100
    Loop
    objIEDebugWindow.Document.Title = "IE Debug Window"
    objIEDebugWindow.Document.Body.InnerHTML = _
                 "<b>" & Now & "</b></br>"
  End If

  objIEDebugWindow.Document.Body.InnerHTML = _
                   objIEDebugWindow.Document.Body.InnerHTML _
                   & myText & "<br>" & vbCrLf
End Sub

' =================================================== '
' What I want to do is essentially combine steps 1,2,3 from viewtopic.php?t=10996#p55197
' 1. for comparing two files selected in different file displays:
' 1.1 for comparing two files with identical names in different file displays:
' 2. for comparing two files within same lister:
' 3. for comparing two folders in two different file displays:

' Single lister
'  0 file/folder selected
'  1 file/folder selected
'  x file/folder selected
' dual lister
'  same as above but for SRC & DEST listersso a total combination of 6 states.
'  0 0 - 3
'  0 1 - 3
'  0 x - 3
'  1 0 - 1.1
'  1 1 - 1
'  1 x - 1
'  x 0 - 2
'  x 1 - 2
'  x x - 2


if args.Count < 2 then
	MsgBox WScript.ScriptName & ": Wrong number of arguments. Need at least 2 arguments Give the source & destination file."
	WScript.Quit 1
end if

' "%apps%\winmerge\winmergelkl.exe" {leftpath}{file} {rightpath}{file}
on error resume next

Dim app 
'app = "%apps%\winmerge\winmergelkl.exe"
app = args.Named.Item("app")
Dim firstarg
Dim secondarg

Dim filepath 
filepath = args.Named.Item("f")

Dim filepathdest
filepathdest = args.Named.Item("fd")
if filepathdest = "-1" then 
	filepathdest = ""
end if

Dim leftpath
leftpath = args.Named.Item("l")

Dim rightpath
rightpath = args.Named.Item("r")

Dim nameonly
nameonly = args.Named.Item("n")

Dim arrFile1
Dim arrFile2
arrFile1 = args.Item(7)
arrFile2 = args.Item(8)

on error goto 0

If filepath = "" Then 'case 3'
	firstarg = leftpath
	secondarg = rightpath
elseif arrFile2 = "" Then
	if filepathdest = "" Then 'case 1.1'
		firstarg = filepath 
		secondarg = rightpath & nameonly
	else 'case 1'
		firstarg = filepath
		secondarg = filepathdest
	end if 
else 'case 2'
	firstarg = arrFile1
	secondarg = arrFile2
End If

Dim strExecute
strExecute = app & " """ & firstarg &""" """ &  secondarg & """"
Debug "Command to be run"
Debug strExecute

 Dim shell
 Set shell = CreateObject("WScript.Shell")
 shell.run strExecute,1,False
1 Like