From ebbfba7beff3ccdfd3a3ef64cee9eea2ef76a227 Mon Sep 17 00:00:00 2001 From: Michael Yan Date: Thu, 28 Nov 2024 11:47:41 +0800 Subject: [PATCH] Support `TemplateRenderer.template()` to find specific the root directory of the templates Closes gh-766 --- grace-cli/build.gradle | 2 + .../commands/template/TemplateRenderer.groovy | 12 +++++- .../template/TemplateRendererImpl.groovy | 41 +++++++++++++++---- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/grace-cli/build.gradle b/grace-cli/build.gradle index ca90bfbc75..b032306419 100644 --- a/grace-cli/build.gradle +++ b/grace-cli/build.gradle @@ -1,6 +1,8 @@ dependencies { api project(":grace-api") api project(":grace-bootstrap") + compileOnly libs.jansi + compileOnly libs.jline api libs.groovy.templates } diff --git a/grace-cli/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy b/grace-cli/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy index d9b05d5aaf..596372bd9c 100644 --- a/grace-cli/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy +++ b/grace-cli/src/main/groovy/grails/dev/commands/template/TemplateRenderer.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 the original author or authors. + * Copyright 2014-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.grails.io.support.Resource * API for locating and rendering templates in the code generation layer * * @author Graeme Rocher + * @author Michael Yan * @since 3.0 */ interface TemplateRenderer { @@ -162,6 +163,15 @@ interface TemplateRenderer { */ Iterable templates(String pattern) + /** + * Find a template at the given location + * + * @param templateRoot The template root + * @param location The location + * @return The resource or null if it doesn't exist + */ + Resource template(String templateRoot, Object location) + /** * Find a template at the given location * diff --git a/grace-cli/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy b/grace-cli/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy index 894e98c8c4..056dcae847 100644 --- a/grace-cli/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy +++ b/grace-cli/src/main/groovy/grails/dev/commands/template/TemplateRendererImpl.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 the original author or authors. + * Copyright 2016-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import groovy.text.Template import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import grails.build.logging.GrailsConsole import grails.codegen.model.Model import grails.dev.commands.io.FileSystemInteraction import grails.dev.commands.io.FileSystemInteractionImpl @@ -34,6 +35,7 @@ import org.grails.io.support.ResourceLoader * API for locating and rendering templates in the code generation layer * * @author Graeme Rocher + * @author Michael Yan * @since 3.2 */ @CompileStatic @@ -44,6 +46,8 @@ class TemplateRendererImpl implements TemplateRenderer { protected Map templateCache = [:] + GrailsConsole console = GrailsConsole.getInstance() + TemplateRendererImpl(File baseDir, ResourceLoader resourceLoader = new DefaultResourceLoader()) { this.fileSystemInteraction = new FileSystemInteractionImpl(baseDir, resourceLoader) } @@ -123,7 +127,7 @@ class TemplateRendererImpl implements TemplateRenderer { void render(File template, File destination, Map model = Collections.emptyMap(), boolean overwrite = false) { if (template && destination) { if (destination.exists() && !overwrite) { - println("Warning | Destination file ${projectPath(destination)} already exists, skipping...") + this.console.addStatus('skip '.padLeft(13), projectPath(destination), "YELLOW") } else { Template t = templateCache[template.absolutePath] @@ -138,8 +142,13 @@ class TemplateRendererImpl implements TemplateRenderer { } } try { + if (destination.exists() && overwrite) { + this.console.addStatus('force '.padLeft(13), projectPath(destination), "YELLOW") + } + else { + this.console.addStatus('create '.padLeft(13), projectPath(destination), "GREEN") + } writeTemplateToDestination(t, model, destination) - println("Rendered template ${template.name} to destination ${projectPath(destination)}") } catch (Throwable e) { destination.delete() @@ -171,7 +180,7 @@ class TemplateRendererImpl implements TemplateRenderer { void render(Resource template, File destination, Map model = Collections.emptyMap(), boolean overwrite = false) { if (template && destination) { if (destination.exists() && !overwrite) { - println("Warning | Destination file ${projectPath(destination)} already exists, skipping...") + this.console.addStatus('skip '.padLeft(13), projectPath(destination), "YELLOW") } else if (!template?.exists()) { throw new TemplateException("Template [$template.filename] not found.") @@ -200,8 +209,13 @@ class TemplateRendererImpl implements TemplateRenderer { } if (t != null) { try { + if (destination.exists() && overwrite) { + this.console.addStatus('force '.padLeft(13), projectPath(destination), "YELLOW") + } + else { + this.console.addStatus('create '.padLeft(13), projectPath(destination), "GREEN") + } writeTemplateToDestination(t, model, destination) - println("Rendered template ${template.filename} to destination ${projectPath(destination)}") } catch (Throwable e) { destination.delete() @@ -229,17 +243,28 @@ class TemplateRendererImpl implements TemplateRenderer { /** * Find a template at the given location * + * @param templateRoot The template root * @param location The location * @return The resource or null if it doesn't exist */ - Resource template(Object location) { - Resource f = resource(file("src/main/templates/$location")) + Resource template(String templateRoot, Object location) { + Resource f = resource(file("src/main/$templateRoot/$location")) if (!f?.exists()) { - return resource("classpath*:META-INF/templates/$location") + return resource("classpath*:META-INF/$templateRoot/$location") } resource(f) } + /** + * Find a template at the given location + * + * @param location The location + * @return The resource or null if it doesn't exist + */ + Resource template(Object location) { + template('templates', location) + } + protected static void writeTemplateToDestination(Template template, Map model, File destination) { destination.parentFile.mkdirs() destination.withWriter { BufferedWriter w ->