1
1
mirror of https://github.com/mawww/kakoune.git synced 2024-11-22 22:55:26 +03:00

Add a why-kakoune post for review, do not publish yet

This commit is contained in:
Maxime Coste 2016-12-11 20:04:29 +00:00
parent 2eb92a113f
commit 99f77ad78e
13 changed files with 964 additions and 0 deletions

View File

@ -0,0 +1,98 @@
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240">
<defs>
<linearGradient id="gtl" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ffa"/>
<stop offset="75%" stop-color="#cc8"/>
<stop offset="100%" stop-color="#8b6"/>
</linearGradient>
<linearGradient id="gtr" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ac7"/>
<stop offset="60%" stop-color="#896"/>
<stop offset="100%" stop-color="#685"/>
</linearGradient>
<linearGradient id="gbl" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#8a7"/>
<stop offset="50%" stop-color="#ba5"/>
<stop offset="100%" stop-color="#226a3a"/>
</linearGradient>
<linearGradient id="gbr" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#798"/>
<stop offset="15%" stop-color="#586"/>
<stop offset="100%" stop-color="#232"/>
</linearGradient>
<linearGradient id="grad2" x1="100%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" stop-color="rgb(178, 255, 160)" />
<stop offset="25%" stop-color="rgb(178, 245, 118)" />
<stop offset="50%" stop-color="rgb(138, 235, 118)" />
<stop offset="100%" stop-color="rgb(108, 185, 88)" />
</linearGradient>
<linearGradient id="grad3" x1="20%" y1="0" x2="80%" y2="100%">
<stop offset="0%" stop-color="rgb(60, 80, 130)" />
<stop offset="40%" stop-color="rgb(20, 80, 130)" />
<stop offset="80%" stop-color="rgb(20, 115, 140)" />
<stop offset="100%" stop-color="rgb(50, 120, 150)" />
</linearGradient>
<linearGradient id="grad4" x1="0%" y1="100%" x2="100%" y2="0%">
<stop offset="0%" stop-color="rgb(200, 75, 65)" />
<stop offset="50%" stop-color="rgb(250, 100, 77)" />
<stop offset="100%" stop-color="rgb(250, 150, 97)" />
</linearGradient>
<linearGradient id="grad5" x1="45%" y1="0%" x2="55%" y2="100%">
<stop offset="0%" stop-color="rgb(255, 130, 100)" />
<stop offset="20%" stop-color="rgb(235, 90, 65)" />
<stop offset="50%" stop-color="rgb(220, 95, 70)" />
<stop offset="80%" stop-color="rgb(200, 75, 55)" />
<stop offset="100%" stop-color="rgb(220, 95, 75)" />
</linearGradient>
<filter id="blur2">
<feOffset result="offOut" in="SourceGraphic" dx="2" dy="3"/>
<feColorMatrix result="matrixOut" in="offOut" type="matrix"
values = "0.3 0 0 0 0 0 0.3 0 0 0 0 0 0.3 0 0 0 0 0 0.1 0"/>
<feGaussianBlur result="blurOut" in="matrixOut"
stdDeviation="4"/>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
</filter>
<filter id="blur3">
<feOffset result="offOut" in="SourceGraphic" dx="2" dy="3"/>
<feColorMatrix result="matrixOut" in="offOut" type="matrix"
values = "0.0 0 0 0 0 0 0.0 0 0 0 0 0 0.0 0 0 0 0 0 0.3 0"/>
<feGaussianBlur result="blurOut" in="matrixOut"
stdDeviation="4"/>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
</filter>
<filter id="blur4">
<feOffset result="offOut" in="SourceGraphic" dx="4" dy="4"/>
<feColorMatrix result="matrixOut" in="offOut" type="matrix"
values = "0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.25 0"/>
<feGaussianBlur result="blurOut" in="matrixOut"
stdDeviation="6"/>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
</filter>
</defs>
<!-- Logo part -->
<g transform="translate(120,120)">
<!-- green rombus -->
<polygon fill="url(#gtr)" filter="url(#blur2)"
points="0,-100 100,0 0,0"/> <!-- top-right -->
<polygon fill="url(#gtl)" filter="url(#blur2)"
points="0,-100 -100,0 0,0"/> <!-- top-left -->
<polygon fill="url(#gbr)" filter="url(#blur2)"
points="0,100 100,0 0,0"/> <!-- bottom-right -->
<polygon fill="url(#gbl)" filter="url(#blur2)"
points="0,100 -100,0 0,0"/> <!-- bottom-left -->
<!-- K letter -->
<g transform="translate(6, 0)">
<polygon fill="url(#grad3)" filter="url(#blur3)"
points="63,69 19,69 -19,34 9,3"/>
<g filter="url(#blur4)">
<polygon fill="url(#grad4)"
points="69,-68 30,-68 -26,-10 -29,48"/>
<polygon fill="url(#grad5)"
points="-68,-68 -68,71 -30,71 -22,-68"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Binary file not shown.

BIN
why-kakoune/video/async.mkv Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,866 @@
<!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.4">
<title>Why Kakoune</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 */
/* Remove comment around @import statement below when using as a 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}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
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}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
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}
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}
body{-webkit-font-smoothing:antialiased}
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}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.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 #ddddd8;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,ul.no-bullet,ol.no-bullet{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}
ul.no-bullet{list-style:none}
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 only 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;font-weight:bold}
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}
body{tab-size:4}
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}
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}
.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,.menu{color:rgba(0,0,0,.8)}
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 #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;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 #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;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 only 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 #efefed;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 #efefed;left:auto;right:0}}
@media only 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}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#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>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.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 #ddddd8;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;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.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 #ddddd8}
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 blockquote 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:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.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{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
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.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,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:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.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>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{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,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: 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 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#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}
.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}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
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 #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
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{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
</style>
</head>
<body class="article">
<div id="header">
<h1>Why Kakoune</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="imageblock" style="text-align: center">
<div class="content">
<img src="kakoune_logo.svg" alt="kakoune logo">
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_why_invest_time_into_text_editing">Why invest time into text editing</h2>
<div class="sectionbody">
<div class="paragraph">
<p>While discussing with fellow developers, I was asked the following question
a few times: We spend most of our time as developers thinking, not editing
code; so, why invest time into mastering a complicated code editor, and why
lose some cognitive resources on thinking about text editing instead of
about the real programming problem?</p>
</div>
<div class="paragraph">
<p>I think this point of view is misguided, for a few reasons:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Despite their name, code editors are not only about editing, but also about
code navigation. Programming is a hard task partly due to the huge amount of
context we have to keep in mind, and being able to quickly navigate code helps
us refresh that context, by looking at definitions, implementations, and comments.</p>
</li>
<li>
<p>Although code editing itself is not the most important part of programming,
it still takes non-negligible time to perform, and can be optimized by using
better tools.</p>
</li>
<li>
<p>Finally, a programming career spans a few decades, so investing a few weeks
to improving our editing and navigating speed is definitely worth it.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_why_a_modal_text_editor">Why a modal text editor</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_what_is_modal_text_editing">What is modal text editing</h3>
<div class="paragraph">
<p>Now that we have established that investing time into mastering text editing
is worth it, let&#8217;s focus on why I think modal text editors are the way to go.</p>
</div>
<div class="paragraph">
<p>A modal text editor can be, as its name implies, in different modes. Depending
on the current mode, keys have different effects: in <strong>insert</strong> mode most keys
insert their character in the buffer, as in non-modal editors, but in <strong>normal</strong>
(default) mode, keys have a different effect. For example, <code>w</code> can move the
cursor to the next word, <code>y</code> can yank (copy) the current selection, <code>p</code> can
paste, <code>u</code> can undo, <code>g</code> followed by <code>f</code> can open the filename under the cursor&#8230;&#8203;</p>
</div>
<div class="paragraph">
<p>Some commands from <strong>normal</strong> mode would change the mode, for example <code>i</code> would
enter <strong>insert</strong> mode, from which the <code>&lt;esc&gt;</code> key would return to <strong>normal</strong> mode.</p>
</div>
<div class="paragraph">
<p>The first thing to realize is that non-modal text editors are extremely biased
towards insertion. They make insertion easy (by making the default behaviour of
most keys to insert a character into the buffer) at the expense of making most
other operations suboptimal, by requiring hard to reach keys or modifiers (or,
even worse, moving your hand all the way to your mouse).</p>
</div>
<div class="paragraph">
<p>Insertion is a key part of text editing, and is worth optimizing, which is
the whole point of completion systems. But it is only a small part of text
editing, we spend a huge amount of our editing time navigating, moving code
around, copying, pasting and reformating.</p>
</div>
<div class="paragraph">
<p>A modal text editor makes all these operations much more accessible, and easier
to express. But they are not only about having convenient shortcuts.</p>
</div>
</div>
<div class="sect2">
<h3 id="_modal_editing_as_a_text_editing_language">Modal editing as a text editing language</h3>
<div class="paragraph">
<p>Many vi users have an epiphany when they realize that vi does not just
provide a set of modes making various text editing shortcuts easier to type,
but actually provides a text editing language.</p>
</div>
<div class="paragraph">
<p>Commands are composable in order to express complex changes, <code>dw</code> in vi is
not just a shortcut to delete a word, it is the combination of a <strong>verb</strong>: <code>d</code>
for delete, with an <strong>object</strong> <code>w</code> for word. There are more complex objects like
<code>ib</code> (inside block) refers to the content of the parenthesis surrounding
the cursor, so <code>yib</code> would yank (copy) the text inside the surround
parenthesis.</p>
</div>
<div class="paragraph">
<p>This language allows the programmer to express their intent much more closely
than in other editors; most editors can express "delete the word after the
next parenthesis", but more often than not, expressing that intent is more
cumbersome than simply doing an ad-hoc edit. Text editing as a language
changes that, by making clearly expressing your intent the fastest and easiest
way to do your edit.</p>
</div>
<div class="paragraph">
<p>This is a desirable property because a lot of text editing operations are
repetitive, but only on structurally similar text: the subject text are
different, but they follow the same structure. Being able to express the
text editing at the structural level allows for reusable commands, and makes
the computer do the repetitive job.</p>
</div>
<div class="paragraph">
<p>Another often overlooked property of using a text editing language is that
it&#8217;s fun. Programmers are problem solvers, we enjoy solving problems, and
we enjoy even more solving them with a clean and efficient solution. This
kind of text editor transform a dull and repetitive edition task into an
interesting puzzle to solve, and that is an engaging thing.</p>
</div>
<div class="paragraph">
<p>Think about it this way: Yes, programming is about thinking, concentrating
on a design problem, or on a bug, understanding what needs to be done,
designing a solution, and then writing it. More often that not, once you get
to the writing phase, most of the thinking, problem solving, part is done,
now the remaining task is just editing the code. Modal editors make this
phase both faster, and more fun.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_why_kakoune">Why Kakoune</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Up to now, I have used vi as an example for modal text editor, mostly because
I expect most programmers have at least heard of it. However, I dont believe
vi and clones are the best modal text editor out there.</p>
</div>
<div class="paragraph">
<p>I have been working, for the last 5 years, on a new modal editor called
Kakoune. It first started as a reimplementation of Vim (the most popular vi
clone) whose source code is quite dated. But, I soon realized that we could
improve a lot on vi editing model.</p>
</div>
<div class="sect2">
<h3 id="_improving_on_the_editing_model">Improving on the editing model</h3>
<div class="paragraph">
<p>vi basic grammar is <strong>verb</strong> followed by <strong>object</strong>; it&#8217;s nice because it matches
well with the order we use in English, "delete word". On the other hand,
it does not match well with the nature of what we express: There is only a
handfull of <strong>verbs</strong> in text editing (<strong>d*elete, *y*ank, *p*aste, *i*nsert&#8230;&#8203;),
and they don&#8217;t compose, contrarily to *objects</strong> which can be arbitrarily
complex, and difficult to express. That means that errors are not handled
well. If you express your object wrongly with a delete verb, the wrong text
will get deleted, you will need to undo, and try again.</p>
</div>
<div class="paragraph">
<p>Kakoune&#8217;s grammar is <strong>object</strong> followed by <strong>verb</strong>, combined with instantaneous
feedback, that means you always see the current object (In Kakoune we call
that the selection) before you apply your change, which allows you to correct
errors on the go.</p>
</div>
<div class="paragraph">
<p>Kakoune tries hard to fix one of the big problems with the vi model: its
lack of interactivity. Because of the <strong>verb</strong> followed by <strong>object</strong> grammar,
vi changes are made in the dark, we dont see their effect until the whole
editing <strong>sentence</strong> is finished. <code>dtf</code> will delete to next <strong>f</strong>, if you then
realize that was one <strong>f</strong> before the one you targeted, you need to undo,
go back to your initial position, and try again with <code>d2tf</code>. In Kakoune, you
would do <code>tf</code>, see immediately that that is not the <strong>f</strong> you were looking for,
type <code>Tf</code> to extend the selection until the correct <strong>f</strong>, then <code>d</code> to delete.
At each step you get visual feedback, and have the opportunity to correct it.</p>
</div>
<div class="paragraph">
<p>At the lower level, the problem is that vi treats moving around and selecting
an object as two different things. Kakoune unifies that, moving <strong>is</strong> selecting.
<code>w</code> does not just go to the next word, it selects from current position to
the next word. By convention, capital commands tend to expand the selection,
so <code>W</code> would expand the current selection to the next word.</p>
</div>
</div>
<div class="sect2">
<h3 id="_multiple_selections">Multiple selections</h3>
<div class="paragraph">
<p>Another particular feature of Kakoune is its support for, and emphasis
towards the use of multiple selections. Multiple selections in Kakoune
are not just one additional feature, it is the central way of interacting
with your text. For example there is no such thing as a "global replace" in
Kakoune. What you would do is select the whole buffer with the <code>%</code> command,
then select all matches for a regex in the current selections (that is the
whole buffer herer) with the <code>s</code> command, which prompts for a regex. You would
end up with one selection for each match of your regex and use the insert
mode to do your change. Globally replacing foo with bar would be done with
<code>%sfoo&lt;ret&gt;cbar&lt;esc&gt;</code> which is just the combination of basic building blocks.</p>
</div>
<div class="videoblock">
<div class="title">Global replace</div>
<div class="content">
<video src="video/global-replace.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
<div class="paragraph">
<p>Multiple selections provides us with a very powerfull to express structural
selection: we can subselect matches inside the current selections, keep
selections containing/not containing a match, split selections on a regex,
swap selections contents&#8230;&#8203;</p>
</div>
<div class="paragraph">
<p>For example, convert from <code>snake_case_style</code> to <code>camelCaseStyle</code> can be done
by selecting the word (with <code>w</code> for example) then subselecting underscores
in the word with <code>s_&lt;ret&gt;</code>, deleting these with <code>d</code>, then upper casing the
selected characters with <code>~</code>. The inverse operation could be done by selecting
the word, then subselecting the upper case characters with <code>s[A-Z]&lt;ret&gt;</code>
lower casing them with ``` and then inserting an underscode before them with
<code>i_&lt;esc&gt;</code> This operation could be put in a macro, and would be reusable
easily to convert any identifier.</p>
</div>
<div class="videoblock">
<div class="title">Camel case to snake case</div>
<div class="content">
<video src="video/camel.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
<div class="paragraph">
<p>Another example would be parameter swapping, if you had <code>func(arg2, arg1);</code>
you could select the contents of the parenthesis with <code>&lt;a-i&gt;(</code>, split the
selection on comma with <code>S, &lt;ret&gt;</code>, and swap selection contents with <code>&lt;a-'&gt;</code>.</p>
</div>
<div class="videoblock">
<div class="title">Swapping arguments</div>
<div class="content">
<video src="video/args-swap.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
<div class="paragraph">
<p>It is as well easy to use multiple selections for alignment, as the <code>&amp;</code>
command will align all selection cursors by inserting blanks before
selection start</p>
</div>
<div class="videoblock">
<div class="title">Aligning variables</div>
<div class="content">
<video src="video/align.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
<div class="paragraph">
<p>Or to use multiple selections as a way to gather some text from different
places and regroup it in another place, thanks to a special form of pasting
<code>&lt;a-p&gt;</code> that will paste every yanked selections instead of the first one.</p>
</div>
<div class="videoblock">
<div class="title">Regrouping manager objects together</div>
<div class="content">
<video src="video/regroup.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_discoverability">Discoverability</h3>
<div class="paragraph">
<p>Keyboard oriented programs tend to be at a disadvantage compared to GUI
applications because they are less discoverable; there is no menu bar on
which to click to see the available options, no tooltip appearing when you
hover above a button explaining what it does.</p>
</div>
<div class="paragraph">
<p>Kakoune solves this problem through the use of two mechanisms: extensive
completion support, and auto-information display.</p>
</div>
<div class="paragraph">
<p>When a command is written in a prompt, Kakoune will automatically open a menu
providing you with the available completions for the current parameter. It
will know if the parameter is supposed to be a word against a fixed set
of word, the name of a buffer, a filename, etc&#8230;&#8203; Actually, as soon as <code>:</code>
is typed, entering command prompt mode, the list of existing commands will
be displayed in the completion menu.</p>
</div>
<div class="paragraph">
<p>Additionally, Kakoune will display an information box, describing what the
command does, what optional switches it can take, what they do&#8230;&#8203;</p>
</div>
<div class="videoblock">
<div class="title">Command discoverability</div>
<div class="content">
<video src="video/discoverability.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
<div class="paragraph">
<p>That information box gets displayed in other cases, for example if the <code>g</code>
key is hit, which then waits for another key (<code>g</code> is the <strong>goto</strong> commands
prefix), an information box will display all the recognized keys, informing
the user that Kakoune is waiting on a keystroke, and listing the available
options.</p>
</div>
<div class="paragraph">
<p>To go even further in discoverablility, the auto information system can
be set to display an information box after each normal mode keystroke,
explaining what the key pressed just did.</p>
</div>
</div>
<div class="sect2">
<h3 id="_extensive_completion_support">Extensive completion support</h3>
<div class="paragraph">
<p>Keyboard oriented programs are much easier to work with when they provide
extensive completion support. For a long time, completion has been prefix
based, and that has been working very well.</p>
</div>
<div class="paragraph">
<p>More recently, we started to see more and more programs using the so called
fuzzy completion. Fuzzy completion tends to be subsequence based, instead
of prefix based, which means the typed query needs to be a subsequence of
a candidate to be considered matching, instead of a prefix. That will generate
more candidates (all prefix matches are also subsequence matches), so it
needs a good ranking algorithm to sort the matches and put the best ones first.</p>
</div>
<div class="paragraph">
<p>Kakoune embraces fuzzy matching for its completion support, which kicks in both
during insert mode, and prompt mode.</p>
</div>
<div class="videoblock">
<div class="title">Word completion support</div>
<div class="content">
<video src="video/completion.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
<div class="paragraph">
<p>Insert mode completion provides completion suggestions while inserting in the
buffer, it can complete words from the buffer, or from all buffers, lines,
filenames, or get completion candidates from an external source, making it
possible to implement intelligent code completion.</p>
</div>
<div class="videoblock">
<div class="title">Language specific completion support</div>
<div class="content">
<video src="video/cpp-completion.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
<div class="paragraph">
<p>Prompt completion is displayed whenever we enter command mode, and provides
completion candidates that are adapted to the command being entered, and to
the current argument being edited.</p>
</div>
</div>
<div class="sect2">
<h3 id="_a_better_unix_citizen">A better unix citizen</h3>
<div class="paragraph">
<p>Easily making programs cooperate with each others is one of the main strength
of the Unix environment. Kakoune is designed to integrate nicely with a POSIX
system: various text editing commands give direct access to the power of POSIX
tools, like <code>|</code>, which prompts for a shell command and pipe selections through
it, replacing their contents with the command output, or <code>$</code> that prompts for
a command, and keeps selections for which the command returned success.</p>
</div>
<div class="paragraph">
<p>This is only the tip of the iceberg, Kakoune is very easily controllable from
the shell, just pipe whatever commands you like to <code>kak -p &lt;session&gt;</code>, and the
target Kakoune session will execute these.</p>
</div>
<div class="paragraph">
<p>Kakoune command line also support shell expansion, similar to what <code>$(...)</code>
does in a shell. If you type <code>echo %sh{ echo hello }</code> in the command prompt,
"hello" will get displayed in the status line. Various values from Kakoune
can be accessed in these expand through environment variables, which, along
with shell scripting forms the basis of Kakoune extension model.</p>
</div>
<div class="paragraph">
<p>This model, although a bit less familiar than integrating a scripting language,
is conceptually very simple, relatively simple implementation-wise, and is
expressive enough to implement a custom code completer, linters, formatters&#8230;&#8203;</p>
</div>
<div class="paragraph">
<p>Moreover, combined with support for <code>fifo</code> buffers, that read data from a
named <code>fifo</code>, Kakoune ends up with an extension model that easily support
asynchronous tasks, by forking a shell in the background to do long lived
work (<code>grep</code> or <code>make</code> for example) while displaying the result as they
come through the <code>fifo</code>.</p>
</div>
<div class="paragraph">
<p>Kakoune also tries to limit its scope to code editing: in particular, it does
not try to manage windows, and lets the system&#8217;s window manager, or terminal
multiplexer (such as tmux), handle that responsiblity. This is achieved through
a client/server design: An editing session runs on a server process, and
multiple clients can connect to that session to display different buffers.</p>
</div>
<div class="videoblock">
<div class="title">Asynchronous make and multiple clients in tmux</div>
<div class="content">
<video src="video/async.webm" autoplay controls loop>
Your browser does not support the video tag.
</video>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_final_thoughts">Final Thoughts</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Kakoune provides an efficient code editing environment, both very predictible,
hence scriptable, and very interactive. Its learning curve is considerably
easier than Vim thanks to a more consistent design associated with strong
discoverability, while still being faster (as in less keystrokes) in most
use cases.</p>
</div>
<div class="paragraph">
<p>Although easier to learn than Vim, the learning curve is still quite steep,
however we have established that investing time into optimizing the text
editing workflow is worth it for programmers. Moreover, Kakoune simply makes
code editing a fun and rewarding experience.</p>
</div>
<div class="paragraph">
<p>Kakoune is still evolving, getting better as we get more users, and gathering
more use cases to cater for. It&#8217;s already a very good code editor, and we need
you to use it so that it can be made even better.</p>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2016-12-11 19:08:08 GMT
</div>
</div>
</body>
</html>