2
votes

I am trying to develop an Autohotkey script to comment or uncomment a code block irrespective of editor I am using(It can even be notepad).

The kind of implementation I have on mind is I select some piece of code and press a hotkey to comment it out or I select a commented code and press another hotkey to uncomment it just the way it is with IDEs.

The language for code does not matter here. Every language has some syntax for multi-line comment and thus script can be modified to work for any language.

How should I go about it?

I am afraid there may be duplicates of this questions. But, I could not find any.

3
The basic process would be: 1. Get the highlighted text (most probably via clipboard) 2. Parse the code and comment/uncomment it if necessary 3. If there was a change, post the code back to the source window. The very nontrivial part is the parsing. Best case scenario is you have a full code parser at hand for the respective language. Otherwise, if you're aiming for something sophisticated, you'll have to implement a broad set of parsing rules. For example for handling nested comments, ignoring strings, detecting syntactically incorrect comments etc. - MCL
MCL - you should post that as an answer, not a comment. I'd +1 your answer. - bgmCoder

3 Answers

3
votes

Here is a simplified method for you.

  1. Manually select text
  2. push the hotkey (in my example, it is ctrl+alt+c)
  3. The script will copy the selection
  4. Then it will add your comment signatures
  5. then it will put the new string on the clipboard
  6. then it will paste back, replacing the current selection

You might have to add a sleep or a clipwait in there somewhere.

!^c::
    send ^c
    thisvar := clipboard
    thisvar := "<!--" . thisvar . "-->"
    clipboard := thisvar
    send ^v
return

This should give you someplace to start.

Like MCL says, if you want to use different comment signatures, then you are going to have to write an elaborate function to parse the copied selection and determine what language it is. One idea for you is to see if you can fetch the code-file's path from the editor you are working in - then you can judge by the file extension what sort of code is being used. That will work most of the time - but only if the code file contains a single kind of code (C++ or ahk for example - html would be more difficult because it contains several kinds).

0
votes

This is my code to uncomment:

!^d::
    send ^c
    Sleep, 40
    StringReplace, clipboard, clipboard, -->, , All
    StringReplace, clipboard, clipboard, <!--, , All
    Sleep, 40
    send ^v
return

The hotkey is ctrl+alt+d

0
votes

This is a script to comment multiple lines and uncomment them. The chars used to comment can be modified targeting the "commentChars" variable.
Ctrl+Alt+c to comment a selection
Ctrl+Alt+x to uncomment a selection

SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
commentChars := "//"
!^c::
    send ^c
    delimiter := "`n"
    thisvar := ""
    size := parsedTextContainerSize(clipboard,delimiter)
    Loop, parse, clipboard, `n, `r
    {
        ;MsgBox, index = %A_Index% . size = %size%
        if (A_Index < size)
        {
            thisvar := thisvar . commentChars . A_LoopField . "`n"
        }
        else
        {
            ;MsgBox, finally = %A_Index%
            thisvar := thisvar . commentChars . A_LoopField
        }
    }

    clipboard := thisvar
    send ^v
return

!^x::
    send ^c
    delimiter := "`n"
    thisvar := ""
    size := parsedTextContainerSize(clipboard,delimiter)
    Loop, parse, clipboard, `n, `r
    {
        line := ""
        firtTwoChars := ""
        pos := -1
        StringGetPos, pos, A_LoopField, %commentChars%
        if (pos = 0) 
        {
            ;StringReplace, newString, originalString, –, %A_Space%, 1
            StringReplace, line, A_LoopField, %commentChars%, ,
            ;MsgBox, line = %line%
        }
        else
        {
            line := A_LoopField
        }

        ;MsgBox, index = %A_Index% . size = %size%
        if (A_Index < size)
        {
            thisvar := thisvar . line . "`n"
        }
        else
        {
            ;MsgBox, finally = %A_Index%
            thisvar := thisvar . line
        }
    }

    clipboard := thisvar
    send ^v
return


parsedTextContainerSize(text,delimiter)
{
  count = 0
  pos = 0
  Loop,
  {
    StringGetPos, pos, text, %delimiter%,, %pos%    
    If (Errorlevel<>0)
      break
    count += 1
    pos +=1
  }    
  return count + 1
}