<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rasukarusan</title>
    <description>The latest articles on DEV Community by Rasukarusan (@rasukarusan).</description>
    <link>https://dev.to/rasukarusan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F579052%2F094392be-4540-40a0-85b4-f3c75ee6c841.png</url>
      <title>DEV Community: Rasukarusan</title>
      <link>https://dev.to/rasukarusan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rasukarusan"/>
    <language>en</language>
    <item>
      <title>Shellnium: Simple Selnium WebDriver for Bash</title>
      <dc:creator>Rasukarusan</dc:creator>
      <pubDate>Thu, 25 Feb 2021 06:06:30 +0000</pubDate>
      <link>https://dev.to/rasukarusan/shellnium-simple-selnium-webdriver-for-bash-1a9k</link>
      <guid>https://dev.to/rasukarusan/shellnium-simple-selnium-webdriver-for-bash-1a9k</guid>
      <description>&lt;h2&gt;
  
  
  Selenium can be used in many languages
&lt;/h2&gt;

&lt;p&gt;Selenium, as we all know, is a tool for automated browser operations.&lt;br&gt;
Selenium uses a WebDriver to perform automatic browser operations, and there are WebDrivers for various languages such as &lt;code&gt;php&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, and &lt;code&gt;javascript&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, if you want to use &lt;code&gt;php&lt;/code&gt;, you can use &lt;a href="https://github.com/php-webdriver/php-webdriver"&gt;facebook-webdriver&lt;/a&gt; like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// run chromedriver&lt;/span&gt;
&lt;span class="nv"&gt;$driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RemoteWebDriver&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;DesiredCapabilities&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// open the URL&lt;/span&gt;
&lt;span class="nv"&gt;$driver&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://www.google.co.jp/'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;javascript&lt;/code&gt;, you can use &lt;a href="https://github.com/SeleniumHQ/selenium/tree/master/javascript/node/selenium-webdriver"&gt;selenium-webdriver&lt;/a&gt; to do this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// run chromedriver&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;capabilities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Capabilities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;withCapabilities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;// open the URL&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://www.google.co.jp/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can be written in a similar way in almost any language, so if you have experience with Selenium in any language, you should be able to write it easily in other languages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yes, except for ShellScript.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why isn't there a WebDriver for Bash or Zsh?
&lt;/h2&gt;

&lt;p&gt;As far as I can see, there is no WebDriver for ShellScript, so if you want to try Selenium with Shell, you'll have a hard time.&lt;br&gt;
You need to do &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;composer install&lt;/code&gt;, etc. to get the environment ready.&lt;br&gt;
I thought it would be easier for me to automate browser operations, but that's not the case.&lt;/p&gt;
&lt;h2&gt;
  
  
  Selenium for Shell Hackers - Shellnium
&lt;/h2&gt;

&lt;p&gt;So, this is for those who want to use ShellScript to easily perform automatic browser operations.&lt;br&gt;
As shown below, automatic browser operation can be achieved with ShellScript alone. &lt;strong&gt;All you need is bash or zsh.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  How to perform automatic browser operations with Shell
&lt;/h2&gt;

&lt;p&gt;The flow of automatic browser operation is as follows. All you have to do is POST JSON to the browser (driver) with curl.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oyfKaRyN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c1tn23xy2rm5eebjfol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oyfKaRyN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c1tn23xy2rm5eebjfol.png" alt="post_json"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser Launch&lt;/li&gt;
&lt;li&gt;URL transition&lt;/li&gt;
&lt;li&gt;Keyboard input&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;one by one to get a feel for it.&lt;/p&gt;
&lt;h2&gt;
  
  
  0. Launch chromedriver
&lt;/h2&gt;

&lt;p&gt;First of all, you need to run &lt;code&gt;chromedriver&lt;/code&gt;. if you don't have &lt;code&gt;chromedriver&lt;/code&gt;, just &lt;code&gt;brew install chromedriver&lt;/code&gt;. (or download it directly from the official website).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;chromedriver
Starting ChromeDriver 2.40.565386 &lt;span class="o"&gt;(&lt;/span&gt;45a059dc425e08165f9a10324bd1380cc13ca363&lt;span class="o"&gt;)&lt;/span&gt; on port 9515
Only &lt;span class="nb"&gt;local &lt;/span&gt;connections are allowed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then chromedriver wait at &lt;code&gt;http://localhost:9515&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Launching the Browser &amp;amp; Getting the Session ID
&lt;/h2&gt;

&lt;p&gt;Let's start the browser from Shell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"desiredCapabilities": { "browserName": "chrome" }}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     http://localhost:9515/session
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, it's that simple. If you run it, you will see the browser start up.&lt;br&gt;
In order to send commands to this browser in the future, we will need to specify the session and send the commands, so we will need to obtain the session ID.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sessionID&lt;/code&gt; will be returned as JSON in the above curl response, so extract the sessionId in it. Since we are using ShellScript, it will be easier to use &lt;code&gt;jq&lt;/code&gt;. Of course, using &lt;code&gt;grep&lt;/code&gt; is also good.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl ... http://localhost:9515/session | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.sessionId'&lt;/span&gt;
&lt;span class="c"&gt;# Get the sessionID&lt;/span&gt;
e1c3d895e7c7d42383c110e5e4cd7bbf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. URL transition
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url":"https://google.co.jp"}'&lt;/span&gt; http://localhost:9515/session/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SESSION_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/url
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be redirected to the top page of Google. The &lt;code&gt;${SESSION_ID}&lt;/code&gt; is the one you obtained earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Getting elements &amp;amp; Keyboard input
&lt;/h2&gt;

&lt;p&gt;Now let's do some Selenium-like things. First, we'll do something like &lt;code&gt;findElementByName()&lt;/code&gt; to get the element from the name attribute.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"using":"name", "value": "q"}'&lt;/span&gt; http://localhost:9515/session/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SESSION_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/element &lt;span class="se"&gt;\&lt;/span&gt;
    | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.value.ELEMENT'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can get the element with &lt;code&gt;{"using": "property name", "value": "value"}&lt;/code&gt;. Google's search box has &lt;code&gt;name="q"&lt;/code&gt;, so you can specify it as &lt;code&gt;{"using": "name", "value": "q"}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PlV0yE3g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nd35l02u2kjdc0rjx33a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PlV0yE3g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nd35l02u2kjdc0rjx33a.png" alt="search_box"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the &lt;strong&gt;element ID&lt;/strong&gt; of the search box by executing the above curl.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl ... http://localhost:9515/session/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SESSION_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/element | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.value.ELEMENT'&lt;/span&gt;
&lt;span class="c"&gt;# Get the element ID&lt;/span&gt;
0.5757440182130869-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An "element ID" is required to perform any action using the element, such as clicking on the element, keyboard input, or focus.&lt;/p&gt;

&lt;p&gt;In the case of keyboard input, it looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"value": ["animal\n"]}'&lt;/span&gt; http://localhost:9515/session/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SESSION_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/element/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;elementId&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only thing you need to be careful about is to pass the string to be input in array format. You can also add &lt;code&gt;\n&lt;/code&gt; to the end to make it act as an ENTER.&lt;/p&gt;

&lt;h2&gt;
  
  
  Works like Selenium
&lt;/h2&gt;

&lt;p&gt;If you combine the above into a single ShellScript and run it, you have a complete Selenium.&lt;/p&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

main&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;# Open the URL&lt;/span&gt;
    navigate_to &lt;span class="s1"&gt;'https://google.co.jp'&lt;/span&gt;

    &lt;span class="c"&gt;# Get the search box&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;searchBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;find_element &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="s1"&gt;'q'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# keyboard input and searching&lt;/span&gt;
    send_keys &lt;span class="nv"&gt;$searchBox&lt;/span&gt; &lt;span class="s2"&gt;"animal&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

get_session_id&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
            "desiredCapabilities": {
                "browserName": "chrome"
            }
        }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/session | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.sessionId'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:9515
&lt;span class="nv"&gt;SESSION_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get_session_id&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ROOT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/session/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SESSION_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;


navigate_to&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
    curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url":"'&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'"}'&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE_URL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/url
&lt;span class="o"&gt;}&lt;/span&gt;

find_element&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
    curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"using":"'&lt;/span&gt;&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="s1"&gt;'", "value": "'&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="s1"&gt;'"}'&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE_URL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/element | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.value.ELEMENT'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

send_keys&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;elementId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
    curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"value": ["'&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="s1"&gt;'"]}'&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE_URL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/element/&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;elementId&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/value &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
&lt;span class="o"&gt;}&lt;/span&gt;

main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's very simple: by making the part of curl that throws JSON into a small function, if you just look at the contents of the main function, it's already a complete WebDriver description.&lt;br&gt;
The parts that have been put together into functions can be put together in selenium.sh, etc. and sourced as shown below for a very simple look.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; ./selenium.sh

main&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;# Open the URL&lt;/span&gt;
    navigate_to &lt;span class="s1"&gt;'https://google.co.jp'&lt;/span&gt;

    &lt;span class="c"&gt;# Get the search box&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;searchBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;find_element &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="s1"&gt;'q'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# keyboard input and searching&lt;/span&gt;
    send_keys &lt;span class="nv"&gt;$searchBox&lt;/span&gt; &lt;span class="s2"&gt;"animal&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bonus: iTerm 🤝 Selenium
&lt;/h2&gt;

&lt;p&gt;So, I attached iTerm and Selenium together with ShellScript.&lt;/p&gt;



&lt;p&gt;While working with iTerm, the browser is automatically operating behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  More
&lt;/h2&gt;

&lt;p&gt;I've created a repository for &lt;code&gt;shellnium&lt;/code&gt;, so have a look at that too!&lt;br&gt;
&lt;a href="https://github.com/Rasukarusan/shellnium"&gt;https://github.com/Rasukarusan/shellnium&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.w3.org/TR/webdriver/#get-title"&gt;WebDriver&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bash</category>
      <category>selenium</category>
    </item>
    <item>
      <title>Make Button By Floating Window</title>
      <dc:creator>Rasukarusan</dc:creator>
      <pubDate>Sun, 14 Feb 2021 12:12:47 +0000</pubDate>
      <link>https://dev.to/rasukarusan/make-button-by-floating-window-2i22</link>
      <guid>https://dev.to/rasukarusan/make-button-by-floating-window-2i22</guid>
      <description>&lt;h2&gt;
  
  
  Let's make a button by floating window!
&lt;/h2&gt;

&lt;p&gt;I made a button using floating window. You can push the button by ENTER.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dyji53RD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/Rasukarusan/blog-assets/blob/master/nvim-button/demo.gif%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dyji53RD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/Rasukarusan/blog-assets/blob/master/nvim-button/demo.gif%3Fraw%3Dtrue"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How do I make it look like a button?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gkim17T7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4wwee1aked3kiq40uqbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gkim17T7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4wwee1aked3kiq40uqbv.png" alt="screenshot_ 2021-02-14 20.56.45"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Prepare two windows, front and back.&lt;/li&gt;
&lt;li&gt;Make the color of the back a little darker than the color of the front.&lt;/li&gt;
&lt;li&gt;Lower the position of the front so that it covers the back when it is pressed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When ENTER is pressed, just move it back down and it will appear to be pressed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;hi&lt;/span&gt; FrontColor guibg&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;#F27200&lt;/span&gt;
&lt;span class="k"&gt;hi&lt;/span&gt; BackColor guibg&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;#AC5D24&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;str&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; width &lt;span class="p"&gt;=&lt;/span&gt; nvim_win_get_width&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; shift &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;width&lt;span class="sr"&gt;/2) - floor(strdisplaywidth(a:str)/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float2nr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;shift&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;a:str&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:remove_button&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; front_win &lt;span class="p"&gt;=&lt;/span&gt; nvim_get_current_win&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;front_win&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_close&lt;span class="p"&gt;(&lt;/span&gt;back_win&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_close&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; front_win&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:create_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;config&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; hi_group &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;a:1&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; transparency &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; buf &lt;span class="p"&gt;=&lt;/span&gt; nvim_create_buf&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;false&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;win&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; nvim_open_win&lt;span class="p"&gt;(&lt;/span&gt;buf&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;a:config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; hi_group &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_option&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;win&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'winhighlight'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; hi_group&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_option&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;win&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'winblend'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; transparency&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_config&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;win&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;a:config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;endif&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;win&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; front_win &lt;span class="p"&gt;=&lt;/span&gt; nvim_get_current_win&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;front_win&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; config &lt;span class="p"&gt;=&lt;/span&gt; nvim_win_get_config&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; config&lt;span class="p"&gt;.&lt;/span&gt;row &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_config&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;,&lt;/span&gt; config&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;sleep&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;ms
  &lt;span class="k"&gt;redraw&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; config&lt;span class="p"&gt;.&lt;/span&gt;row &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_config&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;,&lt;/span&gt; config&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; row &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;col&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; width &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; height &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; config &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'relative'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'editor'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'row'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; row&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'col'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'width'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; width&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'height'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; height&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'anchor'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'NW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'style'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'minimal'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;" back window&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_config &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;config&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_config&lt;span class="p"&gt;.&lt;/span&gt;row &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;s:create_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;back_config&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Normal:BackColor'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;" front window&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; front_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;s:create_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;config&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Normal:FrontColor'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;setline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;s:center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Button'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;nowait&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;q&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;remove_button&lt;span class="p"&gt;()&lt;/span&gt;
  nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;push&lt;span class="p"&gt;()&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;front_win&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; back_win
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nv"&gt;s:main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Bonus: Fire bullets with ENTER
&lt;/h2&gt;


    
        
    


&lt;p&gt;And you can move by hjkl.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;hi&lt;/span&gt; FrontColor guibg&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;#F27200&lt;/span&gt;
&lt;span class="k"&gt;hi&lt;/span&gt; BackColor guibg&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mh"&gt;#AC5D24&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;str&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; width &lt;span class="p"&gt;=&lt;/span&gt; nvim_win_get_width&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; shift &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;width&lt;span class="sr"&gt;/2) - floor(strdisplaywidth(a:str)/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float2nr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;shift&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;a:str&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;direction&lt;span class="p"&gt;,&lt;/span&gt; value&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; front_win &lt;span class="p"&gt;=&lt;/span&gt; nvim_get_current_win&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;front_win&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; id &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;front_win&lt;span class="p"&gt;,&lt;/span&gt; back_win&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; config &lt;span class="p"&gt;=&lt;/span&gt; nvim_win_get_config&lt;span class="p"&gt;(&lt;/span&gt;id&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;a:direction&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt;
      &lt;span class="k"&gt;let&lt;/span&gt; config&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;col&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;a:value&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="k"&gt;let&lt;/span&gt; config&lt;span class="p"&gt;.&lt;/span&gt;row &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;a:value&lt;/span&gt;
    &lt;span class="k"&gt;endif&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_config&lt;span class="p"&gt;(&lt;/span&gt;id&lt;span class="p"&gt;,&lt;/span&gt; config&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;endfor&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:remove_button&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; front_win &lt;span class="p"&gt;=&lt;/span&gt; nvim_get_current_win&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;front_win&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_close&lt;span class="p"&gt;(&lt;/span&gt;back_win&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_close&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; front_win&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:create_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;config&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; hi_group &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;a:1&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; transparency &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; buf &lt;span class="p"&gt;=&lt;/span&gt; nvim_create_buf&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;false&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;win&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; nvim_open_win&lt;span class="p"&gt;(&lt;/span&gt;buf&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;a:config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; hi_group &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_option&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;win&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'winhighlight'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; hi_group&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_option&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;win&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'winblend'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; transparency&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_config&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;win&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;a:config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;endif&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;win&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:fire&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; front_win &lt;span class="p"&gt;=&lt;/span&gt; nvim_get_current_win&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;conf&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; nvim_win_get_config&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; row &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;row &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;col&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;col&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="k"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;width
  &lt;span class="k"&gt;let&lt;/span&gt; width &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; height &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; config &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'relative'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'editor'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'row'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; row&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'col'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'width'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; width&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'height'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; height&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'anchor'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'NW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'style'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'minimal'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; ballet &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;s:create_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;config&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Normal:FrontColor'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; config&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;col&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_config&lt;span class="p"&gt;(&lt;/span&gt;ballet&lt;span class="p"&gt;,&lt;/span&gt; config&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;redraw&lt;/span&gt;
    &lt;span class="k"&gt;sleep&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;ms
  &lt;span class="k"&gt;endfor&lt;/span&gt;

  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_close&lt;span class="p"&gt;(&lt;/span&gt;ballet&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;true&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:push&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; front_win &lt;span class="p"&gt;=&lt;/span&gt; nvim_get_current_win&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;front_win&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; config &lt;span class="p"&gt;=&lt;/span&gt; nvim_win_get_config&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; config&lt;span class="p"&gt;.&lt;/span&gt;row &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_config&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;,&lt;/span&gt; config&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;sleep&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;ms
  &lt;span class="k"&gt;redraw&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; config&lt;span class="p"&gt;.&lt;/span&gt;row &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; nvim_win_set_config&lt;span class="p"&gt;(&lt;/span&gt;front_win&lt;span class="p"&gt;,&lt;/span&gt; config&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nv"&gt;s:fire&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; row &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;col&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; width &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; height &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; config &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'relative'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'editor'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'row'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; row&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'col'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;col&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'width'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; width&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'height'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; height&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'anchor'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'NW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'style'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'minimal'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;" back window&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_config &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;deepcopy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;config&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_config&lt;span class="p"&gt;.&lt;/span&gt;row &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; back_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;s:create_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;back_config&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Normal:BackColor'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;" front window&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; front_win &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;s:create_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;config&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Normal:FrontColor'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;setline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;s:center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Button'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;nowait&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;nowait&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;h&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'x'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;-2&lt;/span&gt;&lt;span class="p"&gt;)&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;nowait&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;j&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;nowait&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;k&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'y'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;-2&lt;/span&gt;&lt;span class="p"&gt;)&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;nowait&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;q&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;remove_button&lt;span class="p"&gt;()&lt;/span&gt;
  nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;push&lt;span class="p"&gt;()&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:button_window&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;front_win&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; back_win
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nv"&gt;s:main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Have a happy vim life!&lt;/p&gt;

</description>
      <category>neovim</category>
    </item>
  </channel>
</rss>
