|
1 | 1 | package summary |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "fmt" |
| 5 | + "os" |
4 | 6 | "strings" |
5 | 7 |
|
6 | 8 | "github.com/go-task/task/v3/internal/logger" |
@@ -29,6 +31,9 @@ func PrintSpaceBetweenSummaries(l *logger.Logger, i int) { |
29 | 31 | func PrintTask(l *logger.Logger, t *ast.Task) { |
30 | 32 | printTaskName(l, t) |
31 | 33 | printTaskDescribingText(t, l) |
| 34 | + printTaskVars(l, t) |
| 35 | + printTaskEnv(l, t) |
| 36 | + printTaskRequires(l, t) |
32 | 37 | printTaskDependencies(l, t) |
33 | 38 | printTaskAliases(l, t) |
34 | 39 | printTaskCommands(l, t) |
@@ -118,3 +123,186 @@ func printTaskCommands(l *logger.Logger, t *ast.Task) { |
118 | 123 | } |
119 | 124 | } |
120 | 125 | } |
| 126 | + |
| 127 | +// printTaskVars prints the variables defined in a task in YAML format. |
| 128 | +// It displays the vars section with proper indentation and formatting. |
| 129 | +// Filters out OS environment variables, auto-generated Task variables, and Taskfile env vars. |
| 130 | +// Returns early if the task has no variables defined. |
| 131 | +func printTaskVars(l *logger.Logger, t *ast.Task) { |
| 132 | + if t.Vars == nil || t.Vars.Len() == 0 { |
| 133 | + return |
| 134 | + } |
| 135 | + |
| 136 | + // Create a set of OS environment variable names to filter them out |
| 137 | + osEnvVars := getEnvVarNames() |
| 138 | + |
| 139 | + // Create a set of Taskfile env variable names to avoid duplication |
| 140 | + taskfileEnvVars := make(map[string]bool) |
| 141 | + if t.Env != nil { |
| 142 | + for key := range t.Env.All() { |
| 143 | + taskfileEnvVars[key] = true |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + // Check if there are any non-environment variables to display |
| 148 | + hasNonEnvVars := false |
| 149 | + for key := range t.Vars.All() { |
| 150 | + if !isEnvVar(key, osEnvVars) && !taskfileEnvVars[key] { |
| 151 | + hasNonEnvVars = true |
| 152 | + break |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + if !hasNonEnvVars { |
| 157 | + return |
| 158 | + } |
| 159 | + |
| 160 | + l.Outf(logger.Default, "\n") |
| 161 | + l.Outf(logger.Default, "vars:\n") |
| 162 | + |
| 163 | + for key, value := range t.Vars.All() { |
| 164 | + // Only display variables that are not from OS environment or Taskfile env |
| 165 | + if !isEnvVar(key, osEnvVars) && !taskfileEnvVars[key] { |
| 166 | + formattedValue := formatVarValue(value) |
| 167 | + l.Outf(logger.Yellow, " %s: %s\n", key, formattedValue) |
| 168 | + } |
| 169 | + } |
| 170 | +} |
| 171 | + |
| 172 | +// printTaskEnv prints the environment variables defined in a task in YAML format. |
| 173 | +// It displays the env section with proper indentation and formatting. |
| 174 | +// Filters out OS environment variables and auto-generated Task variables. |
| 175 | +// Returns early if the task has no environment variables defined. |
| 176 | +func printTaskEnv(l *logger.Logger, t *ast.Task) { |
| 177 | + if t.Env == nil || t.Env.Len() == 0 { |
| 178 | + return |
| 179 | + } |
| 180 | + |
| 181 | + // Create a set of OS environment variable names to filter them out |
| 182 | + envVars := getEnvVarNames() |
| 183 | + |
| 184 | + // Check if there are any non-environment variables to display |
| 185 | + hasNonEnvVars := false |
| 186 | + for key := range t.Env.All() { |
| 187 | + if !isEnvVar(key, envVars) { |
| 188 | + hasNonEnvVars = true |
| 189 | + break |
| 190 | + } |
| 191 | + } |
| 192 | + |
| 193 | + if !hasNonEnvVars { |
| 194 | + return |
| 195 | + } |
| 196 | + |
| 197 | + l.Outf(logger.Default, "\n") |
| 198 | + l.Outf(logger.Default, "env:\n") |
| 199 | + |
| 200 | + for key, value := range t.Env.All() { |
| 201 | + // Only display variables that are not from OS environment |
| 202 | + if !isEnvVar(key, envVars) { |
| 203 | + formattedValue := formatVarValue(value) |
| 204 | + l.Outf(logger.Yellow, " %s: %s\n", key, formattedValue) |
| 205 | + } |
| 206 | + } |
| 207 | +} |
| 208 | + |
| 209 | +// formatVarValue formats a variable value based on its type. |
| 210 | +// Handles static values, shell commands (sh:), references (ref:), and maps. |
| 211 | +func formatVarValue(v ast.Var) string { |
| 212 | + // Shell command - check this first before Value |
| 213 | + // because dynamic vars may have both Sh and an empty Value |
| 214 | + if v.Sh != nil { |
| 215 | + return fmt.Sprintf("sh: %s", *v.Sh) |
| 216 | + } |
| 217 | + |
| 218 | + // Reference |
| 219 | + if v.Ref != "" { |
| 220 | + return fmt.Sprintf("ref: %s", v.Ref) |
| 221 | + } |
| 222 | + |
| 223 | + // Static value |
| 224 | + if v.Value != nil { |
| 225 | + // Check if it's a map or complex type |
| 226 | + if m, ok := v.Value.(map[string]any); ok { |
| 227 | + return formatMap(m, 4) |
| 228 | + } |
| 229 | + // Simple string value |
| 230 | + return fmt.Sprintf(`"%v"`, v.Value) |
| 231 | + } |
| 232 | + |
| 233 | + return `""` |
| 234 | +} |
| 235 | + |
| 236 | +// formatMap formats a map value with proper indentation for YAML. |
| 237 | +func formatMap(m map[string]any, indent int) string { |
| 238 | + if len(m) == 0 { |
| 239 | + return "{}" |
| 240 | + } |
| 241 | + |
| 242 | + var result strings.Builder |
| 243 | + result.WriteString("\n") |
| 244 | + spaces := strings.Repeat(" ", indent) |
| 245 | + |
| 246 | + for k, v := range m { |
| 247 | + result.WriteString(fmt.Sprintf("%s%s: %v\n", spaces, k, v)) |
| 248 | + } |
| 249 | + |
| 250 | + return result.String() |
| 251 | +} |
| 252 | + |
| 253 | +// printTaskRequires prints the required variables for a task in YAML format. |
| 254 | +// It displays the requires section with proper indentation and formatting. |
| 255 | +// Returns early if the task has no required variables. |
| 256 | +func printTaskRequires(l *logger.Logger, t *ast.Task) { |
| 257 | + if t.Requires == nil || len(t.Requires.Vars) == 0 { |
| 258 | + return |
| 259 | + } |
| 260 | + |
| 261 | + l.Outf(logger.Default, "\n") |
| 262 | + l.Outf(logger.Default, "requires:\n") |
| 263 | + l.Outf(logger.Default, " vars:\n") |
| 264 | + |
| 265 | + for _, v := range t.Requires.Vars { |
| 266 | + // If the variable has enum constraints, format accordingly |
| 267 | + if len(v.Enum) > 0 { |
| 268 | + l.Outf(logger.Yellow, " - %s:\n", v.Name) |
| 269 | + l.Outf(logger.Yellow, " enum:\n") |
| 270 | + for _, enumValue := range v.Enum { |
| 271 | + l.Outf(logger.Yellow, " - %s\n", enumValue) |
| 272 | + } |
| 273 | + } else { |
| 274 | + // Simple required variable |
| 275 | + l.Outf(logger.Yellow, " - %s\n", v.Name) |
| 276 | + } |
| 277 | + } |
| 278 | +} |
| 279 | + |
| 280 | +// getEnvVarNames returns a set of all OS environment variable names. |
| 281 | +func getEnvVarNames() map[string]bool { |
| 282 | + envMap := make(map[string]bool) |
| 283 | + for _, e := range os.Environ() { |
| 284 | + parts := strings.SplitN(e, "=", 2) |
| 285 | + if len(parts) > 0 { |
| 286 | + envMap[parts[0]] = true |
| 287 | + } |
| 288 | + } |
| 289 | + return envMap |
| 290 | +} |
| 291 | + |
| 292 | +// isEnvVar checks if a variable is from OS environment or auto-generated by Task. |
| 293 | +func isEnvVar(key string, envVars map[string]bool) bool { |
| 294 | + // Filter out auto-generated Task variables |
| 295 | + if strings.HasPrefix(key, "TASK_") || |
| 296 | + strings.HasPrefix(key, "CLI_") || |
| 297 | + strings.HasPrefix(key, "ROOT_") || |
| 298 | + key == "TASK" || |
| 299 | + key == "TASKFILE" || |
| 300 | + key == "TASKFILE_DIR" || |
| 301 | + key == "USER_WORKING_DIR" || |
| 302 | + key == "ALIAS" || |
| 303 | + key == "MATCH" { |
| 304 | + return true |
| 305 | + } |
| 306 | + // Filter out OS environment variables |
| 307 | + return envVars[key] |
| 308 | +} |
0 commit comments