-- Copyright 1996-2000 Robelle Solutions Technology Inc. -- Version 1.07 April 14, 2000 name QSLUtilList group "Ro&belle" command "&List "; property QSLScriptVersion = "ListLines 1.07 - Copyright Robelle 2000"; -- This script allows a user to search for strings, regexp or patterns in one or more -- files. -- Script menu commands are created allowed the search to occur on: -- the current file only or using $include, #include or .include files recursively for -- a particular string. The script has entry points implemented as On Command -- blocks: -- -- String: search current file with a simple string -- Regexp: search current file with a regular expression -- Pattern: search current file with a pattern -- String in $include: search include files with a simple string -- Regexp in $include: search include files with a regular expression -- Pattern in $include: search include files with a pattern -- About: displays a short text in the Script Control Panel explaining basic -- operations -- -- -- Search the include file for the specified string -- sub SearchLine(FileH, SearchText, SearchType, FirstFind) ; if SearchType = 1 then findResult = FileH.find( string: SearchText, startattop: FirstFind, ignorecase:true ); else if SearchType = 2 then findResult = FileH.find( regexp: SearchText, startattop: FirstFind, ignorecase:true ); else -- Pattern match findResult = FileH.find( pattern: SearchText, startattop: FirstFind, ignorecase:true ); endif endif if findResult then lastLine = FileH.lastfoundline; foundLineRec = FileH.gettext( startline: lastLine ) ; foundLineRec.lineNum = lastLine; -- Return record number too return foundLineRec ; else return "" ; endif ; endsub ; -- -- Perform the actual search operation -- sub SearchForString(FileH, SearchText, SearchType, OutputFile); foundRecord = {}; if SearchText <> "" lineFound = SearchLine(FileH, SearchText, SearchType, true) ; if length(lineFound) > 0 then if FileH.FullFilename = "" then filename = "(New unnamed file)"; else filename = FileH.FullFileName; endif foundRecord = foundRecord + ("Found in: " + string(filename)); endif ; repeat while length(lineFound) > 0 foundRecord = foundRecord + (string(lineFound.linenum) + ": " + lineFound[1]) ; if lineFound.linenum < FileH.linecount then -- Move the cursor at the beginning of the next line -- so the line is not displayed repeatedly FileH.select(startline: lineFound.linenum + 1, startcolumn: 1); lineFound = SearchLine(FileH, SearchText, SearchType, false) ; else lineFound = ""; -- Stop the loop after displaying the last line endif endrepeat ; else foundRecord = foundRecord + ("Include file: " + string(FileH.FullFilename)); endif -- Write all lines found in this file foundRecord = foundRecord + ""; -- Force skip to a new line OutputFile.insert(foundRecord); endsub -- -- Extract the filename from the $include statement -- General format is: -- [whitespace]$[whitespace]incl[ude][whitespace]filename[whitespace] -- or -- [whitespace]#[whitespace]incl[ude][whitespace]filename[whitespace] -- or -- [whitespace].[whitespace]incl[ude][whitespace]filename[whitespace] -- sub ExtractInclFilename(FileH) ; lastLine = FileH.lastfoundline; nextChar = FileH.lastfoundcolumn + FileH.lastfoundlength; foundLine = FileH.gettext( startline: lastLine, startcolumn: nextChar, endcolumn: FileH.recordlength)[1]; endChar = pos(foundLine, " "); -- Look for a space if endChar = 0 -- No space endChar = pos(foundLine, character(9)); -- Look for a tab if endChar = 0 -- No tab either filename = foundLine; -- Use rest of the line else filename = foundLine[1:endChar]; -- Use up to tab endif else filename = foundLine[1:endChar]; -- Use up to space endif return filename; endsub ; -- -- Try to open the include file. -- For local files, use the name as coded on the $include statement i.e. assume the file -- is in the local CWD. -- If that fails, prepend the main file pathname to the name on the $include statement. -- sub OpenInclFile(ConnectionName, Filename); fileInclHandle = ""; try fileInclHandle = open(connection: connectionName, filename: Filename, readonly: true, minimize: true, updaterecentfiles: false) ; recover (errorRecord) writelog("ERROR (" + Filename + "): " + errorRecord.MessageText); endtry return fileInclHandle; endsub -- -- Find the next $include statement, extract the filename -- and try to open it. -- -- Because of the way regexp currently works, "$inclde" and "$incle" -- statements will also be selected. It's very likely that compilers -- will reject these anyway and should not be around for long. -- sub GetNextInclFileH(FileH, FilePath, FirstFind) ; fileInclOpened = false; fileInclHandle = ""; found = FileH.find( regexp:"^[\s\t]*[$#.][\s\t]*incl?u?d?e?[\s\t]*", startattop: FirstFind, ignorecase: true); if found then fileInclName = ExtractInclFilename(FileH) ; connectionName = fileH.ConnectionName; if fileH.isonhost then fileInclHandle = findopenfile(connection: connectionName, matches: fileInclName); else fileInclHandle = findopenfile(matches: fileInclName); endif if length(fileInclHandle) > 0 then -- File is already open, proceed fileInclHandle = fileInclHandle[1]; fileInclOpened = true; else -- File is not opened, try now fileInclHandle = OpenInclFile(connectionName, fileInclName); if typeof(fileInclHandle) <> qedit.typeobject then if connectionName = "" and FilePath <> "" then -- Try local file with path from file at upper-level pathFilename = FilePath + fileInclName; fileInclHandle = OpenInclFile(connectionName, pathFilename); if typeof(fileInclHandle) = qedit.typeobject then writelog("Opened as " + pathFilename); endif -- Opened As message endif -- Blank ConnectionName endif -- fileInclHandle is an object endif -- Length of fileInclHandle endif -- $Include found fileInclResult = {}; fileInclResult.fileInclHandle = fileInclHandle; fileInclResult.fileInclOpened = fileInclOpened; return fileInclResult; endsub ; -- -- Search for all $include files and search for the string in each one -- If no search string has been specified, simply lists the $include filenames -- This is a recursive subroutine. -- sub SearchInclFile(FileH, FileOpened, FilePath, SearchText, SearchType, OutputFile); saveSelection = FileH.Selection ; firstFind = true; FileH.select (startline:1, startcolumn: 1) ; includeFileResult = GetNextInclFileH(FileH, FilePath, firstFind) ; includeFileH = includeFileResult.fileInclHandle; includeFileOpened = includeFileResult.fileInclOpened; firstFind = false; repeat while typeof(includeFileH) = qedit.typeobject if not includeFileH.Isonhost then FilePath = ExtractLocalPath(includeFileH.fullfilename); endif SearchInclFile(includeFileH, includeFileOpened, FilePath, SearchText, SearchType, OutputFile) ; includeFileResult = GetNextInclFileH(FileH, FilePath, firstFind) ; includeFileH = includeFileResult.fileInclHandle; includeFileOpened = includeFileResult.fileInclOpened; endrepeat ; SearchForString(FileH, SearchText, SearchType, OutputFile); FileH.select (range: saveSelection) ; if not FileOpened then -- File was not opened so close it now FileH.close() ; endif endsub ; -- -- Extract the pathname from the main file, if it is a local file. -- For example, c:\dir1\dir2\source.cpp returns c:\dir1\dir2\ -- sub ExtractLocalPath(Filename); pathname = ""; fileLength = length(Filename); position = pos(Filename, ":"); -- Extract drive letter if position <> 0 pathname = pathname + Filename[1:position]; fileLength = fileLength - position; Filename = Filename[position + 1:fileLength]; endif noMore = false; repeat until noMore -- Extract path except filename itself position = pos(Filename, "\"); if position <> 0 pathname = pathname + Filename[1:position]; fileLength = fileLength - position; Filename = Filename[position + 1:fileLength]; else noMore = true; endif endrepeat return pathname; endsub -- -- Display script banner -- sub DisplayScriptInfo(FileH, SearchString, SearchType, OutputFile); writelog QSLScriptVersion; if FileH.Isonhost then fileDescription = FileH.ConnectionName + ":" + FileH.FullFilename; else fileDescription = FileH.FullFilename; endif if SearchType = 1 then searchDescription = "STRING"; else if SearchType = 2 then searchDescription = "REGEXP"; else searchDescription = "PATTERN"; endif endif descriptionLine = {}; if SearchString <> "" then descriptionLine = descriptionLine + ("Searching " + fileDescription + " for " + searchDescription + " '" + SearchString +"'"); else descriptionLine = descriptionLine + ("Listing all Include filenames"); endif descriptionLine = descriptionLine + ""; OutputFile.insert(descriptionLine); endsub -- -- Use the selection as the search string. If there is no selection, -- prompt the user for one -- sub GetSearchString(FileH, SearchType) ; searchStr = ""; If length(FileH.selection) = 2 then -- Some text selected theSelection = FileH.selection; startOnLine = theSelection.start.line; endOnLine = theSelection.end.line; if startOnLine = endOnLine then -- All on the same line searchStr = FileH.getselectedtext()[1]; endif endif if SearchType = 1 then searchDescription = "STRING"; else if SearchType = 2 then searchDescription = "REGEXP"; else searchDescription = "PATTERN"; endif endif promptMsg = "Enter a " + searchDescription + " to search for. Clear the field to get a list of Include filenames."; if SearchType <> 1 or length(searchStr) = 0 then r = dialog( promptMsg, 1, searchStr ); okToGoOn = r.button ; if okToGoOn = 1 then searchStr = r.enteredText; else -- Cancel button stop; endif ; endif ; Return searchStr ; endsub ; -- -- Start processing the search request in the current file only. -- Receives a value for the type of search requested. -- sub ListCurrentFile(FileH, SearchString, SearchType, OutputFile) if typeof(OutputFile) = qedit.typeundefined then OutputFile = newfile(); endif saveSelection = FileH.Selection ; FileH.select (startline:1, startcolumn: 1) ; SearchForString(FileH, SearchString, SearchType, OutputFile); FileH.select(range: saveSelection); endsub ; -- -- Start processing the search request for the $Include searches -- Receives a value for the type of search requested. -- sub ListInclude(FileH, SearchString, SearchType, OutputFile) if typeof(OutputFile) = qedit.typeundefined then OutputFile = newfile(); endif if not FileH.Isonhost then filePath = ExtractLocalPath(FileH.FullFilename); endif fileOpened = true; SearchInclFile(FileH, fileOpened, filePath, SearchString, SearchType, OutputFile) ; endsub ; -- -- Interpret command line entered from the Script menu -- and invoke the appropriate procedure. -- sub ProcessListRequest (SearchType, IncludeFile) if SearchType < 1 or SearchType > 3 then result = dialog("SearchType must be one of: 1 (String), 2 (Regexp) or 3 (Pattern)"); stop; endif if typeof(IncludeFile) = qedit.typeundefined then IncludeFile = false; endif fileH = qedit.activefile; if not exists(fileH) then result = dialog("Please open your desired document before attempting a search,"); else saveFilename = string(fileH.FullFilename) ; if saveFilename = "" then saveFilename = "(New unnamed file)"; endif searchString = GetSearchString(fileH, SearchType) ; outputFile = newfile(); DisplayScriptInfo(fileH, searchString, SearchType, outputFile); if IncludeFile writelog("$Include files will be searched!"); ListInclude(fileH, searchString, SearchType, outputFile); else ListCurrentFile(fileH, searchString, SearchType, outputFile); endif endif writelog ("ListLines is DONE!"); endsub on command "&String" ProcessListRequest(1, false); endon on command "&Regexp" ProcessListRequest(2, false); endon on command "&Pattern" ProcessListRequest(3, false); endon on command "S&tring in $Include" ProcessListRequest(1, true); endon on command "R&egexp in $Include" ProcessListRequest(2, true); endon on command "P&attern in $Include" ProcessListRequest(3, true); endon on command "About..." qedit.showscp = true; writelog QSLScriptVersion ; writelog " " ; writelog "This script will perform a search on the current file. "; writelog "All lines found to contain the search string will be "; writelog "displayed in the log window of the Script Control"; writelog "dialog box." ; writelog " " ; writelog "ListInclude will search files named in $INCLUDE, #INCLUDE or" ; writelog ".INCLUDE lines. These files will be opened in Read-Only mode." ; writelog " " ; writelog "ListLines will use selected text as the search string. If no text" ; writelog "is highlighted, then ListLines will prompt you for a search string." ; writelog " "; writelog "If you do not specify a search string, the script lists all the "; writelog "$include filenames."; endon ;