Commits

bogeymin  committed d5ebc4f

Various improvements and bug fixes.

- First steps toward generating proper ReStructuredText output for text format.
- Better handling of printing the file name in text format.
- Output is organized by file.
- Killing the script with CTRL + C no longer results in ugly errors.

  • Participants
  • Parent commits 7ece85f

Comments (0)

Files changed (2)

 
 This will result in output that looks something like this:
 
-    ===============================================================================
+    ========
     REFACTOR
-    ===============================================================================
+    ========
 
-    This whole section could be replaced with 3 lines of code.
     kludge.py
+    ---------
+
+    This whole section could be replaced with 3 lines of code.
 
 ## Installation
 
 - If you have two gotchas, one after the other, make sure there is a blank line
   in between them. Otherwise, they will be matched as a single gotcha.
 
+## New in this Version
+
+- First steps toward generating proper ReStructuredText output for text format.
+- Better handling of printing the file name in text format.
+- Output is organized by file.
+- Killing the script with CTRL + C no longer results in ugly errors.
+
 ## Ideas and To-dos
 
-- Facilitate including and capturing some basic meta data with each gotacha.
-  - `NOTE: This is a note with an author and date. [Bob | Nov 4, 2011].`
-  - `TODO: Need to fix IE display problems. {design}`.
+- Facilitate including and capturing some basic meta data with each gotcha.
+    - Meta data should be contained in [brackets].
+    - Generally speaking, meta data should be placed at the end of the gotcha.
+      However, if it makes sense for the data to be within the gotcha text, then
+      place it there instead.
+    - Line wraps should never occur within the brackets.
+    - Separate multiple meta data entries with a | pipe.
+    - Define various standard codes, such as:
+        - a: <author name, email or initials>
+        - d: <date YYYY-MM-DD>
+        - e: <estimated hours>
+        - t: <ticket_id>
+    - Examples:
+        - QUESTION: Should measures be tied to objectives or goals? [a: Bob].
+        - NOTE: As of [d: 2012-09-12] there is a bug with the compiler that
+          causes unexpected output.
+        - TODO: Implement the connection between the local database and the
+          remote API. [e: 4]
+        - BUG: Clean up this area of the code in response to [t: 1234].
+- Facilitate including and capturing tags within the gotcha.
+    - Tags are enclosed in {curly brackets}.
+    - Tags may be only a single word.
+    - Tags must only appear at the end of the gotcha.
+    - Multiple tags are separated by a comma.
+    - Examples:
+        - BUG: This form renders very badly in IE. {design}
+        - QUESTION: What are the memory requirements for this third-party
+          module? {admin}
+        - TODO: Implement the connection between the local database and the
+          remote API. {programming}
 - HTML output could certainly be improved.
-- Better handling of printing the file name in both text and html format.
-- Option to organize output by file.
-- Killing the script with CTRL + C results in ugly errors.
+- Better handling of printing the file name in HTML format.
 - CSV output format.

File gotchagrep.py

 -f <format>
     Format of the output; "text" (the default), or "html".
 
+--file-decorator=<character>
+    Files are represented as sub-headings in the text output. The default
+    decorator is "-".
+
 -g <gotcha>
     The string to be found. Defaults to "TODO:"
 
     Path to the code in question. Defaults to '.'
 
 -t <title>
-    Optional title for the output.
+    Optional title for the output. Defaults to the gotcha name above.
+
+--title-decorator=<character>
+    The character to use for the title decoration in text-only output. Defaults
+    to "=".
 
 -v
     Print version and exit.
 # Administrivia
 __author__ = "F.S. Davis <consulting@fsdavis.com>"
 __command__ = os.path.basename(sys.argv[0])
-__date__ = "Nov 4, 2011"
-__version__ = "0.2.1-d"
+__date__ = "2012-09-12"
+__version__ = "0.3.0-d"
 
 # Functions
 
 
     # Capture options and arguments.
     try:
-        options, arguments = getopt.getopt(sys.argv[1:], "e:f:g:hL:p:t:v", ["help", "version"])
+        options, arguments = getopt.getopt(sys.argv[1:], "e:f:g:hL:p:t:v", ["help", "file-decorator=", "title-decorator=", "version"])
     except getopt.GetoptError, err:
         print str(err)
         sys.exit(1)
 
     # Set defaults.
     extension = "*"
+    file_decorator = '-'
     format = "text"
     gotcha = 'TODO:'
     leader = "# "
     path = '.'
     title = None
+    title_decorator = '='
 
     # Parse options.
     for name, value in options:
             extension = value
         elif '-f' == name:
             format = value
+        elif '--file-decorator' == name:
+            file_decorator = value
         elif '-g' == name:
             gotcha = value
         elif '-L' == name:
             path = value
         elif '-t' == name:
             title = value
+        elif '--title-decorator' == name:
+            title_decorator = value
         else:
             assert False, "Unhandled option: %s" %(name)
 
     # The title should default to the gotcha string.
-    if title is None: title = gotcha
+    if title is None:
+        title = gotcha
+    title_decorator_length = len(title)
 
     # Get a list of files. This seemed to be easiest to do by calling find and
     # splitting the results.
     (status, output) = commands.getstatusoutput('find %s -type f -name "*.%s"' % (path, extension))
     files = output.split('\n')
 
-    # Check each file for the desired gotcha.
-    pattern = "^%s%s" % (leader, gotcha)
-    matches = list()
-    for f in files:
-
-        # Again, it seemed easiest to let grep determine if there is a match in
-        # each file. (Why not use grep? It doesn't support newlines.) I tried
-        # using Python's regex to obtain matches from within # the content
-        # string, but it never quite worked as I expected. So grep is used to
-        # know if the file contains a match, and a simple line-by-line review
-        # is used to capture multi-line gotchas.
-        (status, output) = commands.getstatusoutput('grep "%s" %s' % (gotcha, f))
-        if status == 0:
-            h = open(f, 'rb')
-            content = h.read().split("\n")
-            h.close()
-
-            start = False
-            for line in content:
-                if re.match(pattern, line):
-                    start = True
-                    match = list()
-                    match.append(f)
-                    match.append(line)
-                elif start == True:
-                    if len(line) == 0:
-                        start = False
-                        matches.append(match)
+    # Run the processing within a try to catch keyboard interrupts.
+    try:
+        # Check each file for the desired gotcha.
+        pattern = "^%s%s" % (leader, gotcha)
+        matches = list()
+        for f in files:
+
+            # Again, it seemed easiest to let grep determine if there is a match in
+            # each file. (Why not use grep? It doesn't support newlines.) I tried
+            # using Python's regex to obtain matches from within # the content
+            # string, but it never quite worked as I expected. So grep is used to
+            # know if the file contains a match, and a simple line-by-line review
+            # is used to capture multi-line gotchas.
+            (status, output) = commands.getstatusoutput('grep "%s" %s' % (gotcha, f))
+            if status == 0:
+                h = open(f, 'rb')
+                content = h.read().split("\n")
+                h.close()
+
+                file_decorator_length = len(f)
+                matches.append((f, file_decorator * file_decorator_length))
+
+                start = False
+                for line in content:
+                    line_stripped = line.lstrip()
+                    if re.match(pattern, line_stripped):
+                        start = True
+                        match = list()
+                        #match.append(f)
+                        match.append(line_stripped)
+                    elif start == True:
+                        if len(line) == 0:
+                            start = False
+                            matches.append(match)
+                        else:
+                            match.append(line)
                     else:
-                        match.append(line)
-                else:
-                    pass
+                        pass
+    except KeyboardInterrupt:
+        sys.exit()
 
     # Give up if there were no matches.
     if len(matches) == 0:
         print wrap_html("h1", title)
         print "<ul>"
     else:
-        print "=" * 79
+        print ""
+        #print "=" * 79
         print title
-        print "=" * 79
+        print title_decorator * title_decorator_length
         print ""
 
     # Print each match in the appropriate format.