HiveBrain v1.2.0
Get Started
← Back to all entries
snippetbashModerate

Create New C++ Class

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
classnewcreate

Problem

I'm currently developing a new version of ExpressGenGen Using TDD. While I'm rewriting the new version of my Code Generator Generator.
I'm using its old version to generate code to be used by the new version.
This is how I'm creating new classes: when a new class is created,
it will generate a .cpp and .h file and then add them to CMakeLists.txt,
and also TestHelper.h is updated with new headers.

What I want reviewed are the bash scripts. (You are also welcome to review the ExpressGenGen templates)

Bash Scripts

gen

#!/bin/bash

cd ..
cat Samples/template_bash_CMakeLists.txt | xgengen bash | bash - > CMakeLists.txt
cat Samples/template_bash_TestHelper.txt | xgengen bash | bash - > Tests/TestHelper.h


new_class

#!/bin/bash

echo 'Create New Class'
echo '--------------------------'
echo 'Type Class Name : '
read _class
# convert Upper Camel case to header guard, ex: NewClass -> _NEW_CLASS_H_
_guard=`echo $_class | sed -e 's/\([A-Z]\)/_\1/g' | awk '{printf toupper($0)} END{printf "_H_";}'`
# export the variables so they are visible to the child shell
export guard=$_guard
export class=$_class
cat template_bash_CPP.txt | xgengen bash | bash - > "../Src/$class.cpp"
cat template_bash_H.txt | xgengen bash | bash - > "../Src/$class.h"
./gen


Templates

template_bash_CMakeLists.txt

```
project(ExpressGenGen)

cmake_minimum_required(VERSION 2.6)
include_directories($ENV{BOOST_ROOT} $ENV{LUA_ROOT} $ENV{GMOCK_HOME}/include $ENV{GMOCK_HOME}/gtest/include .)
link_directories($ENV{LUA_ROOT} $ENV{BOOST_ROOT}/stage/lib $ENV{GMOCK_HOME}/build $ENV{GMOCK_HOME}/build/gtest)
set(CMAKE_CXX_FLAGS "${CMAXE_CXX_FLAGS} -Wall -Wpedantic -std=gnu++11")

set(sources
$$$find . -name '*.cpp' | sed 's/\.\// /'
$$$find . -name '*.h' | sed 's/\.\// /'
WindowsRsrc/WindowsRes.rc)
add_executable(xgengen ${sources})
target_link_libraries(xgengen lua)
target_link_libraries(xgengen boost_program_options)
target_link_libraries(xgengen pthread)
target_link_libraries(x

Solution

Use input redirection instead of cat | ...

Instead of cat somefile | somecommand, you should use input redirection, for example:

xgengen bash  CMakeLists.txt


The advantage of this is that you're running one fewer process (no more cat).

Use modern style command substitution $(...)

Don't use old style `... command substitution.
Use the modern and better
$(...) style.

Simplify
sed + awk pipelines when possible

This looks very complicated, and it's suspicious to have both
sed and awk in the same pipeline:

echo $_class | sed -e 's/\([A-Z]\)/_\1/g' | awk '{printf toupper($0)} END{printf "_H_";}'


You can simplify using a single
awk command:

echo $_class | awk '{gsub("[A-Z]", "_\&"); printf toupper($0) "_H_"}'


Use here-strings instead of
echo | ...

Similar to using input redirection instead of
cat | ...,
in Bash it's better to replace
echo | ... with here-strings using

  • No need to escape . in replacement, as it has no special meaning there



  • No need to escape " within single-quoted strings in Bash



  • Since the pattern matches the entire line, no need for the g flag

Code Snippets

xgengen bash < Samples/template_bash_CMakeLists.txt | bash - > CMakeLists.txt
echo $_class | sed -e 's/\([A-Z]\)/_\1/g' | awk '{printf toupper($0)} END{printf "_H_";}'
echo $_class | awk '{gsub("[A-Z]", "_\&"); printf toupper($0) "_H_"}'
awk '{gsub("[A-Z]", "_\&"); printf toupper($0) "_H_"}' <<< $_class
sed 's/\.\//  /'

Context

StackExchange Code Review Q#80598, answer score: 15

Revisions (0)

No revisions yet.