Visual Studo 환경에서 작업한다면, 매크로를 통해 이 작업을 어느 정도 자동화시킬 수 있다. 아래에 있는 MakeSimpleGetterSetter 매크로가 이런 작업을 자동화하기 위해 사용하는 매크로다. 멤버 변수들을 복사해서 붙인 다음, 복사한 멤버 변수들을 선택하고, 매크로를 실행하면 된다.
EffectId_t m_Id; ///< 이펙트 ID
std::string m_Name; ///< 이펙트 이름 (디버그용)
bool m_Visible; ///< 이펙트가 플레이어에게 보이는가의 여부
bool m_Removable; ///< 디스펠 스킬로 인해 강제로 제거될 수 있는가의 여부
EffectId_t GetId() const { return m_Id; }
void SetId(EffectId_t value) { m_Id = value; }
const std::string& GetName() const { return m_Name; }
void SetName(const std::string& value) { m_Name = value; }
bool IsVisible() const { return m_Visible; }
void SetVisible(bool value) { m_Visible = value; }
bool IsRemovable() const { return m_Removable; }
void SetRemovable(bool value) { m_Removable = value; }
std::string m_Name; ///< 이펙트 이름 (디버그용)
bool m_Visible; ///< 이펙트가 플레이어에게 보이는가의 여부
bool m_Removable; ///< 디스펠 스킬로 인해 강제로 제거될 수 있는가의 여부
EffectId_t GetId() const { return m_Id; }
void SetId(EffectId_t value) { m_Id = value; }
const std::string& GetName() const { return m_Name; }
void SetName(const std::string& value) { m_Name = value; }
bool IsVisible() const { return m_Visible; }
void SetVisible(bool value) { m_Visible = value; }
bool IsRemovable() const { return m_Removable; }
void SetRemovable(bool value) { m_Removable = value; }
아 그러고보니, Visual Studio 2005 기준이다. 낮은 버전에는 돌아가지 않을 수도... 아마 돌아가지 않으려나? 옛날부터 조금씩 수정하며 써온 건데... 모르겠군.
멤버 변수 초기화 매크로도 하나 만들어야 한다고 생각은 하고 있는데, 타입에 따라 대입할 값이 틀리다 보니 "생각"만 하고 있다.
Function ParseVariableDeclarations( _
ByVal strText As String, ByRef colTypes As Collection, ByRef colNames As Collection, ByRef colComments As Collection)
Dim nSpacePos As Integer
Dim nSemicolonPos As Integer
Dim nLineFeedPos As Integer
Dim bSuccess As Boolean
Dim strLine As String
Dim strVariableType As String
Dim strVariableName As String
Dim strVariableComment As String
' 2개 이상의 스페이스를 하나로 만든다.
Do
nSpacePos = InStr(strText, " ")
If nSpacePos <> 0 Then
strText = Replace(strText, " ", " ")
Else
Exit Do
End If
Loop
Do
' 더 이상 파싱할 게 없다면 빠져나간다
If Len(strText) = 0 Then
Exit Do
End If
' 라인 피드를 찾는다.
nLineFeedPos = InStr(strText, CStr(CrLf))
If nLineFeedPos <> 0 Then
' 라인 피드가 있다면 현재 라인을 얻어낸다.
strLine = Trim(Replace(Left(strText, nLineFeedPos - 1), vbTab, " "))
Else
' 라인 피드가 더 이상 없다면...
strLine = Trim(Replace(strText, vbTab, " "))
strText = ""
End If
' 라인 제일 처음 나오는 ';' 글자와 ';' 글자 앞에서 제일 처음 나타나는 ' ' 글자를 찾는다.
bSuccess = False
nSemicolonPos = InStr(strLine, ";")
If nSemicolonPos <> 0 Then
nSpacePos = InStrRev(strLine, " ", nSemicolonPos)
If nSpacePos <> 0 Then
bSuccess = True
End If
End If
' 두 글자 모두를 찾았다면, 변수 선언문이라고 할 수 있다.
If bSuccess Then
strVariableType = Trim(Mid(strLine, 1, nSpacePos))
strVariableName = Trim(Mid(strLine, nSpacePos, nSemicolonPos - nSpacePos))
strVariableComment = ""
If nSemicolonPos <> 0 Then
strVariableComment = Trim(Mid(strLine, nSemicolonPos + 1, Len(strLine) - nSemicolonPos))
End If
colTypes.Add(Trim(Replace(strVariableType, vbTab, " ")))
colNames.Add(Trim(Replace(strVariableName, vbTab, " ")))
colComments.Add(Trim(Replace(strVariableComment, vbTab, " ")))
'MsgBox("[" + vtype + "][" + vname + "][" + vcomment + "]")
End If
strText = Trim(Right(strText, Len(strText) - nLineFeedPos - 1))
Loop
End Function
Function GenerateAccessor(ByVal strVarType As String, ByVal strVarName As String, ByVal strMode As String)
Dim strResult As String
If strVarType <> "" And strVarName <> "" Then
Dim objRegex As New System.Text.RegularExpressions.Regex("")
Dim colBasicTypes As New System.Collections.Generic.Dictionary(Of String, String)
Dim objStream As New System.Text.StringBuilder
' 대문자로만 이루어졌지만, 구조체로 취급하지 않을 타입들 생성
colBasicTypes.Add("DWORD", "")
colBasicTypes.Add("BOOL", "")
colBasicTypes.Add("BYTE", "")
colBasicTypes.Add("WORD", "")
colBasicTypes.Add("FLOAT", "")
colBasicTypes.Add("PFLOAT", "")
colBasicTypes.Add("PBOOL", "")
colBasicTypes.Add("LPBOOL", "")
colBasicTypes.Add("PBYTE", "")
colBasicTypes.Add("LPBYTE", "")
colBasicTypes.Add("PINT", "")
colBasicTypes.Add("LPINT", "")
colBasicTypes.Add("PWORD", "")
colBasicTypes.Add("LPWORD", "")
colBasicTypes.Add("LPLONG", "")
colBasicTypes.Add("PDWORD", "")
colBasicTypes.Add("LPDWORD", "")
colBasicTypes.Add("LPVOID", "")
colBasicTypes.Add("LPCVOID", "")
colBasicTypes.Add("INT", "")
colBasicTypes.Add("UINT", "")
colBasicTypes.Add("PUINT", "")
colBasicTypes.Add("WPARAM", "")
colBasicTypes.Add("LPARAM", "")
colBasicTypes.Add("LRESULT", "")
' 필드 이름 생성
Dim strFieldName As String
strFieldName = strVarName
If Left(strFieldName, 2) = "m_" Then
strFieldName = Right(strFieldName, Len(strFieldName) - 2)
End If
If objRegex.IsMatch(strFieldName, "^[a-z]+[^a-z].+$") Then
strFieldName = objRegex.Replace(strFieldName, "^([a-z]+)([^a-z].+)$", "$2")
End If
' POD인지 아닌지 체크
Dim bComplexType = False
If objRegex.IsMatch(strVarType, "^c[A-Z][A-Za-z0-9]+[^\*\&]$") Then
' cDateTime, cTokenizer
bComplexType = True
ElseIf objRegex.IsMatch(strVarType, "^[A-Z0-9_]+[^\*\&]$") And Not colBasicTypes.ContainsKey(strVarType) Then
' D3DXVECTOR, OVERLAPPED
bComplexType = True
ElseIf objRegex.IsMatch(strVarType, "^.+<.+>$") Then
' std::vector<int>, cMyTemplate<bool>
bComplexType = True
End If
' 몇 가지 타입은 따로 처리
If strVarType = "std::string" Then strVarType = "const std::string&"
If strVarType = "tstring" Then strVarType = "const tstring&"
' Getter? Setter?
If strMode = "Getter" Then
If bComplexType Then
strResult += strVarType + "& Get" + strFieldName + "() { return " + strVarName + "; }" + CStr(Lf)
strResult += "const " + strVarType + "& Get" + strFieldName + "() const { return " + strVarName + "; }" + CStr(Lf)
ElseIf strVarType = "bool" Or strVarType = "BOOL" Then
strResult += strVarType + " Is" + strFieldName + "() const { return " + strVarName + "; }" + CStr(Lf)
Else
strResult += strVarType + " Get" + strFieldName + "() const { return " + strVarName + "; }" + CStr(Lf)
End If
Else
If bComplexType Then
strResult += "void Set" + strFieldName + "(const " + strVarType + "& value) { " + strVarName + " = value; }" + CStr(Lf) + CStr(Lf)
ElseIf strVarType = "bool" Or strVarType = "BOOL" Then
strResult += "void Set" + strFieldName + "(" + strVarType + " value) { " + strVarName + " = value; }" + CStr(Lf) + CStr(Lf)
Else
strResult += "void Set" + strFieldName + "(" + strVarType + " value) { " + strVarName + " = value; }" + CStr(Lf) + CStr(Lf)
End If
End If
End If
Return strResult
End Function
Sub MakeSimpleGetterSetter()
Dim objSel As TextSelection
Dim colTypes As New Collection
Dim colNames As New Collection
Dim colComments As New Collection
Dim objStream As New System.Text.StringBuilder
objSel = ActiveDocument().Selection
ParseVariableDeclarations(Trim(objSel.Text), colTypes, colNames, colComments)
For i = 1 To colNames.Count
objStream.Append(GenerateAccessor(colTypes.Item(i), colNames.Item(i), "Getter"))
objStream.Append(GenerateAccessor(colTypes.Item(i), colNames.Item(i), "Setter"))
Next
objSel.Text = objStream.ToString()
End Sub
ByVal strText As String, ByRef colTypes As Collection, ByRef colNames As Collection, ByRef colComments As Collection)
Dim nSpacePos As Integer
Dim nSemicolonPos As Integer
Dim nLineFeedPos As Integer
Dim bSuccess As Boolean
Dim strLine As String
Dim strVariableType As String
Dim strVariableName As String
Dim strVariableComment As String
' 2개 이상의 스페이스를 하나로 만든다.
Do
nSpacePos = InStr(strText, " ")
If nSpacePos <> 0 Then
strText = Replace(strText, " ", " ")
Else
Exit Do
End If
Loop
Do
' 더 이상 파싱할 게 없다면 빠져나간다
If Len(strText) = 0 Then
Exit Do
End If
' 라인 피드를 찾는다.
nLineFeedPos = InStr(strText, CStr(CrLf))
If nLineFeedPos <> 0 Then
' 라인 피드가 있다면 현재 라인을 얻어낸다.
strLine = Trim(Replace(Left(strText, nLineFeedPos - 1), vbTab, " "))
Else
' 라인 피드가 더 이상 없다면...
strLine = Trim(Replace(strText, vbTab, " "))
strText = ""
End If
' 라인 제일 처음 나오는 ';' 글자와 ';' 글자 앞에서 제일 처음 나타나는 ' ' 글자를 찾는다.
bSuccess = False
nSemicolonPos = InStr(strLine, ";")
If nSemicolonPos <> 0 Then
nSpacePos = InStrRev(strLine, " ", nSemicolonPos)
If nSpacePos <> 0 Then
bSuccess = True
End If
End If
' 두 글자 모두를 찾았다면, 변수 선언문이라고 할 수 있다.
If bSuccess Then
strVariableType = Trim(Mid(strLine, 1, nSpacePos))
strVariableName = Trim(Mid(strLine, nSpacePos, nSemicolonPos - nSpacePos))
strVariableComment = ""
If nSemicolonPos <> 0 Then
strVariableComment = Trim(Mid(strLine, nSemicolonPos + 1, Len(strLine) - nSemicolonPos))
End If
colTypes.Add(Trim(Replace(strVariableType, vbTab, " ")))
colNames.Add(Trim(Replace(strVariableName, vbTab, " ")))
colComments.Add(Trim(Replace(strVariableComment, vbTab, " ")))
'MsgBox("[" + vtype + "][" + vname + "][" + vcomment + "]")
End If
strText = Trim(Right(strText, Len(strText) - nLineFeedPos - 1))
Loop
End Function
Function GenerateAccessor(ByVal strVarType As String, ByVal strVarName As String, ByVal strMode As String)
Dim strResult As String
If strVarType <> "" And strVarName <> "" Then
Dim objRegex As New System.Text.RegularExpressions.Regex("")
Dim colBasicTypes As New System.Collections.Generic.Dictionary(Of String, String)
Dim objStream As New System.Text.StringBuilder
' 대문자로만 이루어졌지만, 구조체로 취급하지 않을 타입들 생성
colBasicTypes.Add("DWORD", "")
colBasicTypes.Add("BOOL", "")
colBasicTypes.Add("BYTE", "")
colBasicTypes.Add("WORD", "")
colBasicTypes.Add("FLOAT", "")
colBasicTypes.Add("PFLOAT", "")
colBasicTypes.Add("PBOOL", "")
colBasicTypes.Add("LPBOOL", "")
colBasicTypes.Add("PBYTE", "")
colBasicTypes.Add("LPBYTE", "")
colBasicTypes.Add("PINT", "")
colBasicTypes.Add("LPINT", "")
colBasicTypes.Add("PWORD", "")
colBasicTypes.Add("LPWORD", "")
colBasicTypes.Add("LPLONG", "")
colBasicTypes.Add("PDWORD", "")
colBasicTypes.Add("LPDWORD", "")
colBasicTypes.Add("LPVOID", "")
colBasicTypes.Add("LPCVOID", "")
colBasicTypes.Add("INT", "")
colBasicTypes.Add("UINT", "")
colBasicTypes.Add("PUINT", "")
colBasicTypes.Add("WPARAM", "")
colBasicTypes.Add("LPARAM", "")
colBasicTypes.Add("LRESULT", "")
' 필드 이름 생성
Dim strFieldName As String
strFieldName = strVarName
If Left(strFieldName, 2) = "m_" Then
strFieldName = Right(strFieldName, Len(strFieldName) - 2)
End If
If objRegex.IsMatch(strFieldName, "^[a-z]+[^a-z].+$") Then
strFieldName = objRegex.Replace(strFieldName, "^([a-z]+)([^a-z].+)$", "$2")
End If
' POD인지 아닌지 체크
Dim bComplexType = False
If objRegex.IsMatch(strVarType, "^c[A-Z][A-Za-z0-9]+[^\*\&]$") Then
' cDateTime, cTokenizer
bComplexType = True
ElseIf objRegex.IsMatch(strVarType, "^[A-Z0-9_]+[^\*\&]$") And Not colBasicTypes.ContainsKey(strVarType) Then
' D3DXVECTOR, OVERLAPPED
bComplexType = True
ElseIf objRegex.IsMatch(strVarType, "^.+<.+>$") Then
' std::vector<int>, cMyTemplate<bool>
bComplexType = True
End If
' 몇 가지 타입은 따로 처리
If strVarType = "std::string" Then strVarType = "const std::string&"
If strVarType = "tstring" Then strVarType = "const tstring&"
' Getter? Setter?
If strMode = "Getter" Then
If bComplexType Then
strResult += strVarType + "& Get" + strFieldName + "() { return " + strVarName + "; }" + CStr(Lf)
strResult += "const " + strVarType + "& Get" + strFieldName + "() const { return " + strVarName + "; }" + CStr(Lf)
ElseIf strVarType = "bool" Or strVarType = "BOOL" Then
strResult += strVarType + " Is" + strFieldName + "() const { return " + strVarName + "; }" + CStr(Lf)
Else
strResult += strVarType + " Get" + strFieldName + "() const { return " + strVarName + "; }" + CStr(Lf)
End If
Else
If bComplexType Then
strResult += "void Set" + strFieldName + "(const " + strVarType + "& value) { " + strVarName + " = value; }" + CStr(Lf) + CStr(Lf)
ElseIf strVarType = "bool" Or strVarType = "BOOL" Then
strResult += "void Set" + strFieldName + "(" + strVarType + " value) { " + strVarName + " = value; }" + CStr(Lf) + CStr(Lf)
Else
strResult += "void Set" + strFieldName + "(" + strVarType + " value) { " + strVarName + " = value; }" + CStr(Lf) + CStr(Lf)
End If
End If
End If
Return strResult
End Function
Sub MakeSimpleGetterSetter()
Dim objSel As TextSelection
Dim colTypes As New Collection
Dim colNames As New Collection
Dim colComments As New Collection
Dim objStream As New System.Text.StringBuilder
objSel = ActiveDocument().Selection
ParseVariableDeclarations(Trim(objSel.Text), colTypes, colNames, colComments)
For i = 1 To colNames.Count
objStream.Append(GenerateAccessor(colTypes.Item(i), colNames.Item(i), "Getter"))
objStream.Append(GenerateAccessor(colTypes.Item(i), colNames.Item(i), "Setter"))
Next
objSel.Text = objStream.ToString()
End Sub

글
댓글을 달아 주세요
댓글 RSS 주소 : http://serious-code.net/tc/rss/comment/9댓글 ATOM 주소 : http://serious-code.net/tc/atom/comment/9
좋은정본데.. 매크로를 한번도 안써봐서..
구글링을해도.. 어떻게 쓰는지 잘모르겠네용....
정말 죄송한데 매크로 추가부터 사용법을 좀 알려주시면 안될까요?...