From 440c33b3b36310e321102bd78d99ec020084b7b6 Mon Sep 17 00:00:00 2001
From: Harald Albers <github@albersweb.de>
Date: Sun, 19 Jan 2025 22:32:32 +0000
Subject: [PATCH 1/4] The default ShellCompDirective can be configured

---
 completions.go                     |  5 +++-
 completions_test.go                | 42 ++++++++++++++++++++++++++++++
 site/content/completions/_index.md | 23 ++++++++++++++++
 3 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/completions.go b/completions.go
index 0862d3f6..7c501fd9 100644
--- a/completions.go
+++ b/completions.go
@@ -115,6 +115,9 @@ type CompletionOptions struct {
 	DisableDescriptions bool
 	// HiddenDefaultCmd makes the default 'completion' command hidden
 	HiddenDefaultCmd bool
+	// DefaultShellCompDirective sets the ShellCompDirective that is returned
+	// if no special directive can be determined
+	DefaultShellCompDirective ShellCompDirective
 }
 
 // NoFileCompletions can be used to disable file completion for commands that should
@@ -451,7 +454,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
 			return finalCmd, completions, directive, nil
 		}
 	} else {
-		directive = ShellCompDirectiveDefault
+		directive = finalCmd.CompletionOptions.DefaultShellCompDirective
 		if flag == nil {
 			foundLocalNonPersistentFlag := false
 			// If TraverseChildren is true on the root command we don't check for
diff --git a/completions_test.go b/completions_test.go
index a8f378eb..19c577a4 100644
--- a/completions_test.go
+++ b/completions_test.go
@@ -3742,3 +3742,45 @@ func TestDisableDescriptions(t *testing.T) {
 		})
 	}
 }
+
+func TestCustomDefaultShellCompDirective(t *testing.T) {
+	rootCmd := &Command{Use: "root", Run: emptyRun}
+	rootCmd.Flags().String("string", "", "test string flag")
+	// use ShellCompDirectiveNoFileComp instead of the default, which is ShellCompDirectiveDefault
+	rootCmd.CompletionOptions.DefaultShellCompDirective = ShellCompDirectiveNoFileComp
+
+	testCases := []struct {
+		desc string
+		args []string
+	}{
+		{
+			"args completion with custom ShellCompDirective",
+			[]string{""},
+		},
+		{
+			"flag completion with custom ShellCompDirective",
+			[]string{"--string", ""},
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.desc, func(t *testing.T) {
+			args := []string{ShellCompNoDescRequestCmd}
+			args = append(args, tc.args...)
+
+			output, err := executeCommand(rootCmd, args...)
+
+			if err != nil {
+				t.Errorf("Unexpected error: %v", err)
+			}
+
+			expected := strings.Join([]string{
+				":4",
+				"Completion ended with directive: ShellCompDirectiveNoFileComp", ""}, "\n")
+
+			if output != expected {
+				t.Errorf("expected: %q, got: %q", expected, output)
+			}
+		})
+	}
+}
diff --git a/site/content/completions/_index.md b/site/content/completions/_index.md
index 02257ade..afab3f6d 100644
--- a/site/content/completions/_index.md
+++ b/site/content/completions/_index.md
@@ -304,6 +304,29 @@ $ helm status --output [tab][tab]
 json table yaml
 ```
 
+#### Change the default ShellCompDirective
+
+If Cobra cannot determine a special `ShellCompDirective` during flag parsing,
+it will return `ShellCompDirectiveDefault`, which will invoke the shell's filename completion.
+This is handy for flags that accept filenames, as they do not require a `FlagCompletionFunc`.
+
+For other flags where no meaningful completion can be provided, this requires extra work:
+You have to register a `FlagCompletionFunc` just to get rid of file completion.
+
+If you find yourself registering lots of handlers like
+
+```go
+cmd.RegisterFlagCompletionFunc("flag-name", cobra.NoFileCompletions)
+```
+
+you can change the default `ShellCompDirective` to `ShellCompDirectiveNoFileComp`:
+
+```go
+cmd.CompletionOptions.DefaultShellCompDirective = ShellCompDirectiveNoFileComp
+```
+
+Keep in mind that from now on you have to register handlers for every filename flag.
+
 #### Debugging
 
 You can also easily debug your Go completion code for flags:

From 33e3ac194f892d993afde4f5c5076334839ec976 Mon Sep 17 00:00:00 2001
From: Harald Albers <github@albersweb.de>
Date: Mon, 20 Jan 2025 08:17:22 +0000
Subject: [PATCH 2/4] Be more explicit about the default ShellCompDirective

---
 completions.go | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/completions.go b/completions.go
index 7c501fd9..0c5c2ec7 100644
--- a/completions.go
+++ b/completions.go
@@ -454,7 +454,13 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
 			return finalCmd, completions, directive, nil
 		}
 	} else {
-		directive = finalCmd.CompletionOptions.DefaultShellCompDirective
+		customShellCompDirective := finalCmd.CompletionOptions.DefaultShellCompDirective
+		if customShellCompDirective != ShellCompDirectiveDefault {
+			directive = customShellCompDirective
+		} else {
+			directive = ShellCompDirectiveDefault
+		}
+
 		if flag == nil {
 			foundLocalNonPersistentFlag := false
 			// If TraverseChildren is true on the root command we don't check for

From b4f26aebb91f267bd595ade69839ac998f2e1dce Mon Sep 17 00:00:00 2001
From: Harald Albers <albers@users.noreply.github.com>
Date: Tue, 21 Jan 2025 09:10:52 +0100
Subject: [PATCH 3/4] Apply suggestions from code review

Co-authored-by: ccoVeille <3875889+ccoVeille@users.noreply.github.com>
---
 completions.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/completions.go b/completions.go
index 0c5c2ec7..b404322f 100644
--- a/completions.go
+++ b/completions.go
@@ -454,11 +454,11 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
 			return finalCmd, completions, directive, nil
 		}
 	} else {
+		directive = ShellCompDirectiveDefault
+		
 		customShellCompDirective := finalCmd.CompletionOptions.DefaultShellCompDirective
 		if customShellCompDirective != ShellCompDirectiveDefault {
 			directive = customShellCompDirective
-		} else {
-			directive = ShellCompDirectiveDefault
 		}
 
 		if flag == nil {

From 5df541d5ef7032016e75b948e32ba33756433536 Mon Sep 17 00:00:00 2001
From: Harald Albers <github@albersweb.de>
Date: Sun, 26 Jan 2025 22:36:57 +0000
Subject: [PATCH 4/4] Resolve gofmt error

---
 completions.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/completions.go b/completions.go
index b404322f..390996d4 100644
--- a/completions.go
+++ b/completions.go
@@ -455,7 +455,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
 		}
 	} else {
 		directive = ShellCompDirectiveDefault
-		
+
 		customShellCompDirective := finalCmd.CompletionOptions.DefaultShellCompDirective
 		if customShellCompDirective != ShellCompDirectiveDefault {
 			directive = customShellCompDirective