| 122 | |
| 123 | } |
| 124 | func executeCodeBlock(codeBlock *CodeBlock, args ...string) error { |
| 125 | |
| 126 | // Create a map for the template arguments |
| 127 | argMap := make(map[string]string) |
| 128 | for i, arg := range args { |
| 129 | argMap[fmt.Sprintf("arg%d", i+1)] = arg |
| 130 | } |
| 131 | |
| 132 | // Validate that all placeholders in the template are provided in args and vice versa |
| 133 | placeholderPattern := regexp.MustCompile(`{{\s*\.arg(\d+)\s*}}`) |
| 134 | matches := placeholderPattern.FindAllStringSubmatch(codeBlock.Code, -1) |
| 135 | |
| 136 | placeholderSet := make(map[string]struct{}) |
| 137 | for _, match := range matches { |
| 138 | placeholderSet[match[1]] = struct{}{} |
| 139 | } |
| 140 | |
| 141 | for i := range args { |
| 142 | argKey := fmt.Sprintf("%d", i+1) |
| 143 | if _, ok := placeholderSet[argKey]; !ok { |
| 144 | return fmt.Errorf("%w: argument: %d (\"%s\")", ErrArgProvidedButNotUsed, i+1, args[i]) |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | for placeholder := range placeholderSet { |
| 149 | argIndex := fmt.Sprintf("arg%s", placeholder) |
| 150 | if _, ok := argMap[argIndex]; !ok { |
| 151 | return fmt.Errorf("%w: {{.arg%s}}", ErrArgUsedInTemplateNotProvided, placeholder) |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | tmpl, err := template.New("command").Parse(codeBlock.Code) |
| 156 | if err != nil { |
| 157 | return fmt.Errorf("failed to parse template: %v", err) |
| 158 | } |
| 159 | |
| 160 | var renderedCode bytes.Buffer |
| 161 | err = tmpl.Execute(&renderedCode, argMap) |
| 162 | if err != nil { |
| 163 | return fmt.Errorf("failed to execute template: %v", err) |
| 164 | } |
| 165 | |
| 166 | launcher, ok := launchers[codeBlock.Lang] |
| 167 | if !ok && !codeBlock.Config.SheBang { |
| 168 | return fmt.Errorf("%w: %s", ErrNoInfostringOrShebang, codeBlock.Lang) |
| 169 | } |
| 170 | |
| 171 | // Write the rendered code to the temporary file |
| 172 | tmpFile, err := os.CreateTemp("", fmt.Sprintf("mdx-*.%s", launcher.extension)) |
| 173 | if err != nil { |
| 174 | return fmt.Errorf("failed to create temporary file: %v", err) |
| 175 | } |
| 176 | // Set the permissions of the temporary file to 755 |
| 177 | if err := os.Chmod(tmpFile.Name(), 0755); err != nil { |
| 178 | return fmt.Errorf("failed to set permissions on temporary file: %v", err) |
| 179 | } |
| 180 | |
| 181 | defer os.Remove(tmpFile.Name()) |