Code Snippets For You, Part 3

Every coder has to deal with some repetitive tasks when they create a new application. Every new file added to your growing application, has some common properties, apart from selected language. Moreover, if you're into design patterns, these common properties become harder to repeat everytime you need them. Of course, i know, there are modern editors with code snippet support in these days.

However I invite you to imagine some apocalyptic scenario in which some crazy virus destroyed all Code-Snippet-Supporting-Editors. So we need to create our own code snippets, in order to re-create Code-Snippet-Supporting-Editors.

Someone has to do it, right?

In this part, we will complete GenerateClass method in our add_class script.

Class Generation

If we remember the last state of GenerateClass method:

def GenerateClass( class_name ):

  for t in templates:
    class_file_name = t.replace('_class_template_', class_name)
    with open(class_file_name, 'wt') as fClass:
      fClass.writelines(['TODO\n'])

We need to replace that ['TODO\n'] array with properly processed template lines. So we first get our template contents into our loop.

Check this out:

def GenerateClass( class_name ):

  for t in templates:

    template_lines = ReadTemplateFile( t )

    processed_lines = ProcessTemplate( template_lines, class_name)

    class_file_name = t.replace('_class_template_', class_name)
    with open(class_file_name, 'wt') as fClass:
      fClass.writelines(processed_lines)

As you see, we introduce two new functions: ReadTemplateFile and ProcessTemplate. First one fetches contents of given template file, and the second generates class contents by replacing template variables with given class name.

Reader and 'Dummy' Processor

Here is the basic form of these two functions:

...
def ReadTemplateFile( template_file ):

  lines = []
  with open(template_file, 'rt') as fTemplate:
    lines = fTemplate.readlines()

  return lines

def ProcessTemplate( template_lines, class_name ):

  # TODO : perform variable replacement here!

  return template_lines
...

Above, ReadTemplateFile is completed, but ProcessTemplate function is just returning template contents.

If we run add_class script at this point, it will write .cpp and .h files for given class names, and they will have raw template contents instead of previous TODO message.

Thus, final step for our script is to complete ProcessTemplate function.

Template Processing...

If we check the content of our templates carefully, we see that there are only two pattern for template variables : [[Name]] and [[NAME]]. It is possible to handle different styles of word casing (lowercase, camelCase, PascalCase, train-case, snake_case...), but we limit it with two styles. Either use it as it is ([[Name]] type) or convert it to uppercase ([[NAME]], as in guards).

So, here it is:

def ProcessTemplate( template_lines, class_name ):

  output_lines = []
  for line in template_lines:
    pass1_line = line.replace('[[Name]]', class_name)
    pass2_line = pass1_line.replace('[[NAME]]', class_name.upper())
    output_lines.append(pass2_line)

  return output_lines

After these changes, a look at add_class script reveals this:

When we run our script at this point with following parameters,

~/TemplateScripts$ ./add_class Warrior Warlock

four files, a cpp and a header for each Warrior and Warlock classes will be generated with desired content, in the current folder.

Almost done...

Even though we achieved the functionality we describe in our first post, there will be a final post to tune up this script, and also introduce a little bonus feature.

See you, soon.