diff options
Diffstat (limited to 'captain/template.f90')
-rw-r--r-- | captain/template.f90 | 148 |
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 |