Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 148 lines (123 sloc) 4.766 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
#! /usr/bin/env groovy

/**
* Script that recursively compares everything within {hidden} macros in a
* user guide translation with another gdoc source directory. By default,
* the translation is compared against the reference 'en' docs.
*/
if (!args || args.size() > 3) {
    println """\
USAGE
left_to_do LANG [LANG] [-nc]

where

LANG = a language code, e.g. 'en' or 'pt_BR'
-nc means: copy the new file if the target LANG file does not exist

Compares the contents of the {hidden} blocks in the user guide for the first language
against the entire contents of the second language. By default, the second language
is 'en', i.e. the reference user guide (which has no {hidden} blocks).\
""".stripIndent()
    System.exit 1
}


// Create a temporary directory to dump the extracted {hidden} contents to.
def tmpDocDir = new File("tmp")
if (tmpDocDir.exists()) {
    println "Removing the old temporary output directory"
    tmpDocDir.deleteDir()
}

tmpDocDir.mkdirs()

// Recursively copy the {hidden} blocks from the source language to the temporary
// directory, ensuring the resulting files have the same relative paths and names
// as the originals.
def srcDir = new File("src", args[0])
if (!srcDir.exists()) {
    println "No source directory for language '${args[0]}'"
    System.exit 2
}
def refDir = new File("src", args.size() >= 2 ? args[1] : 'en')
def isNc = (args.size() >= 3 && args[2]=='-nc') ? true :false
def ant = new AntBuilder()

srcDir.eachFileRecurse { f ->
    if (f.directory) {
        // Recreate this directory in the temporary output folder.
        new File(tmpDocDir, relativePath(srcDir, f)).mkdir()
    }
    else {
        // Read the source file, create a target file with the same
        // name and relative location, and write out the contents of
        // {hidden} blocks to that target file. Note the target file
        // will include the {hidden} macros.
        def relPathStr = relativePath(srcDir, f)
        def targetFile = new File(refDir, relPathStr)
        if (isNc && !targetFile.exists()) {
            if (!targetFile.parentFile.exists()) {
                targetFile.parentFile.mkdirs()
            }
            ant.copy(file:f,tofile:targetFile)
        }
        targetFile = new File(tmpDocDir, relPathStr)
        writeHiddenToFile f.text, targetFile
    }
}

// Now recursively diff the generated files against the reference directory.
generateDiff refDir, tmpDocDir

/// End of script execution ///


def relativePath(File baseDir, File file) {
    def relativePath = file.absolutePath - baseDir.absolutePath
    if (relativePath[0] == File.separator) relativePath = relativePath[1..-1]
    return relativePath
}

def writeHiddenToFile(String text, File target) {
    target.withWriter { w ->
        def marker = 0

        while (marker != -1) {
            def startHidden = findNextMacro(text, marker, "hidden")
            def startCode = findNextMacro(text, marker, "code")

            def start
            def macro
            def writeMacro = false
            if (startHidden != -1 && (startHidden < startCode || startCode == -1)) {
                macro = "hidden"
                start = startHidden
            }
            else {
                macro = "code"
                start = startCode
                writeMacro = true
            }
            def end = start == -1 ? -1 : findNextMacro(text, start + 1, macro)

            if (end != -1) {
                if (!writeMacro) {
                    start = start + macroLength(macro)
                }
                else {
                    end = end + macroLength(macro)
                }

                w << text.substring(start, end)
                
                if (writeMacro) w << '\n'

                marker = end
                if (!writeMacro) marker++
            }
            else {
                marker = -1
            }
        }
    }
}

def generateDiff(File refDir, File targetDir) {
    def pb = new ProcessBuilder(["diff", "--unified", "--recursive", refDir.absolutePath, targetDir.absolutePath])
    pb.redirectErrorStream true

    def process = pb.start()
    process.consumeProcessOutputStream System.out
    process.waitFor()
}

def findNextMacro(String text, start, macro) {
    // This matches {macro} and {macro:...} unless the opening
    // brace is escaped with a backslash. The first parentheses
    // correspond to a negative lookbehind to exclude '\{'.
    def m = text =~ /(?<!\\)\{${macro}(?::[^\}]+)?\}/
    m.region start, text.size()
    return m.find() ? m.start() : -1
}

def macroLength(macro) {
    // Length of macro name + 2 for the '{' and '}'
    return macro.size() + 2
}
Something went wrong with that request. Please try again.