split_cmd_after_subcmd Subroutine

public subroutine split_cmd_after_subcmd(full, prefix, rest)

Split a command line into <fpm subcmd> prefix and remaining arguments.

This is used to support name injection for fpm run/fpm test: the injected names are inserted after prefix and before the rest, while respecting a -- delimiter.

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: full

Full command string.

character(len=:), intent(out), allocatable :: prefix

Prefix up to and including the subcommand token.

character(len=:), intent(out), allocatable :: rest

Remaining arguments after the subcommand.


Called by

proc~~split_cmd_after_subcmd~~CalledByGraph proc~split_cmd_after_subcmd split_cmd_after_subcmd proc~parse_cli_config parse_cli_config proc~parse_cli_config->proc~split_cmd_after_subcmd

Source Code

   subroutine split_cmd_after_subcmd(full, prefix, rest)
      character(len=*), intent(in) :: full
      !! Full command string.
      character(len=:), allocatable, intent(out) :: prefix
      !! Prefix up to and including the subcommand token.
      character(len=:), allocatable, intent(out) :: rest
      !! Remaining arguments after the subcommand.

      character(len=:), allocatable :: s
      integer :: p_fpm_end, p_sub_start, p_sub_end

      s = adjustl(trim(full))
      prefix = ""
      rest   = ""

      if (len_trim(s) == 0) return
      if (.not. starts_with_token(s, "fpm")) return

      p_fpm_end = token_end(s, 1)
      p_sub_start = next_token_start(s, p_fpm_end + 1)
      if (p_sub_start == 0) return
      p_sub_end = token_end(s, p_sub_start)

      prefix = trim(s(1:p_sub_end))
      if (p_sub_end < len_trim(s)) then
         rest = adjustl(s(p_sub_end+1:))
      else
         rest = ""
      end if

   contains

      pure logical function starts_with_token(str, tok) result(ok)
         character(len=*), intent(in) :: str, tok
         integer :: e, n
         ok = .false.
         n = len_trim(tok)
         if (n == 0) return
         if (len_trim(str) < n) return
         if (str(1:n) /= tok(1:n)) return
         e = token_end(str, 1)
         ok = (e == n)
      end function starts_with_token

      pure integer function next_token_start(str, i) result(pos)
         character(len=*), intent(in) :: str
         integer, intent(in) :: i
         integer :: k, n
         pos = 0
         n = len_trim(str)
         k = max(1, i)
         do while (k <= n)
            if (str(k:k) /= " " .and. str(k:k) /= char(9)) then
               pos = k
               return
            end if
            k = k + 1
         end do
      end function next_token_start

      pure integer function token_end(str, i) result(pos)
         character(len=*), intent(in) :: str
         integer, intent(in) :: i
         integer :: k, n
         pos = 0
         n = len_trim(str)
         if (i < 1 .or. i > n) return
         k = i
         do while (k <= n)
            if (str(k:k) == " " .or. str(k:k) == char(9)) then
               pos = k - 1
               return
            end if
            k = k + 1
         end do
         pos = n
      end function token_end

   end subroutine split_cmd_after_subcmd