This program expands upon my Do.py program (Recipe: 577439). Instead of doing one expansion for the entire comand, it performs an expansion on each argument. It uses the Do.py program preserving macro definitions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | # ----------------------------------------------
# Name: Do2
# Description: Expand and execute command
## D20H-35 Expand and execute command
#
# Author: Philip S. Rist
# Date: 10/24/2010
# Copyright 2010 by St. Thomas Software
# ----------------------------------------------
# This program is freeware. It may be used
# for any moral purpose. You use it at your
# own risk. St. Thomas Software makes no
# guarantees to its fitness to do anything.
#
# If you feel you must pay for it. Please
# send one million dollars to
#
# The International Rescue Committee
# 122 East 42nd Street
# New York, N.Y. 10168-1289
#
# Ok, we are in a recession. So, make it a half
# million.
# Usage examples:
#
#[HKEY_CLASSES_ROOT\*\Shell\Do2Bkup]
#@="Backup (Do2)"
#"EditFlags"=hex:01,00,00,00
#[HKEY_CLASSES_ROOT\*\Shell\Do2Bkup\Command]
#@="c:\\sys\\python25\\pythonw.exe c:\\bin\\do2.py \"%1\" c:\\Windows\\system32\\cmd.exe /K copy \"{a}\" \"{u}\\{2}\\{f}\" "
#
#[HKEY_CLASSES_ROOT\*\Shell\Do2Edit]
#@="Edit (Do2)"
#"EditFlags"=hex:01,00,00,00
#[HKEY_CLASSES_ROOT\*\Shell\Do2Edit\Command]
#@="c:\\sys\\python25\\pythonw.exe c:\\bin\\do2.py \"%1\" c:\\Source\\{2}\\qeditor.exe \"{a}\" "
#
import sys, getopt, os
import Do
import subprocess
def ParentSearch(pFilePath, pDefaultPath, pJoin='\\'):
'''
Scan parent list for file selecting lowest level matching file
'''
lParts = pFilePath.split(pJoin)
lCount = len(lParts) - 1
lPath = ''
while lCount > 0:
lPath = pJoin.join(lParts[0:lCount]) + pJoin + lParts[-1]
if os.path.exists(lPath):
break
lCount -= 1
else:
lPath = pDefaultPath
return lPath
def ExpandArg(pArg, pFilePath, pDefaultPath, pLeft='{', pSep=';', pQuote='"',
pPref='{<-}', pJoin='\\'):
'''
Expand single command line argument
'''
# Expand argument
if pArg.find(pLeft) >= 0:
lArg = Do.Expand(pArg, pFilePath)
else:
lArg = pArg
# If starts with {<-} and single path scan parent folders for
# first matching file. Each folder above specified path will
# be checked until file is found.
if lArg.startswith(pPref) and lArg.find(pSep) < 0:
lArg = os.path.abspath(lArg[2:])
print 'Parent Search 1'
lArg = ParentSearch(lArg, pDefaultPath, pJoin=pJoin)
# If multiple paths separated by pSep(';') select first valid path
lFound = ''
if lArg.find(pSep) >= 0:
lPaths = lArg.split(pSep)
for lPath in lPaths:
if lPath.startswith(pPref):
lPath = os.path.abspath(lPath[4:])
lPath = ParentSearch(lPath, pDefaultPath, pJoin=pJoin) # 01/19/11
if lPath == '': #
continue #
lPath = os.path.abspath(lPath)
if os.path.exists(lPath):
lFound = lPath
break
else:
lFound = os.path.abspath(pDefaultPath)
else:
lFound = lArg
# If argument contains space enclose it within quotes
lFound = lFound.strip()
if lFound.find(' ') > 0 and lFound[0] != pQuote:
lFound = pQuote + lFound + pQuote
return lFound
def submitnow(pCommand):
'''
Submit command
'''
lCommand = '"' + pCommand + '"'
#print '\n\nSubmitting:', lCommand
subprocess.Popen(lCommand, shell=True)
#sys.argv.extend( [ '-d', '{o}\\new', 'c:\\source\\python\\new\\do.py', 'c:\\bin\\echop.bat',
# '{a}', '{p}\\test\\{f}', '{<-}\\{p}\\menus.ini', '{t}\\{xx}.bkp',
# '{i}\\{-1}', ' {u}\\{-2}', '{.}\\{-3} ', '"{g}\\{2}\\test.{e}"',
# '{0}\\{3}\\{n}.{e}.txt' ])
if __name__ == '__main__':
(mOptions, mArgs) = getopt.getopt(sys.argv[1:], 'd:e:')
mFilePath = mArgs[0]
mDefaultPath = ''
for (mKey, mValue) in mOptions:
if mKey == '-d':
if mValue.find('}'):
mValue = ExpandArg(mValue, mFilePath, '')
if mValue != '':
os.chdir(mValue)
elif mKey == '-e':
setenviron(mValue, mFilePath)
elif mKey == '-p':
mValue = ExpandArg(mValue, mFilePath, '')
if mValue != '':
mDefaultPath = mValue
mCommand = ''
mCount = 0
for mArg in mArgs[1:]:
mText = ExpandArg(mArg, mFilePath, mDefaultPath) + ' '
#print '%5d: %-24s * %-30s ---> %s' % (mCount, mArgs[mCount+1], mFilePath, mText)
mCommand += mText
mCount += 1
if len(mCommand) > 0:
submitnow(mCommand)
|
Because each expansion processes one argument the program can recognize arguments with embedded white space. Quotes will be added as needed. The program will also accept an argument consisting of a series of paths separated by ';' with or without macro expansion. After expansion each path will be validated from left to right. The first to be valid will be added to the command line.
{o}\menus.ini;c:\data\{e}\menus.ini will result in
any.py selecting c:\source\Python\menus.ini
any.gif selecting c:\data\gif\menus.ini
any.txt selecting c:\bin\menus.ini the hardcoded default
A new macro was added. The macro '{<-}' at the beginning of any path will cause the program to search up the folder tree looking for an appropriatly named file. The first one found, the lowest level file will be used. The argument '{<-}{o}\new\any.py' will scan in reverse the c:\source\python\new tree for the lowest level any.py file.
The program has only been run on a Win32 XP system with Active Python 2.5 and 2.7.
I found a bug. The '{<-}' macro did not work with the ';' path separators. This required two lines of code to be added. Which I have done. This feature is used in my button bar program.
I like using the context menus provided by Windows. Right clicking a folder will display a menu of programs with links to the selected folder. Initially I added programs to this menu but the list got too long. The first solution was a single entry executing my button bar program. This still meant there was only one menu for every folder.
Putting a macro within the menu name can select different menus depending on the selected folder as in '{a}\menus.ini'. The ';' allows the specification of an alternative or default menu if the first is not found as in '{a}\menus.ini;c:\bin\menus.ini'. This requires a menu in every folder for which I do not want to use the default menu. I could use '{a]\menus.ini;{p}\menus.ini;c:\bin\menus.ini' to search the current and parent folders. This is still limiting.
The '{<-}' macro will cause the path of a folder to be searched bottom up starting with the that folder until the file name is found, as in '{<-}c:\source\python\projects\menus.ini'. Combining this macro with the ';' separator allows for multiple searches and the specification of a default file as in '{<-}{a}\test.ini;{<-}{a}\menus.ini;c:\bin\menus.ini'.
I can put a menu in a high level folder such as 'c:\source\python' and access it from any sub-folder. I can also add a menu to a sub-folder if I want a different menu for that sub-folder.