AutoHotkey: AppendLnk option for packing (plus: Automatically assign name for archive)

From TotalcmdWiki
Jump to navigation Jump to search

Context sensitive extension of TC's suggested name in packing dialog (Alt-F5), emulating the missing AppendLnkPack option in TC.
Successfully tested with TC 6.03a up to TC 9.50 (b11).

- Stays resident in memory, can be quit via its icon in the system tray.
- Gets invoked with Alt+F5, replacing TC's standard name suggestion.
- The originally suggested name can be restored by pressing Alt-Backspace once, if needed.
; // Resulting archive name:
; //   - if only 1 file selected -------------------- :  zip:filename.ext.zip (*.*.zip)
; //   - if multiple files /      same name  selected :  zip:filename.zip     (  *.zip)
; //   - if multiple files / different names selected :  zip:dirname.zip (as suggested by TC)

Related links:


	; ////////////////////////////////////////////////////////////////////////////
	; // TC_AppendLnkPack.ahk v1.3   -  (W) StatusQuo 2008-2020
	; //
	; // Context sensitive extension of TC's suggested name in packing dialog (Alt+F5),
	; // emulating the missing AppendLnkPack option,
	; // => http://ghisler.ch/board/viewtopic.php?p=120095#120095
	; //
	; // Option 2 ("multiple files, same name") inspired by
	; // http://www.ghisler.ch/wiki/index.php/AutoHotkey:_Automatically_assign_name_for_archive
	; //
	; ////////////////////////////////////////////////////////////////////////////
	; //
	; // Resulting archive name:
	; //   - only 1 file selected:            zip:filename.ext.zip
	; //   - multiple files, same name:       zip:filename.zip
	; //   - multiple files, different names: zip:dirname.zip (as suggested by TC)
	; //
	; ////////////////////////////////////////////////////////////////////////////

#SingleInstance force

; Menu, Tray, Icon, %SystemRoot%\system32\SHELL32.dll, 39, 1

	; *** end autoexec section here to prevent executing commands on startup without the defined keys being pressed;
	; *** the key definitions below work anyway
return

#IfWinActive ahk_class TTOTAL_CMD
!F5::
{
	boSingleFileAddExt    := "1"
	iSleepAfterEditChange := "50"	; *** in ms: wait for pasted content to arrive in edit control
	
		; *** for 64bit support: control names need to be adjusted!
	s32FilePanelPart := "TMyListBox"	; *** TMyListBox1 / ~2
	s64FilePanelPart := "LCLListbox"	; *** LCLListbox1 / ~2
	s32PackEditAnsi  := "TEdit1"   	; *** <= TC 7.04a 32bit ANSI
	s32PackEditUniC  := "TAltEdit1"	; *** >= TC 7.50  32bit Unicode
	s64PackEditUniC  := "Edit1"   	; ***    TC 9.50  64bit Unicode (and earlier?)
	sPackEdit        := ""         	; *** detect later on the fly!

	sClipSave = %Clipboard%
	IfWinNotExist,  ahk_class TTOTAL_CMD
		Goto, lExit
	IfWinNotActive, ahk_class TTOTAL_CMD,, WinActivate, ahk_class TTOTAL_CMD
	WinWaitActive,  ahk_class TTOTAL_CMD
		; *** save active control name (side of active panel);
		; *** while TC is inactive in background, nothing has the focus!
	ControlGetFocus, sLastFocus, ahk_class TTOTAL_CMD
		; *** check, if TC's main window is active
	If (not (InStr(sLastFocus, s32FilePanelPart))) and (not (InStr(sLastFocus, s64FilePanelPart)))
		Goto, lExit
	
	Clipboard=
	SendMessage, 1075, 2017	; *** 2017 = cm_CopyNamesToClip - copy selected file names to clipboard
	ClipWait, 1
	if ErrorLevel
	{	Clipboard = %sClipSave%
		BlockInput, Off
		MsgBox, 49, TimeOut - %A_ScriptName%, - TimeOut - `n`nCould not get selected file names from TC`n(cm_CopyToClipboard).`n`nOK to use TC's name suggestion`,`nCancel to abort packing now., 5
		IfMsgBox, Cancel,  Goto, lExit
		IfMsgBox, Timeout, Goto, lExit
		Goto, lExit
	}
	
		; *** parse selected file names
	 iLines         = 0
	boUseName       = 1
	 sFirstName     =
	 sFirstFullName =
	Loop, Parse, Clipboard, `n, `r
	{	iLines += 1
			; *** cut path and extension
		SplitPath, A_LoopField, FullFileName, , , FileNameNoExt
		
			; *** if no file name given, use dir name (this is the case with selected dirs)
		if (FullFileName = "")
		{	sTmp  = %A_LoopField%
			if not    (SubStr(sTmp, StrLen(sTmp), 1             ) != "\")	; *** backslash after dir name? => kill!
				sTmp := SubStr(sTmp, 1,            StrLen(sTmp)-1)
			StringGetPos, iTmp, sTmp, \, R	; *** more backslashes in front of dir name? => kill!
			if (iTmp >= 0)	; *** first position is nr. 0
				sTmp := SubStr(sTmp, iTmp+2)
			FullFileName  := sTmp

			StringGetPos, iTmp, sTmp, ., R	; *** contained extension? => kill!
			if (iTmp >= 0)	; *** first position is nr. 0
				sTmp := SubStr(sTmp, 1, iTmp)
			FileNameNoExt := sTmp
		}

			; *** use first name for comparison
		if (sFirstName = "")
		{	sFirstName     = %FileNameNoExt%
			sFirstFullName = %FullFileName%
		} else {
				; *** check if there is a different file name
			if (FileNameNoExt <> sFirstName)
			{	boUseName = 0
				break
			}
		}
	}
	
		; *** multiple files selected:
	if (iLines > 1)
	{	
		IfWinNotExist, ahk_class TTOTAL_CMD
			Return
		WinActivate,   ahk_class TTOTAL_CMD
		WinWaitActive, ahk_class TTOTAL_CMD
		Send, !{F5}
			; *** different file names selected: => use dirname.zip
			; *** (change nothing at all, use TC's suggestion)
		IfEqual, boUseName,  0, Goto, lExit
			; *** no file name found for pasting, so exit
		IfEqual, sFirstName,  , Goto, lError
			; *** all files have same name:     => use filename.zip
		WinWait,        ahk_class TDLGZIP,, 1
		IfWinNotActive, ahk_class TDLGZIP
		{
			IfWinNotExist,  ahk_class TTOTAL_CMD
				Return
			WinActivate,    ahk_class TTOTAL_CMD
			WinWaitActive,  ahk_class TTOTAL_CMD
			Send, !{F5}
			WinWait,        ahk_class TDLGZIP,, 1
			IfWinNotActive, ahk_class TDLGZIP
			{
				MsgBox, 16, %A_ScriptName%, Alt+F5 failed - aborting.`n`n(Use Menu instead? File > Pack)
				Return
			}
		}
		;
		; ControlSend,  TEdit1, !{F5}%sFirstName%{HOME}+{END}
		sFullPath := ""
		sPackEdit := ""
		If (sFullPath = "")
		{
			ControlGetText, sFullPath, %s32PackEditAnsi%	; *** s32PackEditAnsi  := "TEdit1"   	; *** <= TC 7.04a 32bit ANSI
			if (not(sFullPath = ""))
				sPackEdit := s32PackEditAnsi
		}
		If (sFullPath = "")
		{
			ControlGetText, sFullPath, %s32PackEditUniC%	; *** s32PackEditUniC  := "TAltEdit1"	; *** >= TC 7.50  32bit Unicode
			if (not(sFullPath = ""))
				sPackEdit := s32PackEditUniC
		}
		If (sFullPath = "")
		{
			ControlGetText, sFullPath, %s64PackEditUniC%	; *** s64PackEditUniC  := "Edit1"   	; ***    TC 9.50  64bit Unicode (and earlier?)
			if (not(sFullPath = ""))
				sPackEdit := s64PackEditUniC
		}
		;
		sFullPath := ExchangeFN(sFullPath, sFirstName)
		ControlSetText, %sPackEdit%, %sFullPath%
		Sleep, %iSleepAfterEditChange%	; *** sleep, because sometimes next line ia executed too fast, especially for TC 64 bit
		ControlSend,    %sPackEdit%, {HOME}+{END}	; *** select all + move cursor to end of content (= Ctrl+A)
		Goto, lExit
	}
	
		; *** single file name selected:   => use filename.ext.zip
	;ControlSend,  TPanel1, {Alt DownTemp}{F5}{Alt up}	;!{F5}
	;ControlSend,  TMyListBox1, {Alt DownTemp}{F5}{Alt up}	;!{F5}
	IfWinNotExist, ahk_class TTOTAL_CMD
		Return
	WinActivate,   ahk_class TTOTAL_CMD
	WinWaitActive, ahk_class TTOTAL_CMD
	Send, !{F5}
	;Send, {Alt up} ;{Alt up}
	if (not(boSingleFileAddExt))
		Goto, lExit
	;
	WinWaitActive , ahk_class TDLGZIP,, 3
	IfWinNotActive, ahk_class TDLGZIP
		Return	; *** abort!
	;
	; ControlSend,  TEdit1, !{F5}%sFirstFullName%{HOME}+{END}
	sFullPath := ""
	sPackEdit := ""
	If (sFullPath = "")
	{
		ControlGetText, sFullPath, %s32PackEditAnsi%	; *** s32PackEditAnsi  := "TEdit1"   	; *** <= TC 7.04a 32bit ANSI
		if (not(sFullPath = ""))
			sPackEdit := s32PackEditAnsi
	}
	If (sFullPath = "")
	{
		ControlGetText, sFullPath, %s32PackEditUniC%	; *** s32PackEditUniC  := "TAltEdit1"	; *** >= TC 7.50  32bit Unicode
		if (not(sFullPath = ""))
			sPackEdit := s32PackEditUniC
	}
	If (sFullPath = "")
	{
		ControlGetText, sFullPath, %s64PackEditUniC%	; *** s64PackEditUniC  := "Edit1"   	; ***    TC 9.50  64bit Unicode (and earlier?)
		if (not(sFullPath = ""))
			sPackEdit := s64PackEditUniC
	}
	;
		; *** no file name found for pasting, so exit
	IfEqual, sFirstFullName,  , Goto, lError
	sFullPath := ExchangeFN(sFullPath, sFirstFullName)
	WinWaitActive , ahk_class TDLGZIP,, 1
	IfWinNotActive, ahk_class TDLGZIP
		Return	; *** abort!
	ControlSetText, %sPackEdit%, %sFullPath%
	Sleep, %iSleepAfterEditChange%	; *** sleep, because sometimes next line ia executed too fast, especially for TC 64 bit
	ControlSend,    %sPackEdit%, {HOME}+{END}	; *** select all + move cursor to end of content (= Ctrl+A)
	
lExit:
	BlockInput, Off
	Clipboard = %sClipSave%
	Return

lError:
	BlockInput, Off
	MsgBox, Error getting file name(s)`n`n- sFullPath = %sFullPath%`n- sFirstFullName = %sFirstFullName%`n- sFirstName = %sFirstName%
	Goto, lExit
}

Return

ExchangeFN(sEfnFullPath, sNewFN)
{
	StringGetPos,    i1, sEfnFullPath, \, R
	StringGetPos,    i2, sEfnFullPath, ., R
	StringLeft, sEfnOut, sEfnFullPath, i1
	Stringmid,  sEfnExt, sEfnFullPath, (i2 + 1)
	if StrLen(sEfnOut) > 0
		sEfnOut = %sEfnOut%\
	sEfnOut    = %sEfnOut%%sNewFN%%sEfnExt%
	Return %sEfnOut%
}
#IfWinActive

;

Back to AutoHotkey