Prettify code

Note: Until the release of Igor Pro version 8.05, make sure you have updated to a recent nightly build (version 8.05B01 build 36043 or later) if you want to play with this code. The code posted below exposes a bug that can cause Igor to crash.

 

Case-corrects Igor function and operation names, and removes trailing whitespace.

Be careful not to select code that contains binary encoded as ASCII, such as proc pictures and text that represents the output of StructPut. There is a chance that some part of a proc picture will be parsed as a whole word that matches a function name and undesirably 'corrected'!

Note that the linked file containing this code will be loaded as an independent module. You'll have to show hidden items in the procedure browser to see the code.

Edit: updated code ignores words with fewer than 3 characters. This greatly reduces the chances of substituting text in a proc picture.

#pragma TextEncoding="UTF-8"
#pragma rtGlobals=3
#pragma IgorVersion=8
#pragma IndependentModule=Prettify
#pragma version=1.3

// https://www.wavemetrics.com/user/tony

// To prettify selected code: cmd-5 (Mac), ctrl-5 (Windows)

// customize prettification here
strconstant ksIgnoreList="" // function and operation names to ignore
strconstant ksCustomList="variable;string;" // add or override items
constant kMinWordLength=3 // avoiding 2 character words like Pi and ei
// reduces possibility of replacing text in binary represented as ASCII

menu "Edit"
    "Prettify Clipboard Code", /Q, PutScrapText Prettify#PrettifyCode(GetScrapText())
    "Prettify Selected Code/5", /Q, PrettifySelection()
end

function PrettifySelection()
   
    string strScrap = GetScrapText()
    PutScrapText ""
    DoIgorMenu "Edit" "Copy"
    PutScrapText PrettifyCode(GetScrapText())
    DoIgorMenu "Edit" "Paste"
    PutScrapText strScrap // leave clipboard state unchanged
end

// Returns a string with known function and operation names case-corrected.
// Commented text is ignored. Trailing whitespace is eradicated.
function /S PrettifyCode(string strText)
   
    string strList = FunctionList("*",";","") + OperationList("*",";","")  
    // remove words in ksIgnoreList, substitute or add words in ksCustomList
    strList = RemoveFromList(ksIgnoreList+ksCustomList, strList, ";", 0) + ksCustomList
    wave /T wList = ListToTextWave(strList, ";")   
    // remove words with fewer than kMinWordLength characters
    variable i
    for(i=numpnts(wList)-1; i>=0; i-=1)
        if(strlen(wList[i]) < kMinWordLength)
            DeletePoints i, 1, wList
        endif
    endfor
   
    variable endsWithReturn = (cmpstr(strText[strlen(strText)-1], "\r") == 0)
    wave /T wText = ListToTextWave(strText, "\r")
    variable lastLine = numpnts(wText) - 1
    wText += SelectString(p<(lastLine) || endsWithReturn, "", "\r")
    multithread wText = PrettifyLine(wText, wList)
    wfprintf strText, "%s", wText
    return strText
end

// strLine should include \r if one was present in input text
threadsafe function /S PrettifyLine(string strLine, wave /T wordList)
   
    string strCode="", word="", restOfCode=""
    variable bytes

    bytes = startOfComment(strLine)
    if(bytes > 1) // examine part of line before any comment
        strCode = strLine[0, bytes-1]

        if(GrepString(strCode, "\S")) // line contains non-whitespace
            restOfCode = strCode
            do // loop through words in line
                SplitString /E="([[:alnum:]]+)(.*)" restOfCode, word, restOfCode
                FindValue /TEXT=word/TXOP=4/Z wordList
                if(V_value > -1)
                    strCode = ReplaceWord(word, strCode, wordList[V_value])
                endif
            while(strlen(restOfCode))
        endif
        strLine = strCode + strLine[bytes, Inf]
    endif

    // remove trailing whitespace, ie. spaces and tabs that follow non-whitespace at end of line
    if(GrepString(strLine, "\S[[:blank:]]+\r$"))
        do
            bytes = strlen(strLine)
            strLine = ReplaceString(" \r", strLine, "\r")
            strLine = ReplaceString("\t\r", strLine, "\r")
        while(bytes > strlen(strLine))
    endif
   
    return strLine
end

// Wrapper for ReplaceString, replaces whole words
threadsafe function /S ReplaceWord(replaceThisWord, inStr, withThisWord)
    string replaceThisWord, inStr, withThisWord
   
    string substring=""
    variable startByte=0, endByte=0
   
    if(GrepString(inStr, "(?i)\\B" + replaceThisWord + "|" + replaceThisWord + "\\B"))
        // line contains word to be replaced as substring
        do // loop through matches
            startByte = strsearch(inStr, replaceThisWord, endByte, 2)
            if(startByte == -1)
                return inStr
            endif
            endByte = startByte + strlen(replaceThisWord)
            substring = inStr[startByte-1, endByte+1] // will be clipped to 0, strlen(inStr)
            // check that match is whole word
            if(GrepString(substring, "(?i)\\b" + replaceThisWord + "\\b"))
                substring = ReplaceString(replaceThisWord, substring, withThisWord)
            endif
            inStr = inStr[0, startByte-2] + substring + inStr[endByte+2, Inf]
        while(1)
    endif
    return ReplaceString(replaceThisWord, inStr, withThisWord)
end

// returns byte offset for comment marker in strLine
// or strlen(strLine) when no comment found.
threadsafe function startOfComment(string strLine)
   
    variable startByte, commentByte, startQuote, endQuote, lineLength
    lineLength=strlen(strLine)
    startByte=0
    do
        if(startByte>=(lineLength-1))
            return lineLength
        endif
        commentByte = strsearch(strLine, "//", startByte)
        if(commentByte == -1)
            return lineLength
        endif
        // found "//"
        startQuote=strsearch(strLine, "\"", startByte)
        if(startQuote==-1 || startQuote>commentByte) // no quotes before //, we're done
            return commentByte
        endif
        // we have a quotation mark before //
       
        do
            endQuote=startQuote
            do
                endQuote=strsearch(strLine, "\"", endQuote+1)
                if(endQuote==-1)
                    return lineLength
                endif
                // endQuote is possible end of quote
                // remove escaped backslashes!
                strLine[startQuote,endQuote]=ReplaceString("\\\\", strLine[startQuote,endQuote], "  ")
            while(cmpstr(strLine[endQuote-1], "\\")==0) // ignore escaped quotes
           
            // found end of quote
            if(endQuote>commentByte) // commentByte was within commented text
                startByte=endQuote+1
                break // look for another comment mark
            else
                startQuote=strsearch(strLine, "\"", endQuote+1)
                if(startQuote==-1 || startQuote>commentByte) // no quotes before //, we're done
                    return commentByte
                endif
            endif
        while(1)
    while(1)   
end

 

Prettify130.ipf

Forum

Support

Gallery

Igor Pro 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More