aboutsummaryrefslogtreecommitdiff
path: root/captain/template.f90
diff options
context:
space:
mode:
Diffstat (limited to 'captain/template.f90')
-rw-r--r--captain/template.f90148
1 files changed, 141 insertions, 7 deletions
diff --git a/captain/template.f90 b/captain/template.f90
index f3f6db1..ad4ea19 100644
--- a/captain/template.f90
+++ b/captain/template.f90
@@ -298,21 +298,106 @@ contains
call self%variables(i)%assign(name, value)
end subroutine template_assign_logical
+
+ function handle_template_extends(in_unit, extends_command) result(outfile)
+ use utilities, only: generate_temporary_filename
+ use config, only: template_filepath
+ implicit none
+
+ integer, intent(in)::in_unit
+ character(*), intent(in)::extends_command
+
+ character(len=:), pointer::outfile
+
+ integer::base_unit, out_unit
+ character(1024)::base_filename
+
+ character(256)::variable, varbuffer
+ character::this_char, last_char
- subroutine template_render(self, filename)
+ integer::i, istat
+
+ i = index(extends_command, "as")
+ if(i > 0) then
+ call template_filepath(trim(adjustl(extends_command(9:i-1))), base_filename)
+ variable = adjustl(extends_command(i+3:len_trim(extends_command)))
+
+ open(newunit=base_unit, file=trim(base_filename), status="old", &
+ form="unformatted", access="stream")
+
+ outfile => generate_temporary_filename()
+ open(newunit=out_unit, file=outfile, status="new", &
+ form="formatted", access="stream", action="write")
+
+ last_char = ' '
+ read(base_unit, iostat=istat) this_char
+ do while(istat == 0)
+
+ if(this_char == '{' .and. last_char == '{') then
+
+ varbuffer = '{{'
+
+ i = 2
+ do while(varbuffer(i-1:i) /= '}}' .and. istat == 0)
+ i = i + 1
+ read(base_unit, iostat=istat) varbuffer(i:i)
+ end do
+
+ ! Found our variable!
+ if( trim(variable) == trim(adjustl(varbuffer(4:i-3))) ) then
+
+ ! Write out the original input unit
+ read(in_unit, iostat=istat) this_char
+ do while(istat == 0)
+ write(out_unit, '(A1)', advance='no') this_char
+ read(in_unit, iostat=istat) this_char
+ end do
+
+ ! Not our variable
+ else
+
+ do i = 1, len_trim(varbuffer)
+ write(out_unit, '(A1)', advance='no') varbuffer(i:i)
+ end do
+
+ end if
+
+ last_char = ' '
+ this_char = ' '
+ else if(last_char == '{') then
+
+ write(out_unit, '(A1, A1)', advance='no') last_char, this_char
+
+ else if(this_char /= '{') then
+
+ write(out_unit, '(A1)', advance='no') this_char
+
+ end if
+
+ last_char = this_char
+ read(base_unit, iostat=istat) this_char
+ end do
+
+ close(base_unit)
+ close(out_unit)
+
+ end if
+
+ end function handle_template_extends
+
+ recursive subroutine template_render(self, filename, input_tempfile)
use logging
+ use utilities, only: delete_file
implicit none
class(template)::self
- character(*), intent(in), optional::filename
+ character(*), intent(in), optional::filename, input_tempfile
character::this_char, last_char
character(len=2)::running_pair, closing_pair
character(256)::brace_internals
character(len=:), pointer::replacement
- integer(kind=8)::input_position
-
logical::writing_now
integer::input, istat, i, unum
@@ -320,12 +405,18 @@ contains
if(present(filename)) then
allocate(character(len=len_trim(filename)) :: self%output_filename)
self%output_filename = trim(filename)
- else
+ else if(.not. associated(self%output_filename)) then
call self%generate_output_filename()
end if
- open(newunit=unum, file=trim(self%output_filename), status="new", form="formatted", access="stream", action="write")
- open(newunit=input, file=trim(self%base_filename), status="old", form="unformatted", access="stream")
+ open(newunit=unum, file=trim(self%output_filename), status="unknown", form="formatted", access="stream", action="write")
+
+ ! We may be working with a temporary file after a 'extends' tag
+ if(present(input_tempfile)) then
+ open(newunit=input, file=trim(input_tempfile), status="old", form="unformatted", access="stream")
+ else
+ open(newunit=input, file=trim(self%base_filename), status="old", form="unformatted", access="stream")
+ end if
writing_now = .true.
@@ -374,6 +465,49 @@ contains
end if
+ else if(running_pair == '{%') then
+
+ closing_pair = '%}'
+ brace_internals = ' '
+
+ read(input, iostat=istat) this_char
+ i = 1
+ do while(istat == 0 .and. (running_pair /= closing_pair))
+ brace_internals(i:i) = this_char
+
+ i = i + 1
+ last_char = this_char
+ read(input, iostat=istat) this_char
+ running_pair = last_char//this_char
+ end do
+ brace_internals(i-1:i-1) = ' ' ! Remove trailing bracket
+ brace_internals = adjustl(brace_internals)
+
+ ! Parse the command
+ if(brace_internals(1:8) == 'extends ') then
+
+ ! Replacement will be a new file to parse through this engine
+ replacement => handle_template_extends(input ,trim(brace_internals))
+
+ ! Close the current set of files before retrying the rendering
+ close(unum)
+ close(input)
+
+ ! Re-render using the constructed tempfile
+ if(associated(replacement)) then
+ call write_log("replacement template: "//trim(replacement), LOG_DEBUG)
+ call template_render(self, input_tempfile=replacement)
+ call write_log("template output: "//trim(self%output_filename), LOG_DEBUG)
+ ! It was temporary
+ call delete_file(replacement)
+ deallocate(replacement)
+ end if
+
+ ! Stop rendering - it was handled above
+ return
+
+ end if
+
else if(last_char == '{') then
write(unum, '(A1)', advance='no') last_char
write(unum, '(A1)', advance='no') this_char