mirror of
https://github.com/jlengrand/picocli.git
synced 2026-03-10 08:41:17 +00:00
1196 lines
84 KiB
HTML
1196 lines
84 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="generator" content="Asciidoctor 1.5.8">
|
||
<title>Programmatic API</title>
|
||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
|
||
<style>
|
||
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
|
||
/* Uncomment @import statement below to use as custom stylesheet */
|
||
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
|
||
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
|
||
audio,canvas,video{display:inline-block}
|
||
audio:not([controls]){display:none;height:0}
|
||
script{display:none!important}
|
||
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
|
||
a{background:transparent}
|
||
a:focus{outline:thin dotted}
|
||
a:active,a:hover{outline:0}
|
||
h1{font-size:2em;margin:.67em 0}
|
||
abbr[title]{border-bottom:1px dotted}
|
||
b,strong{font-weight:bold}
|
||
dfn{font-style:italic}
|
||
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
|
||
mark{background:#ff0;color:#000}
|
||
code,kbd,pre,samp{font-family:monospace;font-size:1em}
|
||
pre{white-space:pre-wrap}
|
||
q{quotes:"\201C" "\201D" "\2018" "\2019"}
|
||
small{font-size:80%}
|
||
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||
sup{top:-.5em}
|
||
sub{bottom:-.25em}
|
||
img{border:0}
|
||
svg:not(:root){overflow:hidden}
|
||
figure{margin:0}
|
||
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
|
||
legend{border:0;padding:0}
|
||
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
|
||
button,input{line-height:normal}
|
||
button,select{text-transform:none}
|
||
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
|
||
button[disabled],html input[disabled]{cursor:default}
|
||
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
|
||
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
||
textarea{overflow:auto;vertical-align:top}
|
||
table{border-collapse:collapse;border-spacing:0}
|
||
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
|
||
html,body{font-size:100%}
|
||
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
|
||
a:hover{cursor:pointer}
|
||
img,object,embed{max-width:100%;height:auto}
|
||
object,embed{height:100%}
|
||
img{-ms-interpolation-mode:bicubic}
|
||
.left{float:left!important}
|
||
.right{float:right!important}
|
||
.text-left{text-align:left!important}
|
||
.text-right{text-align:right!important}
|
||
.text-center{text-align:center!important}
|
||
.text-justify{text-align:justify!important}
|
||
.hide{display:none}
|
||
img,object,svg{display:inline-block;vertical-align:middle}
|
||
textarea{height:auto;min-height:50px}
|
||
select{width:100%}
|
||
.center{margin-left:auto;margin-right:auto}
|
||
.stretch{width:100%}
|
||
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
|
||
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
|
||
a{color:#2156a5;text-decoration:underline;line-height:inherit}
|
||
a:hover,a:focus{color:#1d4b8f}
|
||
a img{border:none}
|
||
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
|
||
p aside{font-size:.875em;line-height:1.35;font-style:italic}
|
||
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
|
||
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
|
||
h1{font-size:2.125em}
|
||
h2{font-size:1.6875em}
|
||
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
|
||
h4,h5{font-size:1.125em}
|
||
h6{font-size:1em}
|
||
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
|
||
em,i{font-style:italic;line-height:inherit}
|
||
strong,b{font-weight:bold;line-height:inherit}
|
||
small{font-size:60%;line-height:inherit}
|
||
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
|
||
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
|
||
ul,ol{margin-left:1.5em}
|
||
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
|
||
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
|
||
ul.square{list-style-type:square}
|
||
ul.circle{list-style-type:circle}
|
||
ul.disc{list-style-type:disc}
|
||
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
|
||
dl dt{margin-bottom:.3125em;font-weight:bold}
|
||
dl dd{margin-bottom:1.25em}
|
||
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
|
||
abbr{text-transform:none}
|
||
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
||
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
|
||
blockquote cite::before{content:"\2014 \0020"}
|
||
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
|
||
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
||
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
||
h1{font-size:2.75em}
|
||
h2{font-size:2.3125em}
|
||
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
|
||
h4{font-size:1.4375em}}
|
||
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
|
||
table thead,table tfoot{background:#f7f8f7}
|
||
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
||
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
|
||
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
|
||
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
|
||
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
|
||
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
|
||
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
|
||
.clearfix::after,.float-group::after{clear:both}
|
||
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
|
||
*:not(pre)>code.nobreak{word-wrap:normal}
|
||
*:not(pre)>code.nowrap{white-space:nowrap}
|
||
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
|
||
em em{font-style:normal}
|
||
strong strong{font-weight:400}
|
||
.keyseq{color:rgba(51,51,51,.8)}
|
||
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
||
.keyseq kbd:first-child{margin-left:0}
|
||
.keyseq kbd:last-child{margin-right:0}
|
||
.menuseq,.menuref{color:#000}
|
||
.menuseq b:not(.caret),.menuref{font-weight:inherit}
|
||
.menuseq{word-spacing:-.02em}
|
||
.menuseq b.caret{font-size:1.25em;line-height:.8}
|
||
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
|
||
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
|
||
b.button::before{content:"[";padding:0 3px 0 2px}
|
||
b.button::after{content:"]";padding:0 2px 0 3px}
|
||
p a>code:hover{color:rgba(0,0,0,.9)}
|
||
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
|
||
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
|
||
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
|
||
#content{margin-top:1.25em}
|
||
#content::before{content:none}
|
||
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
|
||
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
|
||
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
|
||
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
|
||
#header .details span:first-child{margin-left:-.125em}
|
||
#header .details span.email a{color:rgba(0,0,0,.85)}
|
||
#header .details br{display:none}
|
||
#header .details br+span::before{content:"\00a0\2013\00a0"}
|
||
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
|
||
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
|
||
#header #revnumber{text-transform:capitalize}
|
||
#header #revnumber::after{content:"\00a0"}
|
||
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
|
||
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
|
||
#toc>ul{margin-left:.125em}
|
||
#toc ul.sectlevel0>li>a{font-style:italic}
|
||
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
|
||
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
|
||
#toc li{line-height:1.3334;margin-top:.3334em}
|
||
#toc a{text-decoration:none}
|
||
#toc a:active{text-decoration:underline}
|
||
#toctitle{color:#7a2518;font-size:1.2em}
|
||
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
|
||
body.toc2{padding-left:15em;padding-right:0}
|
||
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
|
||
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
||
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
|
||
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
|
||
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
|
||
body.toc2.toc-right{padding-left:0;padding-right:15em}
|
||
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
|
||
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
|
||
#toc.toc2{width:20em}
|
||
#toc.toc2 #toctitle{font-size:1.375em}
|
||
#toc.toc2>ul{font-size:.95em}
|
||
#toc.toc2 ul ul{padding-left:1.25em}
|
||
body.toc2.toc-right{padding-left:0;padding-right:20em}}
|
||
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
|
||
#content #toc>:first-child{margin-top:0}
|
||
#content #toc>:last-child{margin-bottom:0}
|
||
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
|
||
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
|
||
#content{margin-bottom:.625em}
|
||
.sect1{padding-bottom:.625em}
|
||
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
|
||
.sect1{padding-bottom:1.25em}}
|
||
.sect1:last-child{padding-bottom:0}
|
||
.sect1+.sect1{border-top:1px solid #e7e7e9}
|
||
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
|
||
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
|
||
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
|
||
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
|
||
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
|
||
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
|
||
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
|
||
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
|
||
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
|
||
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
|
||
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
|
||
.admonitionblock>table td.icon{text-align:center;width:80px}
|
||
.admonitionblock>table td.icon img{max-width:none}
|
||
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
|
||
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)}
|
||
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
|
||
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
|
||
.exampleblock>.content>:first-child{margin-top:0}
|
||
.exampleblock>.content>:last-child{margin-bottom:0}
|
||
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
|
||
.sidebarblock>:first-child{margin-top:0}
|
||
.sidebarblock>:last-child{margin-bottom:0}
|
||
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
|
||
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
||
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
|
||
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
|
||
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em}
|
||
@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
|
||
@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
|
||
.literalblock pre.nowrap,.literalblock pre.nowrap pre,.listingblock pre.nowrap,.listingblock pre.nowrap pre{white-space:pre;word-wrap:normal}
|
||
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
|
||
.listingblock pre.highlightjs{padding:0}
|
||
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
|
||
.listingblock pre.prettyprint{border-width:0}
|
||
.listingblock>.content{position:relative}
|
||
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
|
||
.listingblock:hover code[data-lang]::before{display:block}
|
||
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
|
||
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
|
||
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
|
||
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
|
||
table.pyhltable td.code{padding-left:.75em;padding-right:0}
|
||
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #dddddf}
|
||
pre.pygments .lineno{display:inline-block;margin-right:.25em}
|
||
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
|
||
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
|
||
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
|
||
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
|
||
.quoteblock blockquote{margin:0;padding:0;border:0}
|
||
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
||
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
|
||
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
|
||
.verseblock{margin:0 1em 1.25em}
|
||
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
||
.verseblock pre strong{font-weight:400}
|
||
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
|
||
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
|
||
.quoteblock .attribution br,.verseblock .attribution br{display:none}
|
||
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
|
||
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
|
||
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
|
||
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
|
||
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
|
||
.quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
|
||
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
|
||
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
|
||
table.tableblock{max-width:100%;border-collapse:separate}
|
||
p.tableblock:last-child{margin-bottom:0}
|
||
td.tableblock>.content{margin-bottom:-1.25em}
|
||
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
|
||
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
|
||
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
|
||
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
|
||
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
|
||
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
|
||
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
|
||
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
|
||
table.frame-all{border-width:1px}
|
||
table.frame-sides{border-width:0 1px}
|
||
table.frame-topbot,table.frame-ends{border-width:1px 0}
|
||
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
|
||
table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
|
||
th.halign-left,td.halign-left{text-align:left}
|
||
th.halign-right,td.halign-right{text-align:right}
|
||
th.halign-center,td.halign-center{text-align:center}
|
||
th.valign-top,td.valign-top{vertical-align:top}
|
||
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
|
||
th.valign-middle,td.valign-middle{vertical-align:middle}
|
||
table thead th,table tfoot th{font-weight:bold}
|
||
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
|
||
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
|
||
p.tableblock>code:only-child{background:none;padding:0}
|
||
p.tableblock{font-size:1em}
|
||
td>div.verse{white-space:pre}
|
||
ol{margin-left:1.75em}
|
||
ul li ol{margin-left:1.5em}
|
||
dl dd{margin-left:1.125em}
|
||
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
|
||
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
|
||
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
|
||
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
|
||
ul.unstyled,ol.unstyled{margin-left:0}
|
||
ul.checklist{margin-left:.625em}
|
||
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
|
||
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
|
||
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
|
||
ul.inline>li{margin-left:1.25em}
|
||
.unstyled dl dt{font-weight:400;font-style:normal}
|
||
ol.arabic{list-style-type:decimal}
|
||
ol.decimal{list-style-type:decimal-leading-zero}
|
||
ol.loweralpha{list-style-type:lower-alpha}
|
||
ol.upperalpha{list-style-type:upper-alpha}
|
||
ol.lowerroman{list-style-type:lower-roman}
|
||
ol.upperroman{list-style-type:upper-roman}
|
||
ol.lowergreek{list-style-type:lower-greek}
|
||
.hdlist>table,.colist>table{border:0;background:none}
|
||
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
|
||
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
|
||
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
|
||
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
|
||
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
|
||
.colist td:not([class]):first-child img{max-width:none}
|
||
.colist td:not([class]):last-child{padding:.25em 0}
|
||
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
|
||
.imageblock.left{margin:.25em .625em 1.25em 0}
|
||
.imageblock.right{margin:.25em 0 1.25em .625em}
|
||
.imageblock>.title{margin-bottom:0}
|
||
.imageblock.thumb,.imageblock.th{border-width:6px}
|
||
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
|
||
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
|
||
.image.left{margin-right:.625em}
|
||
.image.right{margin-left:.625em}
|
||
a.image{text-decoration:none;display:inline-block}
|
||
a.image object{pointer-events:none}
|
||
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
|
||
sup.footnote a,sup.footnoteref a{text-decoration:none}
|
||
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
|
||
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
|
||
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
|
||
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
|
||
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
|
||
#footnotes .footnote:last-of-type{margin-bottom:0}
|
||
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
|
||
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
|
||
.gist .file-data>table td.line-data{width:99%}
|
||
div.unbreakable{page-break-inside:avoid}
|
||
.big{font-size:larger}
|
||
.small{font-size:smaller}
|
||
.underline{text-decoration:underline}
|
||
.overline{text-decoration:overline}
|
||
.line-through{text-decoration:line-through}
|
||
.aqua{color:#00bfbf}
|
||
.aqua-background{background-color:#00fafa}
|
||
.black{color:#000}
|
||
.black-background{background-color:#000}
|
||
.blue{color:#0000bf}
|
||
.blue-background{background-color:#0000fa}
|
||
.fuchsia{color:#bf00bf}
|
||
.fuchsia-background{background-color:#fa00fa}
|
||
.gray{color:#606060}
|
||
.gray-background{background-color:#7d7d7d}
|
||
.green{color:#006000}
|
||
.green-background{background-color:#007d00}
|
||
.lime{color:#00bf00}
|
||
.lime-background{background-color:#00fa00}
|
||
.maroon{color:#600000}
|
||
.maroon-background{background-color:#7d0000}
|
||
.navy{color:#000060}
|
||
.navy-background{background-color:#00007d}
|
||
.olive{color:#606000}
|
||
.olive-background{background-color:#7d7d00}
|
||
.purple{color:#600060}
|
||
.purple-background{background-color:#7d007d}
|
||
.red{color:#bf0000}
|
||
.red-background{background-color:#fa0000}
|
||
.silver{color:#909090}
|
||
.silver-background{background-color:#bcbcbc}
|
||
.teal{color:#006060}
|
||
.teal-background{background-color:#007d7d}
|
||
.white{color:#bfbfbf}
|
||
.white-background{background-color:#fafafa}
|
||
.yellow{color:#bfbf00}
|
||
.yellow-background{background-color:#fafa00}
|
||
span.icon>.fa{cursor:default}
|
||
a span.icon>.fa{cursor:inherit}
|
||
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
|
||
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
|
||
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
|
||
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
|
||
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
|
||
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
|
||
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
||
.conum[data-value] *{color:#fff!important}
|
||
.conum[data-value]+b{display:none}
|
||
.conum[data-value]::after{content:attr(data-value)}
|
||
pre .conum[data-value]{position:relative;top:-.125em}
|
||
b.conum *{color:inherit!important}
|
||
.conum:not([data-value]):empty{display:none}
|
||
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
|
||
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
|
||
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
|
||
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
|
||
p{margin-bottom:1.25rem}
|
||
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
|
||
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
|
||
.print-only{display:none!important}
|
||
@page{margin:1.25cm .75cm}
|
||
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
|
||
html{font-size:80%}
|
||
a{color:inherit!important;text-decoration:underline!important}
|
||
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
|
||
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
|
||
abbr[title]::after{content:" (" attr(title) ")"}
|
||
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
|
||
thead{display:table-header-group}
|
||
svg{max-width:100%}
|
||
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
|
||
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
|
||
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
|
||
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
|
||
body.book #header{text-align:center}
|
||
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
|
||
body.book #header .details{border:0!important;display:block;padding:0!important}
|
||
body.book #header .details span:first-child{margin-left:0!important}
|
||
body.book #header .details br{display:block}
|
||
body.book #header .details br+span::before{content:none!important}
|
||
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
|
||
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
|
||
.listingblock code[data-lang]::before{display:block}
|
||
#footer{padding:0 .9375em}
|
||
.hide-on-print{display:none!important}
|
||
.print-only{display:block!important}
|
||
.hide-for-print{display:none!important}
|
||
.show-for-print{display:inherit!important}}
|
||
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
|
||
.sect1{padding:0!important}
|
||
.sect1+.sect1{border:0}
|
||
#footer{background:none}
|
||
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
|
||
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
|
||
</style>
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||
<style>
|
||
/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
|
||
/*pre.CodeRay {background-color:#f7f7f8;}*/
|
||
.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
|
||
.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
|
||
.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
|
||
table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
|
||
table.CodeRay td{vertical-align: top;line-height:1.45}
|
||
table.CodeRay td.line-numbers{text-align:right}
|
||
table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
|
||
table.CodeRay td.code{padding:0 0 0 .5em}
|
||
table.CodeRay td.code>pre{padding:0}
|
||
.CodeRay .debug{color:#fff !important;background:#000080 !important}
|
||
.CodeRay .annotation{color:#007}
|
||
.CodeRay .attribute-name{color:#000080}
|
||
.CodeRay .attribute-value{color:#700}
|
||
.CodeRay .binary{color:#509}
|
||
.CodeRay .comment{color:#998;font-style:italic}
|
||
.CodeRay .char{color:#04d}
|
||
.CodeRay .char .content{color:#04d}
|
||
.CodeRay .char .delimiter{color:#039}
|
||
.CodeRay .class{color:#458;font-weight:bold}
|
||
.CodeRay .complex{color:#a08}
|
||
.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
|
||
.CodeRay .color{color:#099}
|
||
.CodeRay .class-variable{color:#369}
|
||
.CodeRay .decorator{color:#b0b}
|
||
.CodeRay .definition{color:#099}
|
||
.CodeRay .delimiter{color:#000}
|
||
.CodeRay .doc{color:#970}
|
||
.CodeRay .doctype{color:#34b}
|
||
.CodeRay .doc-string{color:#d42}
|
||
.CodeRay .escape{color:#666}
|
||
.CodeRay .entity{color:#800}
|
||
.CodeRay .error{color:#808}
|
||
.CodeRay .exception{color:inherit}
|
||
.CodeRay .filename{color:#099}
|
||
.CodeRay .function{color:#900;font-weight:bold}
|
||
.CodeRay .global-variable{color:#008080}
|
||
.CodeRay .hex{color:#058}
|
||
.CodeRay .integer,.CodeRay .float{color:#099}
|
||
.CodeRay .include{color:#555}
|
||
.CodeRay .inline{color:#000}
|
||
.CodeRay .inline .inline{background:#ccc}
|
||
.CodeRay .inline .inline .inline{background:#bbb}
|
||
.CodeRay .inline .inline-delimiter{color:#d14}
|
||
.CodeRay .inline-delimiter{color:#d14}
|
||
.CodeRay .important{color:#555;font-weight:bold}
|
||
.CodeRay .interpreted{color:#b2b}
|
||
.CodeRay .instance-variable{color:#008080}
|
||
.CodeRay .label{color:#970}
|
||
.CodeRay .local-variable{color:#963}
|
||
.CodeRay .octal{color:#40e}
|
||
.CodeRay .predefined{color:#369}
|
||
.CodeRay .preprocessor{color:#579}
|
||
.CodeRay .pseudo-class{color:#555}
|
||
.CodeRay .directive{font-weight:bold}
|
||
.CodeRay .type{font-weight:bold}
|
||
.CodeRay .predefined-type{color:inherit}
|
||
.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
|
||
.CodeRay .key{color:#808}
|
||
.CodeRay .key .delimiter{color:#606}
|
||
.CodeRay .key .char{color:#80f}
|
||
.CodeRay .value{color:#088}
|
||
.CodeRay .regexp .delimiter{color:#808}
|
||
.CodeRay .regexp .content{color:#808}
|
||
.CodeRay .regexp .modifier{color:#808}
|
||
.CodeRay .regexp .char{color:#d14}
|
||
.CodeRay .regexp .function{color:#404;font-weight:bold}
|
||
.CodeRay .string{color:#d20}
|
||
.CodeRay .string .string .string{background:#ffd0d0}
|
||
.CodeRay .string .content{color:#d14}
|
||
.CodeRay .string .char{color:#d14}
|
||
.CodeRay .string .delimiter{color:#d14}
|
||
.CodeRay .shell{color:#d14}
|
||
.CodeRay .shell .delimiter{color:#d14}
|
||
.CodeRay .symbol{color:#990073}
|
||
.CodeRay .symbol .content{color:#a60}
|
||
.CodeRay .symbol .delimiter{color:#630}
|
||
.CodeRay .tag{color:#008080}
|
||
.CodeRay .tag-special{color:#d70}
|
||
.CodeRay .variable{color:#036}
|
||
.CodeRay .insert{background:#afa}
|
||
.CodeRay .delete{background:#faa}
|
||
.CodeRay .change{color:#aaf;background:#007}
|
||
.CodeRay .head{color:#f8f;background:#505}
|
||
.CodeRay .insert .insert{color:#080}
|
||
.CodeRay .delete .delete{color:#800}
|
||
.CodeRay .change .change{color:#66f}
|
||
.CodeRay .head .head{color:#f4f}
|
||
</style>
|
||
</head>
|
||
<body class="article toc2 toc-left">
|
||
<div id="header">
|
||
<h1>Programmatic API</h1>
|
||
<div class="details">
|
||
<span id="revnumber">version 4.1.4,</span>
|
||
<span id="revdate">2019-11-29</span>
|
||
</div>
|
||
<div id="toc" class="toc2">
|
||
<div id="toctitle">Table of Contents</div>
|
||
<ul class="sectlevel1">
|
||
<li><a href="#_introduction">1. Introduction</a></li>
|
||
<li><a href="#_example">2. Example</a></li>
|
||
<li><a href="#_configuration">3. Configuration</a>
|
||
<ul class="sectlevel2">
|
||
<li><a href="#_commandspec">3.1. <code>CommandSpec</code></a></li>
|
||
<li><a href="#_optionspec">3.2. <code>OptionSpec</code></a></li>
|
||
<li><a href="#_positionalparamspec">3.3. <code>PositionalParamSpec</code></a></li>
|
||
<li><a href="#_bindings">3.4. Bindings</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#_parse_result">4. Parse Result</a>
|
||
<ul class="sectlevel2">
|
||
<li><a href="#_querying_for_options">4.1. Querying for Options</a></li>
|
||
<li><a href="#_matched_option_values">4.2. Matched Option Values</a></li>
|
||
<li><a href="#_original_option_values">4.3. Original Option Values</a></li>
|
||
<li><a href="#_subcommands_2">4.4. Subcommands</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a href="#_parsing_and_result_processing">5. Parsing and Result Processing</a>
|
||
<ul class="sectlevel2">
|
||
<li><a href="#_basic_processing">5.1. Basic Processing</a></li>
|
||
<li><a href="#Execute">5.2. <code>Execute</code> Framework </a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div id="content">
|
||
<div id="preamble">
|
||
<div class="sectionbody">
|
||
<div class="admonitionblock tip">
|
||
<table>
|
||
<tr>
|
||
<td class="icon">
|
||
<i class="fa icon-tip" title="Tip"></i>
|
||
</td>
|
||
<td class="content">
|
||
For most applications the annotations API is a better fit than the programmatic API: the annotation syntax is more compact, easier to read, and easier to maintain. See this <a href="https://picocli.info/quick-guide.html">quick guide</a> and for more details, the <a href="http://picocli.info">user manual</a>.
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
<div class="admonitionblock tip">
|
||
<table>
|
||
<tr>
|
||
<td class="icon">
|
||
<i class="fa icon-tip" title="Tip"></i>
|
||
</td>
|
||
<td class="content">
|
||
This document covers the programmatic API for picocli 4.0 and higher. For older versions, check <a href="https://picocli.info/man/3.x/picocli-3.0-programmatic-api.html">picocli-3.0-programmatic-api.html</a>.
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_introduction">1. Introduction</h2>
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>Picocli offers a programmatic API for creating command line applications, in addition to annotations. The programmatic API allows applications to dynamically create command line options on the fly, and also makes it possible to create idiomatic domain-specific languages for processing command line arguments, using picocli, in other JVM languages.</p>
|
||
</div>
|
||
<div class="admonitionblock caution">
|
||
<table>
|
||
<tr>
|
||
<td class="icon">
|
||
<i class="fa icon-caution" title="Caution"></i>
|
||
</td>
|
||
<td class="content">
|
||
This document does not cover all of picocli’s features. If you find yourself wondering "Can picocli do X?", please refer to the <a href="http://picocli.info">user manual</a>. The examples in the user manual use the annotations API, but <strong>everything that can be done with the annotations API can also be done via the programmatic API</strong>.
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>To create an application using the programmatic API,
|
||
use the <code>CommandSpec</code>, <code>OptionSpec</code> and <code>PositionalParamSpec</code> classes to define one or more commands and their options and positional parameters.
|
||
Then, create a <code>CommandLine</code> instance with the top-level command’s <code>CommandSpec</code>,
|
||
and use this object to parse the command line arguments and process the results.
|
||
The rest of this document goes into more detail.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Picocli can be used as a library or as a framework.
|
||
When used as a framework, the application needs to
|
||
designate a method that will be called when the user input was valid, and call the <code>CommandLine.execute</code> method.
|
||
When used as a library, the application calls the <code>CommandLine.parseArgs</code> method to obtain a <code>ParseResult</code> object, and is then responsible for handling the result. See the <a href="#_parsing_and_result_processing">Parsing and Result Processing</a> section for details. The example below uses the (more compact) <code>execute</code> method.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_example">2. Example</h2>
|
||
<div class="sectionbody">
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">ProgrammaticCommand</span> {
|
||
|
||
<span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span><span class="type">[]</span> args) {
|
||
CommandSpec spec = CommandSpec.create();
|
||
spec.mixinStandardHelpOptions(<span class="predefined-constant">true</span>); <span class="comment">// usageHelp and versionHelp options</span>
|
||
spec.addOption(OptionSpec.builder(<span class="string"><span class="delimiter">"</span><span class="content">-c</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--count</span><span class="delimiter">"</span></span>)
|
||
.paramLabel(<span class="string"><span class="delimiter">"</span><span class="content">COUNT</span><span class="delimiter">"</span></span>)
|
||
.type(<span class="type">int</span>.class)
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">number of times to execute</span><span class="delimiter">"</span></span>).build());
|
||
spec.addPositional(PositionalParamSpec.builder()
|
||
.paramLabel(<span class="string"><span class="delimiter">"</span><span class="content">FILES</span><span class="delimiter">"</span></span>)
|
||
.type(<span class="predefined-type">List</span>.class).auxiliaryTypes(<span class="predefined-type">File</span>.class) <span class="comment">// List<File></span>
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">The files to process</span><span class="delimiter">"</span></span>).build());
|
||
CommandLine commandLine = <span class="keyword">new</span> CommandLine(spec);
|
||
|
||
<span class="comment">// set an execution strategy (the run(ParseResult) method) that will be called</span>
|
||
<span class="comment">// by CommandLine.execute(args) when user input was valid</span>
|
||
commandLine.setExecutionStrategy(ProgrammaticCommand::run);
|
||
<span class="type">int</span> exitCode = commandLine.execute(args);
|
||
<span class="predefined-type">System</span>.exit(exitCode);
|
||
}
|
||
|
||
<span class="directive">static</span> <span class="type">int</span> run(ParseResult pr) {
|
||
<span class="comment">// handle requests for help or version information</span>
|
||
<span class="predefined-type">Integer</span> helpExitCode = CommandLine.executeHelpRequest(pr);
|
||
<span class="keyword">if</span> (helpExitCode != <span class="predefined-constant">null</span>) { <span class="keyword">return</span> helpExitCode; }
|
||
|
||
<span class="comment">// implement the business logic</span>
|
||
<span class="type">int</span> count = pr.matchedOptionValue(<span class="string"><span class="delimiter">'</span><span class="content">c</span><span class="delimiter">'</span></span>, <span class="integer">1</span>);
|
||
<span class="predefined-type">List</span><<span class="predefined-type">File</span>> files = pr.matchedPositionalValue(<span class="integer">0</span>, <span class="predefined-type">Collections</span>.<<span class="predefined-type">File</span>>emptyList());
|
||
<span class="keyword">for</span> (<span class="predefined-type">File</span> f : files) {
|
||
<span class="keyword">for</span> (<span class="type">int</span> i = <span class="integer">0</span>; i < count; i++) {
|
||
<span class="predefined-type">System</span>.out.println(i + <span class="string"><span class="delimiter">"</span><span class="content"> </span><span class="delimiter">"</span></span> + f.getName());
|
||
}
|
||
}
|
||
<span class="keyword">return</span> files.size();
|
||
}
|
||
}</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_configuration">3. Configuration</h2>
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>The following classes are the main model classes used to configure the parser:</p>
|
||
</div>
|
||
<div class="ulist">
|
||
<ul>
|
||
<li>
|
||
<p><code>CommandSpec</code></p>
|
||
</li>
|
||
<li>
|
||
<p><code>OptionSpec</code></p>
|
||
</li>
|
||
<li>
|
||
<p><code>PositionalParamSpec</code></p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="_commandspec">3.1. <code>CommandSpec</code></h3>
|
||
<div class="sect3">
|
||
<h4 id="_command_name_and_version">3.1.1. Command Name and Version</h4>
|
||
<div class="paragraph">
|
||
<p><code>CommandSpec</code> models a command. It has a name and a version, both of which may be empty. For example:</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">CommandSpec cmd = CommandSpec.create()
|
||
.name(<span class="string"><span class="delimiter">"</span><span class="content">mycommand</span><span class="delimiter">"</span></span>)
|
||
.version(<span class="string"><span class="delimiter">"</span><span class="content">My Command v1.0</span><span class="delimiter">"</span></span>);</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>It also has a <code>UsageMessageSpec</code> to configure aspects of the usage help message.</p>
|
||
</div>
|
||
</div>
|
||
<div class="sect3">
|
||
<h4 id="_usage_help">3.1.2. Usage Help</h4>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">cmd.usageMessage()
|
||
.headerHeading(<span class="string"><span class="delimiter">"</span><span class="content">Header heading%n</span><span class="delimiter">"</span></span>)
|
||
.header(<span class="string"><span class="delimiter">"</span><span class="content">header line 1</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">header line 2</span><span class="delimiter">"</span></span>)
|
||
.descriptionHeading(<span class="string"><span class="delimiter">"</span><span class="content">Description heading%n</span><span class="delimiter">"</span></span>)
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">description line 1</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">description line 2</span><span class="delimiter">"</span></span>)
|
||
.optionListHeading(<span class="string"><span class="delimiter">"</span><span class="content">Options%n</span><span class="delimiter">"</span></span>)
|
||
.parameterListHeading(<span class="string"><span class="delimiter">"</span><span class="content">Positional Parameters%n</span><span class="delimiter">"</span></span>);
|
||
.footerHeading(<span class="string"><span class="delimiter">"</span><span class="content">Footer heading%n</span><span class="delimiter">"</span></span>)
|
||
.footer(<span class="string"><span class="delimiter">"</span><span class="content">footer line 1</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">footer line 2</span><span class="delimiter">"</span></span>);</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>The <code>ParserSpec</code> can be used to control the behaviour of the parser to some extent.</p>
|
||
</div>
|
||
</div>
|
||
<div class="sect3">
|
||
<h4 id="_parser_options">3.1.3. Parser Options</h4>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">cmd.parser()
|
||
.unmatchedArgumentsAllowed(<span class="predefined-constant">true</span>)
|
||
.overwrittenOptionsAllowed(<span class="predefined-constant">true</span>);</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect3">
|
||
<h4 id="_reusing_options_with_mixins">3.1.4. Reusing Options with Mixins</h4>
|
||
<div class="paragraph">
|
||
<p><code>CommandSpec</code> has methods to add options (<code>OptionSpec</code> objects) and positional parameters (<code>PositionalParamSpec</code> objects). A <code>CommandSpec</code> can be mixed in with another <code>CommandSpec</code>, so its options, positional parameters and usage help attributes are merged into the other <code>CommandSpec</code>.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>This allows application to define some common options in one class and reuse them in many other commands. For example:</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">CommandSpec standardHelpOptions = CommandSpec.create()
|
||
.addOption(OptionSpec.builder(<span class="string"><span class="delimiter">"</span><span class="content">-h</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--help</span><span class="delimiter">"</span></span>)
|
||
.usageHelp(<span class="predefined-constant">true</span>)
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">Show this help message and exit.</span><span class="delimiter">"</span></span>).build())
|
||
.addOption(OptionSpec.builder(<span class="string"><span class="delimiter">"</span><span class="content">-V</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--version</span><span class="delimiter">"</span></span>)
|
||
.versionHelp(<span class="predefined-constant">true</span>)
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">Print version information and exit.</span><span class="delimiter">"</span></span>).build());
|
||
|
||
CommandSpec cmd = CommandSpec.create()
|
||
.name(<span class="string"><span class="delimiter">"</span><span class="content">mycommand</span><span class="delimiter">"</span></span>)
|
||
.addMixin(<span class="string"><span class="delimiter">"</span><span class="content">standardHelpOptions</span><span class="delimiter">"</span></span>, standardHelpOptions);</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Actually, since these options are extremely common, <code>CommandSpec</code> provides a convenience method to quickly add these standard help options:</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">CommandSpec spec = CommandSpec.create();
|
||
spec.mixinStandardHelpOptions(<span class="predefined-constant">true</span>); <span class="comment">// usageHelp and versionHelp options</span></code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect3">
|
||
<h4 id="_subcommands">3.1.5. Subcommands</h4>
|
||
<div class="paragraph">
|
||
<p>It is common for complex applications to break up functionality into "verbs" or "subcommands".
|
||
For example, the <code>git</code> application has many subcommands like <code>commit</code>, <code>push</code>, <code>status</code>, etc.
|
||
Picocli makes it easy to build applications with subcommands (and sub-subcommands).</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p><code>CommandSpec</code> objects can be subcommands of other <code>CommandSpecs</code>. There is no limit to the depth of a hierarchy of command and subcommands.</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">CommandSpec helpSubcommand = CommandSpec.forAnnotatedObject(
|
||
<span class="keyword">new</span> picocli.CommandLine.HelpCommand());
|
||
|
||
CommandSpec cmd = CommandSpec.create()
|
||
.name(<span class="string"><span class="delimiter">"</span><span class="content">mycommand</span><span class="delimiter">"</span></span>)
|
||
.addSubcommand(<span class="string"><span class="delimiter">"</span><span class="content">help</span><span class="delimiter">"</span></span>, helpSubcommand);</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="_optionspec">3.2. <code>OptionSpec</code></h3>
|
||
<div class="paragraph">
|
||
<p><code>OptionSpec</code> models a command option. An <code>OptionSpec</code> must have at least one name, which is used during parsing to match command line arguments. Other attributes can be left empty and picocli will give them a reasonable default value. This defaulting is why <code>OptionSpec</code> objects are created with a builder: this allows you to specify only some attributes and let picocli initialise the other attributes. For example, if only the option’s name is specified, picocli assumes the option takes no parameters (arity = 0), and is of type <code>boolean</code>. Another example, if arity is larger than <code>1</code>, picocli sets the type to <code>List</code> and the <code>auxiliary type</code> to <code>String</code>.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Once an <code>OptionSpec</code> is constructed, its configuration becomes immutable, but its <code>value</code> can still be modified. Usually the value is set during command line parsing when a command line argument matches one of the option names.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>The value is set via the getter and setter <em>bindings</em>. We’ll come back to bindings later in this document.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Similar to the annotation API, <code>OptionSpec</code> objects have <code>help</code>, <code>usageHelp</code> and <code>versionHelp</code> attributes. When the parser matches an option that was marked with any of these attributes, it will no longer validate that all required arguments exist. See the section below on the <code>parseWithHandler(s)</code> methods that automatically print help when requested.</p>
|
||
</div>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="_positionalparamspec">3.3. <code>PositionalParamSpec</code></h3>
|
||
<div class="paragraph">
|
||
<p><code>PositionalParamSpec</code> objects don’t have names, but have an index range instead. A single <code>PositionalParamSpec</code> object can capture multiple positional parameters. The default index range is set to <code>0..*</code> (all indices). A command may have multiple <code>PositionalParamSpec</code> objects to capture positional parameters at different index ranges. This can be useful if positional parameters at different index ranges have different data types.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Similar to <code>OptionSpec</code> objects, Once a <code>PositionalParamSpec</code> is constructed, its configuration becomes immutable, but its <code>value</code> can still be modified. Usually the value is set during command line parsing when a non-option command line argument is encountered at a position in its index range.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>The value is set via getter and setter <em>bindings</em>. We’ll look at bindings next.</p>
|
||
</div>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="_bindings">3.4. Bindings</h3>
|
||
<div class="sect3">
|
||
<h4 id="_bindings_overview">3.4.1. Bindings Overview</h4>
|
||
<div class="paragraph">
|
||
<p>When an option or positional parameter is matched on the command line,
|
||
the parser will create a <a href="https://picocli.info/#_strongly_typed_everything">strongly typed</a> value for the text value
|
||
that was matched on the command line. Picocli stores this value in the <code>ArgSpec</code> by using its <code>IGetter</code> or <code>ISetter</code>.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Most applications don’t need to know the details of getter and setter bindings, and can just call
|
||
<a href="https://picocli.info/apidocs/picocli/CommandLine.Model.ArgSpec.html#getValue--">getValue</a> or
|
||
<a href="https://picocli.info/apidocs/picocli/CommandLine.Model.ArgSpec.html#setValue-T-">setValue</a>.
|
||
The below may be of interest for applications or libraries that use picocli to design a domain-specific language, or implement some other dynamic behaviour.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Picocli internally uses bindings to allow <code>@Option</code> and <code>@Parameters</code>-annotated fields and setter methods on implementation classes, and annotated getter methods on interfaces.</p>
|
||
</div>
|
||
</div>
|
||
<div class="sect3">
|
||
<h4 id="_bindings_details">3.4.2. Bindings Details</h4>
|
||
<div class="paragraph">
|
||
<p>Bindings decouple the option and positional parameter specification from the place where their value is held.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Option specifications and positional parameter specifications created from annotated fields have a <code>FieldBinding</code>, and annotated methods have a <code>MethodBinding</code>, so when the value is set on an option specification, the field’s value is set (or the setter method is invoked).</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Option specifications and positional parameter specifications created programmatically without annotated object by default have an <code>ObjectBinding</code> that simply stores the value in a field of the <code>ObjectBinding</code>.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>You may create a custom binding that delegates to some other data structure to retrieve and store the value.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>A binding is either a getter or a setter:</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="directive">static</span> <span class="type">interface</span> <span class="class">IGetter</span> {
|
||
<span class="comment">/** Returns the current value of the binding. For multi-value options and positional
|
||
* parameters, this method returns an array, collection or map to add values to.
|
||
* @throws PicocliException if a problem occurred while obtaining the current value
|
||
* @throws Exception internally, picocli call sites will catch any exceptions
|
||
* thrown from here and rethrow them wrapped in a PicocliException */</span>
|
||
<T> T get() <span class="directive">throws</span> <span class="exception">Exception</span>;
|
||
}</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="directive">static</span> <span class="type">interface</span> <span class="class">ISetter</span> {
|
||
<span class="comment">/** Sets the new value of the option or positional parameter.
|
||
*
|
||
* @param value the new value of the option or positional parameter
|
||
* @param <T> type of the value
|
||
* @return the previous value of the binding (if supported by this binding)
|
||
* @throws PicocliException if a problem occurred while setting the new value
|
||
* @throws Exception internally, picocli call sites will catch any exceptions
|
||
* thrown from here and rethrow them wrapped in a PicocliException */</span>
|
||
<T> T set(T value) <span class="directive">throws</span> <span class="exception">Exception</span>;
|
||
}</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>For single-value options, picocli will simply invoke the setter when an option or positional parameter is matched on the command line.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>For multi-value options or positional parameters, picocli will call the getter to get the current value, add the newly matched value, and call the setter with the result.
|
||
For arrays, this means the existing elements are copied into a new array that is one element larger, and this new array is then set.
|
||
For collections and maps, the new value is added to the collection returned by the getter.
|
||
If the getter returns <code>null</code>, a new array, collection, or map is created.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_parse_result">4. Parse Result</h2>
|
||
<div class="sectionbody">
|
||
<div class="paragraph">
|
||
<p>For the below examples, we use the following parser configuration:</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">CommandSpec spec = CommandSpec.create();
|
||
spec.addOption(OptionSpec.builder(<span class="string"><span class="delimiter">"</span><span class="content">-V</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--verbose</span><span class="delimiter">"</span></span>).build());
|
||
spec.addOption(OptionSpec.builder(<span class="string"><span class="delimiter">"</span><span class="content">-f</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--file</span><span class="delimiter">"</span></span>)
|
||
.paramLabel(<span class="string"><span class="delimiter">"</span><span class="content">FILES</span><span class="delimiter">"</span></span>)
|
||
.type(<span class="predefined-type">List</span>.class)
|
||
.auxiliaryTypes(<span class="predefined-type">File</span>.class) <span class="comment">// this option is of type List<File></span>
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">The files to process</span><span class="delimiter">"</span></span>).build());
|
||
spec.addOption(OptionSpec.builder(<span class="string"><span class="delimiter">"</span><span class="content">-n</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--num</span><span class="delimiter">"</span></span>)
|
||
.paramLabel(<span class="string"><span class="delimiter">"</span><span class="content">COUNT</span><span class="delimiter">"</span></span>)
|
||
.type(<span class="type">int</span><span class="type">[]</span>.class)
|
||
.splitRegex(<span class="string"><span class="delimiter">"</span><span class="content">,</span><span class="delimiter">"</span></span>)
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">Comma-separated list of integers</span><span class="delimiter">"</span></span>).build());
|
||
CommandLine commandLine = <span class="keyword">new</span> CommandLine(spec);</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="_querying_for_options">4.1. Querying for Options</h3>
|
||
<div class="paragraph">
|
||
<p>The <code>CommandLine::parseArgs</code> method returns a <code>ParseResult</code> object that allows client code to query which options and positional parameters were matched for a given command.</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java"><span class="predefined-type">String</span><span class="type">[]</span> args = { <span class="string"><span class="delimiter">"</span><span class="content">--verbose</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">-f</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">file1</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--file=file2</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">-n1,2,3</span><span class="delimiter">"</span></span> };
|
||
ParseResult pr = commandLine.parseArgs(args);
|
||
|
||
<span class="predefined-type">List</span><<span class="predefined-type">String</span>> originalArgs = pr.originalArgs(); <span class="comment">// lists all command line args</span>
|
||
<span class="keyword">assert</span> <span class="predefined-type">Arrays</span>.asList(args).equals(originalArgs);
|
||
|
||
<span class="keyword">assert</span> pr.hasMatchedOption(<span class="string"><span class="delimiter">"</span><span class="content">--verbose</span><span class="delimiter">"</span></span>); <span class="comment">// as specified on command line</span>
|
||
<span class="keyword">assert</span> pr.hasMatchedOption(<span class="string"><span class="delimiter">"</span><span class="content">-V</span><span class="delimiter">"</span></span>); <span class="comment">// other aliases work also</span>
|
||
<span class="keyword">assert</span> pr.hasMatchedOption(<span class="string"><span class="delimiter">'</span><span class="content">V</span><span class="delimiter">'</span></span>); <span class="comment">// single-character alias works too</span>
|
||
<span class="keyword">assert</span> pr.hasMatchedOption(<span class="string"><span class="delimiter">"</span><span class="content">verbose</span><span class="delimiter">"</span></span>); <span class="comment">// and, command name without hyphens</span></code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="_matched_option_values">4.2. Matched Option Values</h3>
|
||
<div class="paragraph">
|
||
<p>The <code>matchedOptionValue</code> method returns the command line value or values, converted to the option’s type. This method requires a default value, which will be returned in case the option was not matched on the command line. In the above example, we defined the <code>--file</code> option to be of type <code>List<File></code>, so we pass in an empty list as the default value:</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">ParseResult pr = commandLine.parseArgs(<span class="string"><span class="delimiter">"</span><span class="content">-f</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">file1</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--file=file2</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">-n1,2,3</span><span class="delimiter">"</span></span>);
|
||
|
||
<span class="predefined-type">List</span><<span class="predefined-type">File</span>> defaultValue = <span class="predefined-type">Collections</span>.emptyList();
|
||
<span class="predefined-type">List</span><<span class="predefined-type">File</span>> expected = <span class="predefined-type">Arrays</span>.asList(<span class="keyword">new</span> <span class="predefined-type">File</span>(<span class="string"><span class="delimiter">"</span><span class="content">file1</span><span class="delimiter">"</span></span>), <span class="keyword">new</span> <span class="predefined-type">File</span>(<span class="string"><span class="delimiter">"</span><span class="content">file2</span><span class="delimiter">"</span></span>));
|
||
|
||
<span class="keyword">assert</span> expected.equals(pr.matchedOptionValue(<span class="string"><span class="delimiter">'</span><span class="content">f</span><span class="delimiter">'</span></span>, defaultValue));
|
||
<span class="keyword">assert</span> expected.equals(pr.matchedOptionValue(<span class="string"><span class="delimiter">"</span><span class="content">--file</span><span class="delimiter">"</span></span>, defaultValue));
|
||
|
||
<span class="keyword">assert</span> <span class="predefined-type">Arrays</span>.equals(<span class="keyword">new</span> <span class="type">int</span><span class="type">[]</span>{<span class="integer">1</span>,<span class="integer">2</span>,<span class="integer">3</span>}, pr.matchedOptionValue(<span class="string"><span class="delimiter">'</span><span class="content">n</span><span class="delimiter">'</span></span>, <span class="keyword">new</span> <span class="type">int</span>[<span class="integer">0</span>]));</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="_original_option_values">4.3. Original Option Values</h3>
|
||
<div class="paragraph">
|
||
<p>Use the <code>OptionSpec.stringValues()</code> or <code>OptionSpec.originalStringValues()</code> method to get a list of all values specified on the command line for an option.
|
||
The <code>stringValues()</code> method returns the arguments after splitting but before type conversion, while
|
||
the <code>originalStringValues()</code> method returns the matched arguments as specified on the command line (before splitting).</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java">ParseResult pr = commandLine.parseArgs(<span class="string"><span class="delimiter">"</span><span class="content">-f</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">file1</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--file=file2</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">-n1,2,3</span><span class="delimiter">"</span></span>);
|
||
|
||
<span class="comment">// Command line arguments after splitting but before type conversion</span>
|
||
<span class="keyword">assert</span> <span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>.equals(pr.matchedOption(<span class="string"><span class="delimiter">'</span><span class="content">n</span><span class="delimiter">'</span></span>).stringValues().get(<span class="integer">0</span>));
|
||
<span class="keyword">assert</span> <span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>.equals(pr.matchedOption(<span class="string"><span class="delimiter">'</span><span class="content">n</span><span class="delimiter">'</span></span>).stringValues().get(<span class="integer">1</span>));
|
||
<span class="keyword">assert</span> <span class="string"><span class="delimiter">"</span><span class="content">3</span><span class="delimiter">"</span></span>.equals(pr.matchedOption(<span class="string"><span class="delimiter">'</span><span class="content">n</span><span class="delimiter">'</span></span>).stringValues().get(<span class="integer">2</span>));
|
||
|
||
<span class="comment">// Command line arguments as found on the command line</span>
|
||
<span class="keyword">assert</span> <span class="string"><span class="delimiter">"</span><span class="content">1,2,3</span><span class="delimiter">"</span></span>.equals(pr.matchedOption(<span class="string"><span class="delimiter">"</span><span class="content">--num</span><span class="delimiter">"</span></span>).originalStringValues().get(<span class="integer">0</span>));</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="_subcommands_2">4.4. Subcommands</h3>
|
||
<div class="paragraph">
|
||
<p>Use the <code>hasSubcommand</code> method to determine whether the command line contained subcommands. The <code>subcommand</code> method returns a different <code>ParseResult</code> object that can be used to query which options and positional parameters were matched for the subcommand.</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java"><span class="type">class</span> <span class="class">App</span> {
|
||
<span class="annotation">@Option</span>(names = <span class="string"><span class="delimiter">"</span><span class="content">-x</span><span class="delimiter">"</span></span>) <span class="predefined-type">String</span> x;
|
||
}
|
||
<span class="type">class</span> <span class="class">Sub</span> {
|
||
<span class="annotation">@Parameters</span> <span class="predefined-type">String</span><span class="type">[]</span> all;
|
||
}
|
||
CommandLine cmd = <span class="keyword">new</span> CommandLine(<span class="keyword">new</span> App());
|
||
cmd.addSubcommand(<span class="string"><span class="delimiter">"</span><span class="content">sub</span><span class="delimiter">"</span></span>, <span class="keyword">new</span> Sub());
|
||
ParseResult parseResult = cmd.parseArgs(<span class="string"><span class="delimiter">"</span><span class="content">-x</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">xval</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">sub</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">1</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">2</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">3</span><span class="delimiter">"</span></span>);
|
||
|
||
<span class="keyword">assert</span> parseResult.hasMatchedOption(<span class="string"><span class="delimiter">"</span><span class="content">-x</span><span class="delimiter">"</span></span>);
|
||
<span class="keyword">assert</span> <span class="string"><span class="delimiter">"</span><span class="content">xval</span><span class="delimiter">"</span></span>.equals(parseResult.matchedOptionValue(<span class="string"><span class="delimiter">"</span><span class="content">-x</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">default</span><span class="delimiter">"</span></span>));
|
||
|
||
<span class="keyword">assert</span> parseResult.hasSubcommand();
|
||
ParseResult subResult = parseResult.subcommand();
|
||
|
||
<span class="keyword">assert</span> subResult.hasMatchedPositional(<span class="integer">0</span>);
|
||
<span class="keyword">assert</span> subResult.hasMatchedPositional(<span class="integer">1</span>);
|
||
<span class="keyword">assert</span> subResult.hasMatchedPositional(<span class="integer">2</span>);
|
||
<span class="keyword">assert</span> !subResult.hasMatchedPositional(<span class="integer">3</span>);</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect1">
|
||
<h2 id="_parsing_and_result_processing">5. Parsing and Result Processing</h2>
|
||
<div class="sectionbody">
|
||
<div class="sect2">
|
||
<h3 id="_basic_processing">5.1. Basic Processing</h3>
|
||
<div class="paragraph">
|
||
<p>The most basic way to parse the command line is to call the <code>CommandLine::parseArgs</code> method and inspect the resulting <code>ParseResult</code> object.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>The <code>parseArgs</code> method allows applications to use picocli <em>as a library</em>. See the <a href="#Execute">Execute Framework</a> section below on how to use picocli <em>as a framework</em>.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>Using picocli as a library via the <code>parseArgs</code> method is straightforward and leaves the application in control, but doing this correctly means that the application need to take care of many things:</p>
|
||
</div>
|
||
<div class="ulist">
|
||
<ul>
|
||
<li>
|
||
<p>check if usage help or version help was requested</p>
|
||
</li>
|
||
<li>
|
||
<p>handle invalid user input</p>
|
||
</li>
|
||
<li>
|
||
<p>if user input was valid, invoke the business logic</p>
|
||
</li>
|
||
<li>
|
||
<p>handle runtime errors in the business logic</p>
|
||
</li>
|
||
<li>
|
||
<p>optionally return an exit code for all of the above</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>An application that handles all of these cases could look something like this:</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span>... args) {
|
||
<span class="type">int</span> exitCode = myParse(args);
|
||
<span class="predefined-type">System</span>.exit(exitCode);
|
||
}
|
||
|
||
<span class="type">int</span> myParse(<span class="predefined-type">String</span>... args) {
|
||
CommandSpec spec = CommandSpec.create();
|
||
<span class="comment">// add options and positional parameters</span>
|
||
|
||
CommandLine cmd = <span class="keyword">new</span> CommandLine(spec);
|
||
<span class="keyword">try</span> {
|
||
ParseResult parseResult = cmd.parseArgs(args);
|
||
|
||
<span class="comment">// Did user request usage help (--help)?</span>
|
||
<span class="keyword">if</span> (cmd.isUsageHelpRequested()) {
|
||
cmd.usage(cmd.getOut());
|
||
<span class="keyword">return</span> cmd.getCommandSpec().exitCodeOnUsageHelp();
|
||
|
||
<span class="comment">// Did user request version help (--version)?</span>
|
||
} <span class="keyword">else</span> <span class="keyword">if</span> (cmd.isVersionHelpRequested()) {
|
||
cmd.printVersionHelp(cmd.getOut());
|
||
<span class="keyword">return</span> cmd.getCommandSpec().exitCodeOnVersionHelp();
|
||
}
|
||
<span class="comment">// invoke the business logic</span>
|
||
myBusinessLogic(parseResult);
|
||
<span class="keyword">return</span> cmd.getCommandSpec().exitCodeOnSuccess();
|
||
|
||
<span class="comment">// invalid user input: print error message and usage help</span>
|
||
} <span class="keyword">catch</span> (ParameterException ex) {
|
||
cmd.getErr().println(ex.getMessage());
|
||
<span class="keyword">if</span> (!UnmatchedArgumentException.printSuggestions(ex, cmd.getErr())) {
|
||
ex.getCommandLine().usage(cmd.getErr());
|
||
}
|
||
<span class="keyword">return</span> cmd.getCommandSpec().exitCodeOnInvalidInput();
|
||
|
||
<span class="comment">// exception occurred in business logic</span>
|
||
} <span class="keyword">catch</span> (<span class="exception">Exception</span> ex) {
|
||
ex.printStackTrace(cmd.getErr());
|
||
<span class="keyword">return</span> cmd.getCommandSpec().exitCodeOnExecutionException();
|
||
}
|
||
}
|
||
|
||
<span class="type">void</span> myBusinessLogic(ParseResult pr) <span class="directive">throws</span> java.io.IOException {
|
||
<span class="type">int</span> count = pr.matchedOptionValue(<span class="string"><span class="delimiter">'</span><span class="content">c</span><span class="delimiter">'</span></span>, <span class="integer">1</span>);
|
||
<span class="predefined-type">List</span><<span class="predefined-type">File</span>> files = pr.matchedPositionalValue(<span class="integer">0</span>, <span class="predefined-type">Collections</span>.<<span class="predefined-type">File</span>>emptyList());
|
||
<span class="keyword">for</span> (<span class="predefined-type">File</span> f : files) {
|
||
<span class="keyword">for</span> (<span class="type">int</span> i = <span class="integer">0</span>; i < count; i++) {
|
||
<span class="predefined-type">System</span>.out.printf(<span class="string"><span class="delimiter">"</span><span class="content">%d: %s%n</span><span class="delimiter">"</span></span>, i, f.getCanonicalFile());
|
||
}
|
||
}
|
||
}</code></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sect2">
|
||
<h3 id="Execute">5.2. <code>Execute</code> Framework <a id="_execute_convenience_method"></a></h3>
|
||
<div class="paragraph">
|
||
<p>The <code>CommandLine</code> class has an <code>execute</code> method which allows applications to reduce some boilerplate when executing the command.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>It takes care of requests for usage or version help, printing errors if the user input was invalid, invoking the business logic, handling any runtime exceptions in the business logic, and finally returning an exit code. The framework has reasonable defaults for each of these tasks, but they can all be configured.</p>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>The example below demonstrates how to customize and invoke the command:</p>
|
||
</div>
|
||
<div class="listingblock">
|
||
<div class="content">
|
||
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> <span class="type">class</span> <span class="class">MyApp</span> {
|
||
|
||
<span class="directive">public</span> <span class="directive">static</span> <span class="type">void</span> main(<span class="predefined-type">String</span><span class="type">[]</span> args) {
|
||
CommandSpec spec = CommandSpec.create();
|
||
spec.mixinStandardHelpOptions(<span class="predefined-constant">true</span>); <span class="comment">// usageHelp and versionHelp options</span>
|
||
spec.addOption(OptionSpec.builder(<span class="string"><span class="delimiter">"</span><span class="content">-c</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">--count</span><span class="delimiter">"</span></span>)
|
||
.paramLabel(<span class="string"><span class="delimiter">"</span><span class="content">COUNT</span><span class="delimiter">"</span></span>)
|
||
.type(<span class="type">int</span>.class)
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">number of times to execute</span><span class="delimiter">"</span></span>).build());
|
||
spec.addPositional(PositionalParamSpec.builder()
|
||
.paramLabel(<span class="string"><span class="delimiter">"</span><span class="content">FILES</span><span class="delimiter">"</span></span>)
|
||
.type(<span class="predefined-type">List</span>.class).auxiliaryTypes(<span class="predefined-type">File</span>.class) <span class="comment">// List<File></span>
|
||
.description(<span class="string"><span class="delimiter">"</span><span class="content">The files to process</span><span class="delimiter">"</span></span>).build());
|
||
CommandLine commandLine = <span class="keyword">new</span> CommandLine(spec);
|
||
|
||
<span class="comment">// optionally configure streams and handlers to be used</span>
|
||
commandLine.setCaseInsensitiveEnumValuesAllowed(<span class="predefined-constant">true</span>) <span class="comment">//configure a parser option</span>
|
||
.setOut(myOutWriter()) <span class="comment">// configure an alternative to System.out</span>
|
||
.setErr(myErrWriter()) <span class="comment">// configure an alternative to System.err</span>
|
||
.setColorScheme(myColorScheme()) <span class="comment">// configure a custom color scheme</span>
|
||
.setExitCodeExceptionMapper(myMapper()) <span class="comment">// map exception to exit code</span>
|
||
.setParameterExceptionHandler(MyApp::invalidUserInput) <span class="comment">// configure a custom handler</span>
|
||
.setExecutionExceptionHandler(MyApp::runtimeException) <span class="comment">// configure a custom handler</span>
|
||
;
|
||
<span class="comment">// set an execution strategy (the run(ParseResult) method) that will be called</span>
|
||
<span class="comment">// by CommandLine.execute(args) when user input was valid</span>
|
||
commandLine.setExecutionStrategy(MyApp::run);
|
||
<span class="type">int</span> exitCode = commandLine.execute(args);
|
||
<span class="predefined-type">System</span>.exit(exitCode);
|
||
}
|
||
|
||
<span class="directive">static</span> <span class="type">int</span> run(ParseResult pr) {
|
||
<span class="comment">// handle requests for help or version information</span>
|
||
<span class="predefined-type">Integer</span> helpExitCode = CommandLine.executeHelpRequest(pr);
|
||
<span class="keyword">if</span> (helpExitCode != <span class="predefined-constant">null</span>) { <span class="keyword">return</span> helpExitCode; }
|
||
|
||
<span class="comment">// implement the business logic</span>
|
||
<span class="type">int</span> count = pr.matchedOptionValue(<span class="string"><span class="delimiter">'</span><span class="content">c</span><span class="delimiter">'</span></span>, <span class="integer">1</span>);
|
||
<span class="predefined-type">List</span><<span class="predefined-type">File</span>> files = pr.matchedPositionalValue(<span class="integer">0</span>, <span class="predefined-type">Collections</span>.<<span class="predefined-type">File</span>>emptyList());
|
||
<span class="keyword">for</span> (<span class="predefined-type">File</span> f : files) {
|
||
<span class="keyword">for</span> (<span class="type">int</span> i = <span class="integer">0</span>; i < count; i++) {
|
||
<span class="predefined-type">System</span>.out.println(i + <span class="string"><span class="delimiter">"</span><span class="content"> </span><span class="delimiter">"</span></span> + f.getName());
|
||
}
|
||
}
|
||
<span class="keyword">return</span> files.size();
|
||
}
|
||
|
||
<span class="comment">// custom handler for runtime errors that does not print a stack trace</span>
|
||
<span class="directive">static</span> <span class="type">int</span> runtimeException(<span class="exception">Exception</span> e,
|
||
CommandLine commandLine,
|
||
ParseResult parseResult) {
|
||
commandLine.getErr().println(<span class="string"><span class="delimiter">"</span><span class="content">INTERNAL ERROR: </span><span class="delimiter">"</span></span> + e.getMessage());
|
||
<span class="keyword">return</span> CommandLine.ExitCode.SOFTWARE;
|
||
}
|
||
|
||
<span class="comment">// custom handler for invalid input that does not print usage help</span>
|
||
<span class="directive">static</span> <span class="type">int</span> invalidUserInput(ParameterException e, <span class="predefined-type">String</span><span class="type">[]</span> strings) {
|
||
CommandLine commandLine = e.getCommandLine();
|
||
commandLine.getErr().println(<span class="string"><span class="delimiter">"</span><span class="content">ERROR: </span><span class="delimiter">"</span></span> + e.getMessage());
|
||
commandLine.getErr().println(<span class="string"><span class="delimiter">"</span><span class="content">Try '</span><span class="delimiter">"</span></span>
|
||
+ commandLine.getCommandSpec().qualifiedName()
|
||
+ <span class="string"><span class="delimiter">"</span><span class="content"> --help' for more information.</span><span class="delimiter">"</span></span>);
|
||
<span class="keyword">return</span> CommandLine.ExitCode.USAGE;
|
||
}
|
||
}</code></pre>
|
||
</div>
|
||
</div>
|
||
<div class="paragraph">
|
||
<p>For more detail, see the <a href="https://picocli.info/#execute">Executing Commands</a> section of the user manual.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="footer">
|
||
<div id="footer-text">
|
||
Version 4.1.4<br>
|
||
Last updated 2019-12-22 08:17:56 +0900
|
||
</div>
|
||
</div>
|
||
</body>
|
||
</html> |