1515 */
1616package picocli ;
1717
18+ import java .util .regex .Pattern ;
1819import org .hamcrest .CoreMatchers ;
1920import org .junit .Rule ;
2021import org .junit .Test ;
@@ -247,7 +248,8 @@ private static String toString(Object obj) {
247248
248249 private static final String AUTO_COMPLETE_APP_USAGE = String .format ("" +
249250 "Usage: picocli.AutoComplete [-fhVw] [-c=<factoryClass>] [-n=<commandName>]%n" +
250- " [-o=<autoCompleteScript>] [@<filename>...]%n" +
251+ " [-o=<autoCompleteScript>] [-p=<pathCompletionTypes>%n" +
252+ " [,<pathCompletionTypes>...]]... [@<filename>...]%n" +
251253 " <commandLineFQCN>%n" +
252254 "Generates a bash completion script for the specified command class.%n" +
253255 " [@<filename>...] One or more argument files containing options.%n" +
@@ -272,6 +274,10 @@ private static String toString(Object obj) {
272274 " the current directory.%n" +
273275 " -w, --writeCommandScript Write a '<commandName>' sample command script to%n" +
274276 " the same directory as the completion script.%n" +
277+ " -p, --pathCompletionTypes=<pathCompletionTypes>[,<pathCompletionTypes>...]%n" +
278+ " Comma-separated list of fully qualified custom%n" +
279+ " types for which to delegate to built-in path%n" +
280+ " name completion.%n" +
275281 " -f, --force Overwrite existing script files.%n" +
276282 " -h, --help Show this help message and exit.%n" +
277283 " -V, --version Print version information and exit.%n" +
@@ -761,7 +767,7 @@ private String expectedCompletionScriptForAutoCompleteApp() {
761767 "\n " +
762768 " local commands=\" \" \n " +
763769 " local flag_opts=\" -w --writeCommandScript -f --force -h --help -V --version\" \n " +
764- " local arg_opts=\" -c --factory -n --name -o --completionScript\" \n " +
770+ " local arg_opts=\" -c --factory -n --name -o --completionScript -p --pathCompletionTypes \" \n " +
765771 "\n " +
766772 " compopt +o default\n " +
767773 "\n " +
@@ -777,6 +783,9 @@ private String expectedCompletionScriptForAutoCompleteApp() {
777783 " COMPREPLY=( $( compgen -f -- \" ${curr_word}\" ) ) # files\n " +
778784 " return $?\n " +
779785 " ;;\n " +
786+ " -p|--pathCompletionTypes)\n " +
787+ " return\n " +
788+ " ;;\n " +
780789 " esac\n " +
781790 "\n " +
782791 " if [[ \" ${curr_word}\" == -* ]]; then\n " +
@@ -1822,5 +1831,111 @@ public void run() {
18221831 static class NestedLevel1 implements Runnable {
18231832 public void run () {
18241833 }
1834+
1835+ }
1836+
1837+ @ Test
1838+ public void testPathCompletionOnCustomTypes () throws IOException {
1839+ final String commandName = "bestCommandEver" ;
1840+ final File completionScript = new File (commandName + "_completion" );
1841+ if (completionScript .exists ()) {assertTrue (completionScript .delete ());}
1842+ completionScript .deleteOnExit ();
1843+
1844+ AutoComplete .main (String .format ("--name=%s" , commandName ),
1845+ String .format ("--pathCompletionTypes=%s,%s" ,
1846+ PathCompletionCommand .CustomPath1 .class .getName (),
1847+ PathCompletionCommand .CustomPath2 .class .getName ()),
1848+ "picocli.AutoCompleteTest$PathCompletionCommand" );
1849+
1850+ byte [] completion = readBytes (completionScript );
1851+ assertTrue (completionScript .delete ());
1852+
1853+ String expected = expectedCommandCompletion (commandName ,
1854+ "function _picocli_bestCommandEver() {\n " +
1855+ " # Get completion data\n " +
1856+ " local curr_word=${COMP_WORDS[COMP_CWORD]}\n " +
1857+ " local prev_word=${COMP_WORDS[COMP_CWORD-1]}\n " +
1858+ "\n " +
1859+ " local commands=\" \" \n " +
1860+ " local flag_opts=\" \" \n " +
1861+ " local arg_opts=\" --file --custom-path-1 --custom-path-2 --custom-type\" \n " +
1862+ "\n " +
1863+ " compopt +o default\n " +
1864+ "\n " +
1865+ " case ${prev_word} in\n " +
1866+ " --file)\n " +
1867+ " compopt -o filenames\n " +
1868+ " COMPREPLY=( $( compgen -f -- \" ${curr_word}\" ) ) # files\n " +
1869+ " return $?\n " +
1870+ " ;;\n " +
1871+ " --custom-path-1)\n " +
1872+ " compopt -o filenames\n " +
1873+ " COMPREPLY=( $( compgen -f -- \" ${curr_word}\" ) ) # files\n " +
1874+ " return $?\n " +
1875+ " ;;\n " +
1876+ " --custom-path-2)\n " +
1877+ " compopt -o filenames\n " +
1878+ " COMPREPLY=( $( compgen -f -- \" ${curr_word}\" ) ) # files\n " +
1879+ " return $?\n " +
1880+ " ;;\n " +
1881+ " --custom-type)\n " +
1882+ " return\n " +
1883+ " ;;\n " +
1884+ " esac\n " +
1885+ "\n " +
1886+ " if [[ \" ${curr_word}\" == -* ]]; then\n " +
1887+ " COMPREPLY=( $(compgen -W \" ${flag_opts} ${arg_opts}\" -- \" ${curr_word}\" ) )\n " +
1888+ " else\n " +
1889+ " local positionals=\" \" \n " +
1890+ " COMPREPLY=( $(compgen -W \" ${commands} ${positionals}\" -- \" ${curr_word}\" ) )\n " +
1891+ " fi\n " +
1892+ "}\n " );
1893+
1894+ assertEquals (expected , new String (completion , "UTF8" ));
1895+ }
1896+
1897+ private String expectedCommandCompletion (String commandName , String autoCompleteFunctionContent ) {
1898+ String expected = expectedCompletionScriptForAutoCompleteApp ()
1899+ .replaceAll ("picocli\\ .AutoComplete" , commandName );
1900+ expected = Pattern .compile ("function _picocli_" + commandName + "\\ (\\ ) \\ {\n "
1901+ + "(.+)\n "
1902+ + "}\n "
1903+ + "\n "
1904+ + "# Define a completion specification \\ (a compspec\\ ) for the" , Pattern .DOTALL )
1905+ .matcher (expected )
1906+ .replaceFirst (autoCompleteFunctionContent .replace ("$" , "\\ $" ) +
1907+ "\n # Define a completion specification (a compspec) for the" );
1908+ return expected ;
1909+ }
1910+
1911+ @ Command (name = "PathCompletion" )
1912+ static class PathCompletionCommand implements Runnable {
1913+
1914+ @ Option (names = "--file" )
1915+ private File file ;
1916+
1917+ @ Option (names = "--custom-path-1" )
1918+ private CustomPath1 customPath1 ;
1919+
1920+ @ Option (names = "--custom-path-2" )
1921+ private List <CustomPath2 > customPath2 ;
1922+
1923+ @ Option (names = "--custom-type" )
1924+ private CustomType customType ;
1925+
1926+ public void run () {
1927+ }
1928+
1929+ static class CustomPath1 {
1930+ String value ;
1931+ }
1932+
1933+ static class CustomPath2 {
1934+ String value ;
1935+ }
1936+
1937+ static class CustomType {
1938+ String value ;
1939+ }
18251940 }
18261941}
0 commit comments