LineFind: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
No edit summary
Line 122: Line 122:
<b>Example4 (insert lines):</b>
<b>Example4 (insert lines):</b>
<highlight-nsis>Section
<highlight-nsis>Section
${LineFind} "C:\a.log" "" "10" "Example4
${LineFind} "C:\a.log" "" "10" "Example4"
IfErrors 0 +2
IfErrors 0 +2
MessageBox MB_OK "Error"
MessageBox MB_OK "Error"

Revision as of 14:45, 31 August 2005

Author: Instructor (talk, contrib)


Links

Latest version of headers "nsh.zip"
http://forums.winamp.com/showthread.php?s=&threadid=203228&goto=lastpost

If a function is used without header, put the function code in your script before calling it.

The Function Description

____________________________________________________________________________
 
                            LineFind v1.5
____________________________________________________________________________
 
 
Find specified lines in text file and edit or view this lines in callback function.
 
 
Syntax:
${LineFind} "[File1]" "[File2|/NUL]" "[LineNumbers]" "Function"
 
"[File1]"         ; Input text file
                  ;
"[File2|/NUL]"    ; [File2]
                  ;   Output text file
                  ;   If empty then File2=File1
                  ; [/NUL]
                  ;   No output text file (only read File1)
                  ;
"[LineNumbers]"   ; [No|-No|No:No|{No}|{-No}|{No:No}]
                  ;   1:-1     all lines to change (default)
                  ;   2        second line from start
                  ;   -3       third line from end
                  ;   5:9      range of lines from 5 to 9
                  ;   {2}      only second line from start to output
                  ;   {-3}     only third line from end to output
                  ;   {5:9}    only range of lines from 5 to 9 to output
                  ;
"Function"        ; Callback function for specified lines
 
Function "Function"
	; $R9       current line
	; $R8       current line number
	; $R7       current line negative number
	; $R6       current range of lines
	; $R5       handle of a file opened to read
	; $R4       handle of a file opened to write ($R4="" if "/NUL")
 
	; you can use any string functions
	; $R0-$R3  are not used (save data in them).
	; ...
 
	Push $var      ; If $var="StopLineFind"  Then exit from function
	               ; If $var="SkipWrite"     Then skip current line (ignored if "/NUL")
FunctionEnd
 
 
Note:
-Error flag if input file isn't exists
-Error flag if output file path isn't exists
-Ranges must be specified on growth (2 4:5 9:-8 -5:-4 -2:-1)
-Output file will not be updated if no changes made.


Example1 (delete first two symbols):

Section
	${LineFind} "C:\a.log" "C:\a-edited.log" "3:-1" "Example1"
	IfErrors 0 +2
	MessageBox MB_OK "Error"
SectionEnd
 
Function Example1
	${TrimNewLines} '$R9' $R9
	StrCpy $R9 $R9 '' 2
	StrCpy $R9 '$R9$\r$\n'
	;start from 3 line and delete first two symbols
 
	Push $0
FunctionEnd


Example2 (show changed lines):

Section
	${LineFind} "C:\a.log" "a.log" "{5:12 15 -6:-5 -1}" "Example2"
	IfErrors 0 +2
	MessageBox MB_OK "Error"
SectionEnd
 
Function Example2
	${TrimNewLines} '$R9' $R9
	StrCpy $R9 "$R9   ~Changed line ($R8)~$\r$\n"
 
	Push $0
FunctionEnd


Example3 (delete lines):

Section
	${LineFind} "C:\a.log" "\logs\a.log" "2:3 10:-5 -3:-2" "Example3"
	IfErrors 0 +2
	MessageBox MB_OK "Error"
SectionEnd
 
Function Example3
	StrCpy $0 SkipWrite
 
	Push $0
FunctionEnd


Example4 (insert lines):

Section
	${LineFind} "C:\a.log" "" "10" "Example4"
	IfErrors 0 +2
	MessageBox MB_OK "Error"
SectionEnd
 
Function Example4
	FileWrite $R4 "---First Line---$\r$\n"
	FileWrite $R4 "---Second Line ...---$\r$\n"
 
	Push $0
FunctionEnd


Example5 (replace in file with count of changes - "WordFunc.nsh" required):

!include "WordFunc.nsh"
!insertmacro WordReplace
 
Section
	StrCpy $R0 0
	${LineFind} "C:\a.log" "C:\logs\a.log" "1:-1" "Example5"
	IfErrors 0 +2
	MessageBox MB_OK "Error" IDOK +2
	MessageBox MB_OK "Changed lines=$R0"
SectionEnd
 
Function Example5
	StrCpy $1 $R9
 
	${WordReplace} '$R9' ' ' '_' '+*' $R9
 
	StrCmp $1 $R9 +2
	IntOp $R0 $R0 + 1
	;$R0   count of changed lines
 
	Push $0
FunctionEnd


Example6 (line string to cut or delete):

Section
	${LineFind} "\a.log" "C:\logs\a.log" "" "Example6"
	IfErrors 0 +2
	MessageBox MB_OK "Error" IDOK +2
	MessageBox MB_OK "Processed lines=$R1:$R2"
SectionEnd
 
Function Example6
	;(Cut lines from a line to another line (also including that line))
	StrCmp $R0 finish stop
	StrCmp $R0 start finish
	StrCmp $R9 'Start Line$\r$\n' 0 skip
	StrCpy $R0 start
	StrCpy $R1 $R8
	goto code
	finish:
	StrCmp $R9 'Finish Line$\r$\n' 0 code
	StrCpy $R0 finish
	StrCpy $R2 $R8
	goto code
	skip:
	StrCpy $0 SkipWrite
	goto output
	stop:
	StrCpy $0 StopLineFind
	goto output
 
	;;(Delete lines from a line to another line (also including that line))
	; StrCmp $R0 finish code
	; StrCmp $R0 start finish
	; StrCmp $R9 'Start Line$\r$\n' 0 code
	; StrCpy $R0 start
	; StrCpy $R1 $R8
	; goto skip
	; finish:
	; StrCmp $R9 'Finish Line$\r$\n' 0 skip
	; StrCpy $R0 finish
	; StrCpy $R2 $R8
	; skip:
	; StrCpy $0 SkipWrite
	; goto output
 
	code:
	;...
 
	output:
	Push $0
FunctionEnd


Example7 (read lines):

Section
	${LineFind} "C:\a.log" "/NUL" "1:-1" "Example7"
	IfErrors 0 +2
	MessageBox MB_OK "Error"
SectionEnd
 
Function Example7
	MessageBox MB_OKCANCEL '$$R9  "Line"=[$R9]$\n$$R8     "#" =[$R8]' IDOK +2
	StrCpy $0 StopLineFind
 
	Push $0
FunctionEnd

The Function Code

Function LineFind
	!define LineFind `!insertmacro LineFindCall`
 
	!macro LineFindCall _INPUT _OUTPUT _RANGE _FUNC
		Push $0
		Push `${_INPUT}`
		Push `${_OUTPUT}`
		Push `${_RANGE}`
		GetFunctionAddress $0 `${_FUNC}`
		Push `$0`
		Call LineFind
		Pop $0
	!macroend
 
	Exch $3
	Exch
	Exch $2
	Exch
	Exch 2
	Exch $1
	Exch 2
	Exch 3
	Exch $0
	Exch 3
	Push $4
	Push $5
	Push $6
	Push $7
	Push $8
	Push $9
	Push $R4
	Push $R5
	Push $R6
	Push $R7
	Push $R8
	Push $R9
	ClearErrors
 
	IfFileExists '$0' 0 error
	StrCmp $1 '/NUL' begin
	StrCpy $8 0
	IntOp $8 $8 - 1
	StrCpy $9 $1 1 $8
	StrCmp $9 \ +2
	StrCmp $9 '' +3 -3
	StrCpy $9 $1 $8
	IfFileExists '$9\*.*' 0 error
 
	begin:
	StrCpy $4 1
	StrCpy $5 -1
	StrCpy $6 0
	StrCpy $7 0
	StrCpy $R4 ''
	StrCpy $R6 ''
	StrCpy $R7 ''
	StrCpy $R8 0
 
	StrCpy $8 $2 1
	StrCmp $8 '{' 0 delspaces
	StrCpy $2 $2 '' 1
	StrCpy $8 $2 1 -1
	StrCmp $8 '}' 0 delspaces
	StrCpy $2 $2 -1
	StrCpy $R6 cut
 
	delspaces:
	StrCpy $8 $2 1
	StrCmp $8 ' ' 0 +3
	StrCpy $2 $2 '' 1
	goto -3
	StrCmp $2$7 '0' file
	StrCpy $4 ''
	StrCpy $5 ''
	StrCmp $2 '' writechk
 
	range:
	StrCpy $8 0
	StrCpy $9 $2 1 $8
	StrCmp $9 '' +5
	StrCmp $9 ' ' +4
	StrCmp $9 ':' +3
	IntOp $8 $8 + 1
	goto -5
	StrCpy $5 $2 $8
	IntOp $5 $5 + 0
	IntOp $8 $8 + 1
	StrCpy $2 $2 '' $8
	StrCmp $4 '' 0 +2
	StrCpy $4 $5
	StrCmp $9 ':' range
 
	IntCmp $4 0 0 +2
	IntCmp $5 -1 goto 0 growthcmp
	StrCmp $R7 '' 0 minus2plus
	StrCpy $R7 0
	FileOpen $8 $0 r
	FileRead $8 $9
	IfErrors +3
	IntOp $R7 $R7 + 1
	Goto -3
	FileClose $8
 
	minus2plus:
	IntCmp $4 0 +5 0 +5
	IntOp $4 $R7 + $4
	IntOp $4 $4 + 1
	IntCmp $4 0 +2 0 +2
	StrCpy $4 0
	IntCmp $5 -1 goto 0 growthcmp
	IntOp $5 $R7 + $5
	IntOp $5 $5 + 1
	growthcmp:
	IntCmp $4 $5 goto goto
	StrCpy $5 $4
	goto:
	goto $7
 
	file:
	StrCmp $1 '/NUL' +4
	GetTempFileName $R4
	Push $R4
	FileOpen $R4 $R4 w
	FileOpen $R5 $0 r
	IfErrors preerror
 
	loop:
	IntOp $R8 $R8 + 1
	FileRead $R5 $R9
	IfErrors handleclose
 
	cmp:
	StrCmp $2$4$5 '' writechk
	IntCmp $4 $R8 call 0 writechk
	StrCmp $5 -1 call
	IntCmp $5 $R8 call 0 call
 
	GetLabelAddress $7 cmp
	goto delspaces
 
	call:
	StrCpy $7 $R9
	Push $0
	Push $1
	Push $2
	Push $3
	Push $4
	Push $5
	Push $6
	Push $7
	Push $R4
	Push $R5
	Push $R6
	Push $R7
	Push $R8
	StrCpy $R6 '$4:$5'
	StrCmp $R7 '' +3
	IntOp $R7 $R8 - $R7
	IntOp $R7 $R7 - 1
	Call $3
	Pop $9
	Pop $R8
	Pop $R7
	Pop $R6
	Pop $R5
	Pop $R4
	Pop $7
	Pop $6
	Pop $5
	Pop $4
	Pop $3
	Pop $2
	Pop $1
	Pop $0
	IfErrors preerror
	StrCmp $9 'StopLineFind' 0 +3
	IntOp $6 $6 + 1
	goto handleclose
	StrCmp $1 '/NUL' loop
	StrCmp $9 'SkipWrite' 0 +3
	IntOp $6 $6 + 1
	goto loop
	StrCmp $7 $R9 write
	IntOp $6 $6 + 1
	goto write
 
	writechk:
	StrCmp $1 '/NUL' loop
	StrCmp $R6 cut 0 write
	IntOp $6 $6 + 1
	goto loop
 
	write:
	FileWrite $R4 $R9
	goto loop
 
	preerror:
	SetErrors
 
	handleclose:
	StrCmp $1 '/NUL' +3
	FileClose $R4
	Pop $R4
	FileClose $R5
	IfErrors error
 
	StrCmp $1 '/NUL' end
	StrCmp $1 '' 0 +2
	StrCpy $1 $0
	StrCmp $6 0 0 rename
	FileOpen $7 $0 r
	FileSeek $7 0 END $8
	FileClose $7
	FileOpen $7 $R4 r
	FileSeek $7 0 END $9
	FileClose $7
	IntCmp $8 $9 0 rename
	Delete $R4
	StrCmp $1 $0 end
	CopyFiles /SILENT $0 $1
	goto end
 
	rename:
	Delete '$EXEDIR\$1'
	Rename $R4 '$EXEDIR\$1'
	IfErrors 0 end
	Delete $1
	Rename $R4 $1
	IfErrors 0 end
 
	error:
	SetErrors
 
	end:
	Pop $R9
	Pop $R8
	Pop $R7
	Pop $R6
	Pop $R5
	Pop $R4
	Pop $9
	Pop $8
	Pop $7
	Pop $6
	Pop $5
	Pop $4
	Pop $3
	Pop $2
	Pop $1
	Pop $0
FunctionEnd