<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by lakshman kumar on Medium]]></title>
        <description><![CDATA[Stories by lakshman kumar on Medium]]></description>
        <link>https://medium.com/@lakshmankumar12?source=rss-1836b4937c96------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*czWpiXEYZRl2PmPc.png</url>
            <title>Stories by lakshman kumar on Medium</title>
            <link>https://medium.com/@lakshmankumar12?source=rss-1836b4937c96------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 18 May 2026 06:36:44 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@lakshmankumar12/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Reimaging a headless system]]></title>
            <link>https://medium.com/@lakshmankumar12/reimaging-a-headless-system-1cf32aa2c615?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/1cf32aa2c615</guid>
            <category><![CDATA[headless]]></category>
            <category><![CDATA[grub]]></category>
            <category><![CDATA[embedded]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[netboot]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Sun, 13 Oct 2024 08:52:21 GMT</pubDate>
            <atom:updated>2024-10-13T09:28:36.031Z</atom:updated>
            <content:encoded><![CDATA[<h3>Usecase</h3><p>We have an embedded system, which in its final form factor has only its power-cable, and networking port exposed. There are usb and hdmi ports in the machine, but these are concealed. The only access to this device is via networking(ssh). The SSD on this disk is factory imaged. During developement cycles, if we need to reimage and test, we need to open up the case to get access to the usb/hdmi ports for connecting monitor/keyboard and get console access — so that we can choose different boot options from BIOS and follow console instructions during boot. Typically this is done by booting a live-linux-image over USB and then from the console-terminal, we scpthe disk-image from a remote-file-server to the sda of the machine, and reboot the machine.</p><p>This article shows how to reimage this machine <strong>without using console/keyboard access </strong>— purely via networking access. This saves the trouble of having to open the casing and do the reimaging on the fly.</p><h4>Challenges</h4><p>The following things make the installation challenging:</p><ul><li>The choice of boot option is always set to the SSD disk in the UEFI. Editing this to anything else is challenging in the first place without access to UEFI console.</li><li>Even if we manage to PXE boot instructing the UEFI to do so (say by tools like efibootmgr), we still dont have console access to follow through instructions as part of boot — we need to boot some live OS, and then ssh into the machine to dd the image. To know the IP of the machine running the liveOS, and the choice of user-name / passwd is not trivial.</li><li>Further PXE boots call for extra options doled out as part of DHCP-responses — and this needs talking to the IT-personal as we dont own the corporate DHCP-server settings. Some non-intrusive way to doling out the boot images/settings, without having to adjust corporte-DHCP settings would be preferred.</li><li>Using a non-PXE boot option, like trying to dd an image to the SSD, from an OS that is still mounted on the SSD itself, is not guaranteed to work. This is because random processes(eg systemd/journaling) of the running OS may continue to write to the disk and the SSD may have a corrupted image. So we are pretty much limited to performing the imaging of the disk when the disk is unmounted and is totally untouched by the running OS, except for the dd process.</li></ul><h3>Quick rundown of the solution</h3><ul><li>We run a http-server on the network. This will serve iPXE boot-scripts, initrd/vmlinuz images, live-ubuntu-iso, and autoinstall scripts(that will just stop post kernel-load without really installing anything).</li><li>Use <a href="https://ipxe.org/">iPXE</a>. We will use a customized image that will simply chain load from a script off the http-server.</li><li>On the current running OS, we will copy the customized iPXE image and let grub boot from this next time. <br>– The UEFI on the device continues to boot from SSD. But the grub will now boot the iPXE file, instead of the current OS.</li><li>The iPXE image will pick the script-file from the http-server, that further instructs it to boot the live-ubuntu-iso. Here we supply among other args two important args. <br>– The first is the choce of IP. Once the live-ubuntu is booted, we pass a predictable IP so that we can ssh into the machine. <br>– The second is the autoinstall script to use — this script contains a preset user-name and ssh-keyfile/password to use so that we can login to the live-linux that is just booted.</li><li>Once the machine boots the live-os, we keep trying to ssh login (with the known credential). Once the ssh is successful, we dd the image from the file-server to the hard-disk.</li></ul><h3>The steps in detail</h3><h4>Preparing the iPXE image</h4><p>Clone the iPXE repository</p><pre>git clone git@github.com:ipxe/ipxe.git<br>cd ipxe/src<br><br># prepare a file boot.ipxe that will simply pick a file from an external server<br># ensure the change the IP of the server here. If the IP of the server changes<br># we will have to rebuild this ipxe image<br>cat &gt; boot.ipxe &lt;&lt;EOF<br>#!ipxe<br>dhcp<br>chain http://192.168.122.110:8999/boot-http.ipxe<br>EOF<br><br>make bin/ipxe.lkrn bin-x86_64-efi/ipxe.efi EMBED=boot.ipxe</pre><p>As part of the make we will get a bin-x86_64-efi/ipxe.efi file.</p><h4>Preparing the grub entry</h4><p>On the current running machine that needs to be reimaged, add this content to /etc/grub.d/40_custom at its end. The choice of the UUID should preferably be the partition id where /boot is mounted. Copy the ipxe.efi file obtained in the above step in the root folder of this partition. Care should be take that the UUID reflects the partition where the ipxe.efi is kept and the chainloader argument reflects the path of the file in this partition.</p><pre>menuentry &quot;Reinstall via iPXE&quot; {<br>  insmod part_gpt<br>  insmod chain<br>  search --no-floppy --fs-uuid --set=root 84d5ce35-af85-44fe-bd15-c26b8418d0d6<br>  chainloader /ipxe.efi<br>}</pre><p>Once added, rebuild grub-cfg: sudo update-grub and find the position of this menuentry:</p><pre>grep -e &#39;^menuentry&#39; -e &#39;^submenu&#39; /boot/grub/grub.cfg</pre><p>Giving a 0-based index, say if the Reinstall via iPXEappears 4th in the list, do: sudo grub-reboot 3 to have grub choose this entry for next boot.</p><h4>Preparing the HTTP server</h4><p>On the machine that we chose to run http server, we will have to first pick a folder where we have all of these files</p><ul><li>Ubuntu-ISO file. The ubuntu-22.04.4-live-server-amd64.iso(jammy-server) would do fine.</li><li>Pick the casper/initrd and casper/vmlinuz files out of iso and copy in the same folder. Use tools like ( 7z x file.iso ) to unzip the iso and extract the 2 files.</li><li>Create a autoinstall file that supplies the username/password to login in via ssh. A sample file is shown below. We can keep all of the below same, except for the ssh_authorized_keys and the password under list. Use any password and ssh-key of choice. The password is a encrypted one. Use python3 -c ‘import crypt;print(crypt.crypt(“clearpassword&quot;))’ to get this.</li><li>The name of the file having the below content MUST be cloud-data. On the same place also touch meta-data and touch vendor-data. The latter 2 are empty files, but MUST exist!</li></ul><pre>#cloud-config<br>chpasswd:<br>    expire: false<br>    list:<br>        - installer:$6$TrC8TZduman3BRLs$KZd58FKOVZ8Hqc/ielAw.B/AcB20Ls.J3TD7IKiN53.i.iB0xtIyFN4CxKUnTTQwxcTPlA1kQgwrUUeeVF84w.<br>ssh_authorized_keys:<br>    - &quot;ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCg/6dxFHFbrQct3sdo42qG29Q5CAsUESwIUq6ZH7jTX/h9ayikqnDSNnKka1PGRcbAkMCQFvsFvEwjZiI7n76lhcsuyRfwRDQmpwMUnLIJNobGWTLscuhBXe7eg9WAR8cuN5hOE1b9UPmy2VYMJ0R2BydFMhSwQ9f4ZMLnqeooMHfj+x5k14jpCO0UZCmR82/esZO4QfeSzQWhaIbTQMZsNTRvn8qRObUo80bakUI4IK8oWZgbwqj2Z7QyA6mzqo4rTJpFyltho3VRiv9DBsPtYBh6YE0cguKkcB9Bzp9zrDDEfQIXnp8XS/W4tn1kS1478DPlABzPk+BA7ogaSxPVdGqy0Q5IAfzWuNNI6z5KFwYVuteqqR1hNF4dQGdq2B/aFIXygt0tSALkEoHnezFfE9WeK2wetxZAjtxqjsvLl8474qw0UjYWtVuQdavwUyjtS7EBZ44826ayLQGACHt54eNNTp45ReSC/AMeZ1znavSyMZceQCsWG5qDSd+vnNs= SSH-key-for-login&quot;<br>system_info:<br>  default_user:<br>    name: installer<br>    lock_passwd: false<br>    gecos: Ubuntu<br>    groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video]<br>    sudo: [&quot;ALL=(ALL) NOPASSWD:ALL&quot;]<br>    shell: /bin/bash<br>autoinstall:<br>  version: 1<br>  early-commands:<br>    - ip addr show &gt; /dev/ttyS0<br>    - ip addr show &gt; /dev/tty0<br>    - while [ ! -f /run/some-non-exist-file ]; do sleep 1; done</pre><ul><li>Create a boot-http.ipxe file that instructs to boot the live-server. <br>- The ipval gives the IP-details of the machine that will be used when the live-os is booted. This is how we know which IP to login. We can choose to give the same current IP used in the system to avoid DHCP conflicts with other machines on the network. Its format is client-ip::gwip:netmask::::dnsip</li></ul><pre>set server_ip http://192.168.122.110:8999<br>kernel ${server_ip}/vmlinuz || sleep 3600<br>initrd ${server_ip}/initrd || sleep 3600<br>set ipval 192.168.122.100::192.168.122.1:255.255.255.0::::192.168.122.1<br>imgargs vmlinuz initrd=initrd boot=casper ip=${ipval} cloud-config-url=/dev/null url=${server_ip}/ubuntu-22.04.4-live-server-amd64.iso autoinstall ds=nocloud-net;s=${server_ip}/ --- || sleep 3600<br>boot || sleep 3600</pre><ul><li>The || sleep 3600 is a way to see what failed. Otherwise iPXE will yield control back to UEFI and we can’t debug much. This assume we have console access — not a bad idea to have until the process is known to work smoothly without console.</li></ul><p>A simple http-server can be started by running the following command on the folder having all files.</p><pre>python -m http.server 8999</pre><h4>Reboot the machine</h4><p>Now we can reboot the machine that needs to be reimaged. Once done, by way of grub setting, it will load the ipxe image. This will then auto-load the embedded boot.ipxe. The machine will get its ip over dhcp (some random ip). Then it will get boot-http.ipxe from the http-server. Then it will get the vmlinuz/initrd files and switch into that kernel. At this point, by way of kernel args, it will assign itself the IP that we had given and start booting the jammy live OS. Then by way of kernel-args it will start auto-installing ubuntu post the kernel boot-up. The autoinstall yaml contents are downloaded from the http-server. The auto-install file instructs the creation of a installer user with the choice of password/ssh-key and the early-commands simply holds the installation forever at the while..sleep loop. At this point, the machine is ready to be SSH’ed into. We can ssh into and then do whatever we want — which is to ddthe actual target image from a remote-machine.</p><pre>ssh remote-file-server &quot;cat /actualimage.gz&quot; | sudo gunzip -c | sudo dd of=/dev/sda bs=1M status=progress</pre><p>Once done, we reboot the machine, and we now reboot off the brand new image w/o using usb-sticks/console access!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1cf32aa2c615" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Copying to mac clipboard from linux]]></title>
            <link>https://medium.com/@lakshmankumar12/copying-to-mac-clipboard-from-linux-831aedc3c669?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/831aedc3c669</guid>
            <category><![CDATA[ssh]]></category>
            <category><![CDATA[mac]]></category>
            <category><![CDATA[clipboard]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Fri, 16 Nov 2018 23:59:26 GMT</pubDate>
            <atom:updated>2018-11-16T23:59:26.274Z</atom:updated>
            <content:encoded><![CDATA[<p>I use a MAC at work. Most of the time, my work is on a linux development server. I use iTerm and mosh into the linux-server.</p><p>Mac offers a cool pbcopy and pbaste command-line programs to exchange contents from/to clipboard right from command-line. This chains nicely with other unix tools using the standard stdin/stdout interface. For instance:</p><pre>pbpaste &gt; file.txt<br>ls -1 | pbcopy</pre><p>Pasting MAC’s clipboard into the server is trivial as doing a ⌘v in iTerm will paste the current clipboard’s contents where we are in, be it a terminal on the local mac or the remote machine if we are currently ssh’ed there. However, loading something from the server into the MAC’s clipboard isn’t easy without reaching for the mouse. Further we should have the content displayed on screen before we can select it in iTerm and slurp into the clipboard with a ⌘c. This is frustrating for huge multi-page content. Extending command line copying from the server relieves us from using the mouse, and removes the artificial limitation of having to keep the content on screen. I find it very handy when we need to say get some code-snippet or output of some command from the server and paste it in mac’s slack app, outlook or browser.</p><p>The trick is simple. Just ssh into the MAC from the linux-server and execute pbcopy, giving the contents to ssh as its stdin. In essence, do</p><pre>echo Whatever-needs-to-be-copied | ssh mac_user_name@MAC_IP pbcopy</pre><p>A few steps are in order to do this seamlessly, though.</p><ol><li>Setup the ssh-key-based login. Generate a ssh-rsa key-pair in the linux-server, and add the public key to the mac’s MAC-HOME/.ssh/authorized_keys. This way ssh gets non-interactive.</li><li>The main problem with ssh’ing back into mac from the linux-server is that the mac’s IP is ephemeral in nature. The MAC gets a different IP depending on its current locations — a wi-fi network, a wired-network, or in my home over VPN. This can be further complicated if the MAC is behind a firewall/NAT. The bottom line is that there is no well-known IP for the linux-server to SSH-into to reach MAC. To have a stable way of ssh’ing into the mac from the linux-server, no matter where the mac is, we use ssh’s tunneling option.</li></ol><p>Run this ssh command from MAC</p><pre>ssh -nNT -R 9222:localhost:22 my_linux_id@my_linux_server.myoffice.com &amp;</pre><p>The above command opens up a listener at localhost:9222 on the linux-server and forwards the packets to the MAC’s localhost:22. The -nNT options are useful for this tunnel-sake-only ssh. So, doing a</p><pre>ssh -p 9222 mac_user_name@localhost</pre><p>in the linux-server, ssh’s back into MAC. Voila! Needless to say, this will stop working once the ssh connection setup by the tunneling command is severed (happens when MAC moves out from a network, or if the MAC goes into standby..). We ust have to re-issue that command, usually when we find the clip-board isn’t working!</p><p>3. Have a bash function in the linux-server to enable copy-paste</p><pre>to_mac_clip () {<br>   toSet=$(cat) <br>   l=$(echo &quot;$toSet&quot; | wc -l) <br>   echo -n &quot;$toSet&quot; | ssh -p 9222 mac_user_name@localhost pbcopy<br>   if [[ $l -le 3 ]]<br>   then<br>      echo &quot;Your clip is setup with: $toSet&quot;<br>   else<br>      echo &quot;Your clip is setup with $l lines&quot;<br>   fi<br>}</pre><p>That’s it. Anytime, to copy to MAC form the linux-server, its now</p><pre>echo any-command-generating-output-to-stdout | to_mac_clip</pre><p>The same can be extended to work in vim too. Here is a vim-function and a key-map I use</p><pre>function! DumpToClipBoard()<br>  if s:uname == &quot;Darwin&quot;<br>    call system(&quot;pbcopy -pboard general&quot;, getreg(&quot;\&quot;&quot;))<br>  else<br>    call system(&quot;ssh -p 9222 mac_user_name@localhost pbcopy&quot;, getreg(&quot;\&quot;&quot;))<br>  endif<br>endfunction</pre><pre>vmap &lt;C-c&gt; y:call DumpToClipBoard()&lt;CR&gt;</pre><p>I usually visually select what I want and then do y. I now issue ctrl-cto copy to MAC’s clipboard, when needed. The above makes Vim first yank normally and then also push the contents of the default-register into the ssh-command, thereby bringing it to MAC’s clipboard.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=831aedc3c669" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Play/pause and Query Track-Info of music streaming from a Chrome Tab]]></title>
            <link>https://medium.com/@lakshmankumar12/play-pause-and-query-track-info-of-music-streaming-from-a-chrome-tab-d4a668215248?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/d4a668215248</guid>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Sat, 16 Dec 2017 01:23:15 GMT</pubDate>
            <atom:updated>2017-12-16T01:23:15.538Z</atom:updated>
            <content:encoded><![CDATA[<p>I am heavy keyboard user. Taking my hands off the home row (read:to hit arrow keys) is a major annoyance, and taking my hands off to mouse is just blasphemous. Given this disposition, I was looking for a way to global-hotkey play/pause the music that I listen on my macbook.</p><p>I usually listen from Google Play. For this, there is an awesome <a href="https://www.googleplaymusicdesktopplayer.com/">desktop-google-play music app</a> — that supports the media-play/pause key — so this is straight off the box (but having to move my hand off from home row to media key is still a sore).</p><p>Of late, I have started listening from <a href="https://www.pandora.com">Pandora.com</a>. This means, its a chrome tab that is streaming music. Chrome unfortunately doesn’t respond to the media-key by itself. There is a chrome extension, (probably others similar too) — <a href="https://chrome.google.com/webstore/detail/streamkeys/ekpipjofdicppbepocohdlgenahaneen?hl=en">stream-keys</a>, that helps to capture the media-play/pause key to stop/start music running from popular sites. I was using this for some time. However, it was becoming unresponsive frequently. Further, I wasn’t too happy with running yet another extension in the background in chrome. Manually switching to chrome, scan for the pandora tab, click it and pause/play the music wasn’t exactly fun. It is absolutely distracting and flow-breaking to to switch to a browser, especially a music streaming tab when we are deep into watching code/running tests in iTerm!</p><p>I was looking for alternatives — and came across <a href="https://gist.github.com/khrice/10143186">this awesome gist</a>, about using applescript to play/pause youtube. The script searches through all windows of chrome / all tabs of chrome and matches for the tab with the title - YouTube, grabs the Play/Pause button element using java-script and executes a click event on that element! Cool. This gist also suggests how to use Alfred to execute the script over a global-hotkey. I just replaced - YouTube with Pandora Radio for my use. Since I use <a href="https://qsapp.com/">quick-silver</a>, instead of Alfred, I just used quick-sliver to fire up this script on a global-hotkey (and one of my choice — not the distant a-mile-away media keys!). This works great so far.</p><p>I liked one another feature of Google-Play Desktop app — ability to know the current song that is playing, from my terminal. The google-play desktop app, exposes the currently playing track’s information in a playback.json file, and we just need to look there and print the content from there. This way, when I like a song that I am listening and I want to know its title/artist, I dont get distracted off my terminal window by looking into the web-page/album-arts of the current song, but just dump that in terminal. I wished a similar interface was possible for the Pandora-Radio in my chrome-tab as well.</p><p>Reading here and there with my meagre applescript and javascript knowledge, finally pulled off this:</p><pre>#!/bin/bash</pre><pre>result=$(osascript &lt;&lt;EOF<br>    tell application &quot;Google Chrome&quot;<br>        set songtitle to &quot;&quot;<br>        set songartist to &quot;&quot;<br>        set found_video to false<br>        set window_list to every window<br>        repeat with the_window in window_list<br>            if found_video is equal to true then<br>                exit repeat<br>            end if<br>            set tab_list to every tab in the_window<br>            repeat with the_tab in tab_list<br>                if the title of the_tab contains &quot;Pandora Radio&quot; then<br>                    tell the_tab<br>                    set songtitle to (execute javascript &quot;var outputtitle = document.querySelector(&#39;[data-qa=\&quot;mini_track_title\&quot;]&#39;).innerHTML; outputtitle;&quot;)<br>                    set songartist to (execute javascript &quot;var outputartist = document.querySelector(&#39;[data-qa=\&quot;mini_track_artist_name\&quot;]&#39;).innerHTML; outputartist;&quot;)<br>                    end tell<br>                    set found_video to true<br>                    exit repeat<br>                end if<br>            end repeat<br>        end repeat<br>    end tell<br>    return songtitle &amp; &quot;:&quot; &amp; songartist<br>EOF<br>)</pre><pre>if [ $? -ne 0 ] ; then<br>    echo &quot;Sorry, No cigar :(&quot;<br>else<br>    echo $result | awk -F: &#39; {print &quot;Song: &quot; $1 &quot;\nArtist: &quot; $2  } &#39;<br>fi</pre><p>So, now, I get to know the title/artist of the song that is playing on the browser, right in my terminal w/o taking eyes off iTerm!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d4a668215248" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Vim and key-mapping]]></title>
            <link>https://medium.com/@lakshmankumar12/vim-and-key-mapping-f02db3f88b58?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/f02db3f88b58</guid>
            <category><![CDATA[vim]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Thu, 23 Nov 2017 00:51:50 GMT</pubDate>
            <atom:updated>2017-11-23T00:52:32.206Z</atom:updated>
            <content:encoded><![CDATA[<p>For most of us, the first tryst with vi/vim, wouldn’t have been pleasant — as vim doesn’t offer the traditional ‘you get what you type’ interaction as most text-editors. We scrambled our way through a minimal command-set, mostly living by just i , &lt;Esc&gt;:w, &lt;Esc&gt;:q, and wondering why there isn’t a pleasant editor on the machine. Slowly, after reading about the modal nature of vim, things start to fall in place and we start grasping the editor’s working and the sudden weird behaviors start getting lesser.</p><p>As we mature, we start realizing the method in the madness — slowly appreciating, how most tasks build on some grammer and we soon realize the proliferation of options isn’t as unwiedly after all, and if we understand the pieces, we can leverage the whole is greater than the sum of parts philosophy with vim.</p><p>And eventually, we come across key-mappings in vim — a convenient way to remap some often repeated key-strokes into some shorter keys. So, we get hyper-excited about key mappings and go overboard with mapping most things with shorthands. And then comes the problems :)</p><ul><li>We realize that we masked some existing command with our creative mapping.</li><li>We get trained to our maps, but suddenly they no longer work in another person’s setup or another machine, which doesn’t have our vimrc files, and that is frustrating, especially looking clumsy in a colleague’s desk!</li></ul><p>As I was beset with those moments, I stumbled on this <a href="http://vimcasts.org/blog/2014/02/follow-my-leader/">vim-blog</a> and specifically on this article. It opened me to thinking anew towards vim-mappings. As mentioned here, the vim-keyscape is pretty saturated. At the outset, there appears hardly any room for new maps without trampling on some existing command. But upon looking through, there are some holes that we can mine. So, I decided, I will list the existing commands and identify the gaps, keep them ready so that I can use those whenever I need a map.</p><p>So, I prepared <a href="https://github.com/lakshmankumar12/vimfiles/blob/master/vim_notes.txt">this list</a> over time.</p><h4>Directly Mappable Hot-Keys</h4><p>Normal mode commands for each key are really hot — as they are the fastest to type. Over here, I saw that I can reclaim the lowercase s, upper-case Q,S and Z. The substitute(s) closely overlaps with change(c). s is a convenience for changing a single char with many chars, which I rarely used. Further its available with a cl, in case I needed that. Q goes to ex-mode. This was a long-term frustration for me. I would accidentally type Q, and wonder why vim suddenly came over to this ex-mode prompt. And it was a while till I realized, I could come out of it typing a :visual, without having to quit and restart! Finally, I realized, it was the accidental Q, that was causing all the trouble! S is a shorthand for changing current-line. Again, I rarely use that, and cc is a synonym. ZZ is a shorthand for close and exit — not something I do often. So, after listing down all the alphabets and symbols, I mined 4 hot-keys right away. I have mapped them to</p><ul><li>s -&gt; easy-motion-s2</li><li>S -&gt; easy-motion-s2</li><li>Q -&gt; close tab. I go crazy with tabs, especially with vim-fugitive, and need a way to close all those tabs having commits/diffs quickly.</li><li>Z -&gt; :lclose and :lopen location-list. The location window tends to go out of size, when we open new windows and this is a quick way to redraw it.</li></ul><h4>The g-key</h4><p>I realized that the g-key has some cute options — with what follows. So, this called for a listing on its own. I listed down all the g-&lt;&gt;commands. The following were revelations</p><ul><li>gd — goto local definition! I had been a c-programmer for so long, and didn’t know that vim has a simple gd out-of-box and we needn’t hop above with # !</li><li>g*/g# — searching current word without word-limiters, handy if we want to later use the / register for some purpose.</li><li>gJ — avoid that annoying space when joining lines!</li></ul><p>After listing down all the g-&lt;&gt; commands, there are quite some good holes here. My most used is gw&lt;&gt;. The original gw&lt;motion&gt; will format whatever gw&lt;motion&gt; covers. But I typically visually select my block and press gq. So, gw appeared redundant. I have mapped all window commands to this gw prefix (w for window!). Finally some relief to keep pressing ctrl-w and hurting my little finger.</p><p>The next big bang was using gx-&lt;&gt;. It has some netrw usage. But I don’t use netrw and use NERD-Tree plugin. So, i use gx as a cscope-prefix instead of the C-\. More rest to the little finger. gxx is mapped to C-tto unwind back the tag-list.</p><p>The next was gh-&lt;&gt;. ghis originally to enter select-mode. But who needs this mode anyway! So, gh-&lt;letters&gt; are mapped to various unite operations.</p><h4>Listing the various commands</h4><p>While I still have plenty of mapping-space with the above listing, I realized that I was vimming better by listing the keys in one place — so went ahead and listed the various ctrl- keys in normal mode, ctrl-keys in insert-mode, ctrl- keys in command mode. I found these which I didn’t know till then.</p><p>insert-mode ^-o : executes one command and comes back to insert mode. This is handy to move around in insert mode.</p><p>insert-mode ^-y/e: type contents of previous/next line. While we can do a yy/p or P and then change what we want, sometimes, if we are in insert mode, this is handy.</p><p>So, there, you can start from here and define your maps and relieve your fingers from typing less and hitting ctrl-keys even lesser.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f02db3f88b58" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Vim and Cscope]]></title>
            <link>https://medium.com/@lakshmankumar12/vim-and-cscope-5f4558c8a8b8?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/5f4558c8a8b8</guid>
            <category><![CDATA[cscope]]></category>
            <category><![CDATA[vim]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Sat, 12 Aug 2017 03:11:37 GMT</pubDate>
            <atom:updated>2017-08-12T03:11:37.512Z</atom:updated>
            <content:encoded><![CDATA[<p>Cscope is one of the essential tools in any vim-using-c-developer’s kit. There are 2 primary ways of using cscope. The first way, (I opine it the dumb way) is to invoke cscope first and then type the keyword in cscope’s interface, have it list all the match-results and then have cscope open vim at a desired result. Here cscope is the parent program and the editor is the child program. The second way is to invoke vim first and have the editor manage cscope in its background. This is powerful as we don’t lose our context in vim — cscope is just yet another way to jump/navigate across files, and all the registers/marks/jump-history/buffers is maintained intact by vim as we hop here and there.</p><p>The vanilla commands to interact with cscope are</p><pre>&quot; Let vim know about a cscope database<br>:cs add path/to/cscope.out relative/path/to/prepend/to/any/result</pre><pre>&quot; If cscope.out is in the cwd and cscope was build here too, then just<br>:cs add cscope.out</pre><pre>&quot;Invoke csocpe. goto definition of functionA<br>:cs find g functionA()</pre><p>Naturally, it is too tedius to type the :cs find … everytime, we need to lookup something. Not the vim way! There is a plugin <a href="https://github.com/vim-scripts/cscope_macros.vim">cscope_macros.vim</a> to solve just that. It adds the</p><pre>C-\ g|c|s|f|e</pre><p>key-maps to respectively do jump-to-definition/callers/all-references at the current keyword. And loads the cscope on startup automatically. This in itself is a great boost to productivity. I am hoping most readers are already doing this much.</p><p>One major pain point in this usage is when there are too many results. The normal vim-cscope behavior is to list all results interactively for us to choose with a number. If the result spans more than one screen, vim paginates the results. We skim over the current page, and if our result isn’t shown so far, we move to the next page. We can’t go back to the previous page (unless we are couched inside a tmux/screen window or use the terminal’s scroll-up). Further we painfully note down the number of the result and choose that number. This was largely how I was doing things till I realized vim has a nifty option to load the cscope results into the quick-fix window. Please refer to my <a href="https://medium.com/@lakshmankumar12/quickfix-and-location-list-in-vim-ca0292ac894d">previous post</a> if you aren’t familiar with quick-fix/location-list.</p><p>This behavior of showing the cscope results interactively or in a quick-fix list is controlled by the following setting</p><pre>:set cscopequickfix=s-,c-,d-,i-,t-,e-,a-<br>&quot; or in short:<br>:set csqf=...</pre><p>Each of the letters control the action for the respective cscope invocation. The +,-,0 after the letter controls whether the result should be added to an existing list(+) or replace the existing list(-) or 0(don’t use quick-fix and use the interactive option — the default). Absence of the letter in the csqf setting also implies 0. So, setting</p><pre>:set csqf=s-</pre><p>makes any cscope-s invocation list all its results in the quickfix. That’s it. There is one problem to this. Vim will automatically jump to the first result. When I initially came across this option in vim, I was excited. But this jumping immediately to the first result, kind of put me off over time, as it broke my flow, by jumping to arbitrary locations that happened to come up first in cscope’s list. So, I turned this off and went back to using the interactive way, until it struck me that I can fix this with a small vimscript. The idea is to mark the current location, set the cscope setting temporarily to load into location-list, invoke cscope, revert cscope setting and jump back to the saved location. This way, the default interactive behavior of cscope is intact which fits for go-to definitions, where results aren’t too many. When on demand, the cscope result can be loaded into location list — and cursor remains wherever we are.</p><pre>function! LoadCscopeToQuickFix(currword, oper)<br>  execute &quot;normal mZ&quot;<br>  execute &quot;set csqf=&quot; . a:oper . &quot;-&quot;<br>  execute &quot;lcs find &quot; a:oper . &quot; &quot; . a:currword<br>  execute &quot;lopen&quot;<br>  execute &quot;wincmd p&quot;<br>  execute &quot;normal `Z&quot;<br>  execute &quot;set csqf=&quot;<br>endfunction</pre><pre>nmap &lt;Leader&gt;css         &lt;Esc&gt;:call LoadCscopeToQuickFix(expand(&quot;&lt;cword&gt;&quot;),&quot;s&quot;)&lt;CR&gt;<br>nmap &lt;Leader&gt;csg         &lt;Esc&gt;:call LoadCscopeToQuickFix(expand(&quot;&lt;cword&gt;&quot;),&quot;g&quot;)&lt;CR&gt;<br>nmap &lt;Leader&gt;csc         &lt;Esc&gt;:call LoadCscopeToQuickFix(expand(&quot;&lt;cword&gt;&quot;),&quot;c&quot;)&lt;CR&gt;</pre><p>Here is a small <a href="https://asciinema.org/a/133041">screencast</a> of the above in operation.</p><h4>Bonus:</h4><p>I find the cscope’s listing of a C-keyword more useful than a simple grep, as it gives a contextual information — the function in which its present. This helps to quick look for information we need.</p><h4>Bonus-2:</h4><p>Use the plugin QFGrep to filter entries from quickfix/location-list.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5f4558c8a8b8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[To Buy or Rent]]></title>
            <link>https://medium.com/@lakshmankumar12/to-buy-or-rent-b060227fdfe4?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/b060227fdfe4</guid>
            <category><![CDATA[life-lessons]]></category>
            <category><![CDATA[compound-interest]]></category>
            <category><![CDATA[renting]]></category>
            <category><![CDATA[buying-a-home]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Fri, 21 Jul 2017 05:21:16 GMT</pubDate>
            <atom:updated>2017-07-21T05:21:16.637Z</atom:updated>
            <content:encoded><![CDATA[<p>My Friend introduced me to this <a href="https://www.nytimes.com/interactive/2014/upshot/buy-rent-calculator.html?abt=0002&amp;abg=0">web-page</a>, that compares the costs of buying vs renting. I have been always on the fence between the two. My friend is a strong proponent of the no-buying camp. Most people, I talk with, tend to gravitate on the buy-side. So, I threw at him the slew of questions which typically come from the buyers, like why pay rent which is just an expense. So, he showed me <a href="https://www.nytimes.com/interactive/2014/upshot/buy-rent-calculator.html?abt=0002&amp;abg=0">this awesome calculator</a> that considers in most of the influencing parameters towards deciding whether to buy or rent.</p><p>By far, this was the first time, I came across such a comprehensive analysis. Intuitively, while paying the interest part in a mortgage seems like a drain and this is typically more than the rent when a mortgage starts, as years roll by, the interest part diminishes and the rent keeps growing due to inflation. At this point, its not clear whether renting or buying is better.</p><p>I like the way the calculator approaches the comparison. While I wish I got access to the actual comparing code/logic, after reading the explanations on the page, I just came up with <a href="https://github.com/lakshmankumar12/rent_vs_buy">my implementation</a> of the same comparison. Mine is not as accurate, as feeding the same inputs gives a different result in mine vs the web page. Probably the actual tax calculations are a bit different. But anyway, my actual desire to (re)implement the calculation was to quickly try out variations on parameters and see how each has a say on the comparison, and manually feeding them on a web-page was turning out cumbersome.</p><p>So, here is a list of all factors that are taken in. I am also listing the default values I am assuming. These are baked into the script. We can override any explicitly.</p><ol><li>Home value ($750,000)</li><li>How long (30 Yrs)</li><li>Mortgage (4.0%)</li><li>Down Payment (10%)</li><li>Length of Mortgage (30 Yrs)</li><li>Home Price Appreciation (4.0%)</li><li>Rent Appreciation (4.5%)</li><li>Inflation Rate (3.0%)</li><li>Investment Rate (8.0%)</li><li>Prop Tax Rate (0.8%)</li><li>Joint/Single (Joint)</li><li>Marginal Tax Rate (25%)</li><li>Buying Expense (1.5%)</li><li>Selling Expense (6%)</li><li>Maintenance (1%)</li><li>Own Insurance (0.46%)</li><li>Common Monthly Expense (250)</li><li>Rental Deposit (I am leaving this off)</li><li>Broker Fees (I am leaving this off)</li><li>Rent Insurance (0.5%)</li></ol><p>For these values, the web-page shows $2199, while my calculation shows $2452. So, my understanding/calcuations err on the side of renting, while the web-site is towards buying. Anyway, even $2452 is not sufficient to rent any $750K house as of now in the bay-area, that I come across. So, overall, for these numbers, the tilt is towards buying. But, lets hold our horses, and study tweaking each parameter.</p><h4>1. Home Price Appreciation</h4><p>The most popular push to buying a new home is the fear that home price is getting costlier by the day. But my friends points to <a href="http://www.cnbc.com/2014/12/08/where-to-put-your-cash-a-house-or-a-stock.html">this article</a> that pegs the historical home price growth at much less than 4%. So, lets adjust this rate from 2 to 10. Anything above 6, renting doesn’t hold. But below 6, the case for buying isn’t that strong, especially if we tweak the other numbers too. (I pulled up the mortgage value to be same as price_appreciation). The numbers have a decent impact. For example at 3% to 5% the variation is ~$120.</p><pre>$ for i in $(seq 2.0 0.5 10.0) ; do rent=$(./calculate.py --price_appr $i --down_pay 100 -l 0); echo &quot;$i -- $rent&quot; ; done<br>2.0 -- 2269.20<br>2.5 -- 2322.98<br>3.0 -- 2372.38<br>3.5 -- 2416.01<br>4.0 -- 2452.31<br>4.5 -- 2479.46<br>5.0 -- 2495.37<br>5.5 -- 2497.67<br>6.0 -- 2483.64<br>6.5 -- 2450.18<br>7.0 -- 2393.76<br>7.5 -- 2310.35<br>8.0 -- 2195.37<br>8.5 -- 2043.62<br>9.0 -- 1849.19<br>9.5 -- 1605.36<br>10.0 -- 1304.49</pre><h4>2. Mortgage rates</h4><p>Naturally, more the mortgate rate, the worser is the buying decision. While 4% is our default, an 1% increase here strongly bumps up the break-even rent by $180!</p><pre>$ for i in $(seq 2.0 0.5 10.0) ; do rent=$(./calculate.py --mort_per $i -l 0); echo &quot;$i -- $rent&quot; ; done<br>2.0 -- 2126.19<br>2.5 -- 2203.34<br>3.0 -- 2283.46<br>3.5 -- 2366.48<br>4.0 -- 2452.31<br>4.5 -- 2540.87<br>5.0 -- 2632.04<br>5.5 -- 2725.73<br>6.0 -- 2821.82<br>6.5 -- 2920.20<br>7.0 -- 3020.75<br>7.5 -- 3123.34<br>8.0 -- 3227.87<br>8.5 -- 3334.21<br>9.0 -- 3442.24<br>9.5 -- 3551.86<br>10.0 -- 3662.94</pre><h4>3. Investment rate</h4><p>Investment rate has to meaningfully hold above 8% to makes any sense. But every percent increase, greatly tilts on renting. Anyway, I dont think, we should assume anything beyond 9% for especially long terms like 30+ years.</p><pre>$ for i in $(seq 5.0 0.5 10.0) ; do rent=$(./calculate.py --inv_rate $i -l 0); echo &quot;$i -- $rent&quot; ; done<br>5.0 -- 1636.67<br>5.5 -- 1786.58<br>6.0 -- 1930.75<br>6.5 -- 2069.28<br>7.0 -- 2202.29<br>7.5 -- 2329.92<br>8.0 -- 2452.31<br>8.5 -- 2569.62<br>9.0 -- 2682.01<br>9.5 -- 2789.66<br>10.0 -- 2892.73</pre><h4>4. House price</h4><p>This is tricky. Does increasing home price have any effect? So, we will also print how many rents it take to cover up the home-price. It looks like as home-values increase, it looks like buying is better as the break-even rent keeps coming down.</p><pre>$ for i in $(seq 100000 50000 1000000) ; do rent=$(./calculate.py --home_val $i -l 0); rent_price_ratio=$(python -c &quot;r=($i/$rent);print r&quot;); echo &quot;$i -- $rent -- $rent_price_ratio&quot; ; done<br>100000 -- 563.37 -- 177.503239434<br>150000 -- 741.34 -- 202.336309925<br>200000 -- 914.05 -- 218.806411028<br>250000 -- 1054.88 -- 236.993781283<br>300000 -- 1194.63 -- 251.123778911<br>350000 -- 1334.37 -- 262.29606481<br>400000 -- 1474.11 -- 271.350170611<br>450000 -- 1613.85 -- 278.836323078<br>500000 -- 1753.60 -- 285.127737226<br>550000 -- 1893.34 -- 290.491934888<br>600000 -- 2033.08 -- 295.118736105<br>650000 -- 2172.83 -- 299.14903605<br>700000 -- 2312.57 -- 302.693540087<br>750000 -- 2452.31 -- 305.834091122<br>800000 -- 2592.05 -- 308.636021682<br>850000 -- 2731.80 -- 311.150157405<br>900000 -- 2871.54 -- 313.420673228<br>950000 -- 3011.28 -- 315.480460137<br>1000000 -- 3151.03 -- 317.356546907</pre><h4>5. Duration of holding the house</h4><p>The best time seem to be somewhere in the 16 Year’ish — perhaps because of the tax benefits that dip after that. But otherwise, the tenure doesn’t seem to hold much.</p><pre>$ for i in $(seq 4 4 100) ; do rent=$(./calculate.py --how_long $i -l 0); echo &quot;$i -- $rent&quot; ; done<br>4 -- 2631.93<br>8 -- 2264.25<br>12 -- 2232.43<br>16 -- 2272.13<br>20 -- 2330.52<br>24 -- 2384.35<br>28 -- 2431.42<br>32 -- 2498.54<br>36 -- 2565.80<br>40 -- 2609.67<br>44 -- 2638.16<br>48 -- 2656.35<br>52 -- 2667.55<br>56 -- 2673.95<br>60 -- 2677.07<br>64 -- 2677.95<br>68 -- 2677.30<br>72 -- 2675.64<br>76 -- 2673.34<br>80 -- 2670.64<br>84 -- 2667.73<br>88 -- 2664.75<br>92 -- 2661.77<br>96 -- 2658.87<br>100 -- 2656.07</pre><h4>6. DownPayment</h4><p>Interestingly, I was wondering the case, where we buy the house outright w/o mortgage. Guess, what it costs $3727 vs the $2452! So, it makes sense to mortgage, espeically when we can invest money in hand in stock-market and not pre-pay anything! Thank you tax-exemptions.</p><pre>$ for i in $(seq 10 10 100) ; do rent=$(./calculate.py --down_pay $i -l 0); echo &quot;$i -- $rent&quot; ; done<br>10 -- 2452.31<br>20 -- 2599.03<br>30 -- 2745.74<br>40 -- 2892.45<br>50 -- 3039.17<br>60 -- 3185.88<br>70 -- 3332.60<br>80 -- 3479.31<br>90 -- 3618.21<br>100 -- 3727.20</pre><h4>7. Common Monthly Expenses</h4><p>There are the community charges etc.. that we need to pay. This has the highest say — as it almost translates directly to rent.</p><pre>$ for i in $(seq 0 100 1000) ; do rent=$(./calculate.py --month_comm $i -l 0); echo &quot;$i -- $rent&quot; ; done<br>0 -- 2244.87<br>100 -- 2327.85<br>200 -- 2410.82<br>300 -- 2493.80<br>400 -- 2576.78<br>500 -- 2659.75<br>600 -- 2742.73<br>700 -- 2825.70<br>800 -- 2908.68<br>900 -- 2991.65<br>1000 -- 3074.63</pre><p>Just avoid houses with these charges :) A better deal would be to chose a costlier house without it. For example, its almost same in break-even rent (~$2450)to choose a home at $825K with no monthly charges to a house of $750K with a $250 monthly charge.</p><h4>8. Property Taxes</h4><p>Again, more the taxes, more the loss (No, tax exemptions dont mean much)</p><pre>$ for i in $(seq 0.5 0.1 1.5) ; do rent=$(./calculate.py --prop_tax $i -l 0); echo &quot;$i -- $rent&quot; ; done<br>0.5 -- 2320.78<br>0.6 -- 2364.63<br>0.7 -- 2408.47<br>0.8 -- 2452.31<br>0.9 -- 2496.16<br>1.0 -- 2540.00<br>1.1 -- 2583.84<br>1.2 -- 2627.69<br>1.3 -- 2671.53<br>1.4 -- 2715.37<br>1.5 -- 2759.22</pre><h4>9. Other parameters</h4><p>There are hardly any change in the following. So, I am not tweaking this. Maintenance might be more or less. Since we are accounting compounded maintenance, I guess, the 1% assumption fairly evens out this expense.</p><ul><li>Joint/Single, assumed joint</li><li>Marginal Tax Rate (25%)</li><li>Maintenance (1%)</li><li>Own Insurance (0.46%)</li><li>Rent Insurance (0.5%)</li></ul><p>These parameters dont make much impact.</p><ul><li>Buying Expense (1.5%)</li><li>Selling Expense( 6%)</li></ul><h3>BottomLine</h3><p>One thing I realize is, depending on our assumptions on the 3 big-ticket items — Home-value appreciation, Rent appreciation and Investment Returns, our decision will change. None of them are easy to arrive it. While there are the broad indices and past-performances, the exact house we look at or the investment we make, might differ from these broad averages. I ball-park the values at 4,4,9. So, I tend to decide towards renting. This is further emboldened by the fact that I don’t have money anyway to pay for a downpayment!</p><p>The biggest take-away for me over this exercise is that, neither buying or renting, is unquestionably better than the other. While we may not have to shy away from buying altogether, we needn’t think buying is the must-to-do thing either. The house price/rent-appreciation are definitely not as high as investment-returns. So, participating in competitive bids to just buy a house early in our career, is totally unnecessary — renting is not loss of money, and house prices and rents aren’t beating general inflation as much as investment-returns.</p><p>Further, while we buy, we typically over-shoot for a slightly bigger house than we would otherwise rent. Also we tend to pick on considerations that have temporal needs, like proximity to work or school-districts, which we can move away from, in case of renting.</p><p>Happy renting, buying or well, deciding :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b060227fdfe4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[QuickFix and Location list in vim]]></title>
            <link>https://medium.com/@lakshmankumar12/quickfix-and-location-list-in-vim-ca0292ac894d?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/ca0292ac894d</guid>
            <category><![CDATA[vim]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Fri, 14 Jul 2017 22:11:05 GMT</pubDate>
            <atom:updated>2017-08-12T03:12:13.762Z</atom:updated>
            <content:encoded><![CDATA[<p>Quickfix is a convenient way to load and navigate compilation errors/warnings. I prepared a <a href="https://asciinema.org/a/128941">screen-cast</a> illustrating quick-fix in Vim. You can skip this if you already are familiar with the following vim commands.</p><pre>&quot;The window opened by vim on these commands is called the QuickFix<br>:copen<br>:cnext<br>:cprev<br>:cc<br>:cf &lt;file&gt;<br>:cclose</pre><p>In addition to quickly moving around compile-results, we can load grep results in vim and move around with exactly the same commands. If we think about it, both compilation errors and grep results have similar patterns. Each entry has a file-name, line-number to go to and a string to watch out for — the error message in case of a compilation-result or the line itself in case of grep. To open a grep result in quick-fix:</p><pre>&quot;This will invoke an external grep<br>:grep pattern</pre><pre>&quot;Or you can do grep externally in a terminal and collect <br>&quot;its result in a file.<br>&quot;Ensure to do grep -nH to get filename and line numbers<br>:cfile file_having_grep_results</pre><pre>&quot;Note that vim jumps to first result right on :cf. <br>&quot;To view the results<br>:copen</pre><h3>Location List Vs QuickFix</h3><p>QuickFix window is global to one vim-session. If we have lots of windows, they all share the same quick-fix. If we are wading over compilation errors, one global quickfix window is sufficient — as we compile per project and there aren’t typically different compilation error lists. However once we start using grep, we soon run into not wanting to disturb the grep results loaded in one window and still do another grep in another window. In such cases, we can use the location list. The location list is exactly same as quickfix, just that its private to each window! The commands for the location list are very similar. Just substitute l instead of c.</p><pre>:copen      :lopen<br>:cnext      :lnext<br>:cprev      :prev<br>:cc         :ll<br>:cf &lt;file&gt;  :lf &lt;file&gt;</pre><p>In fact, we dont have to grep separately in a terminal, but rather grep from within vim. There are some nice plugins that grep every efficiently in source-repositories. I use <a href="https://github.com/Numkil/ag.nvim">Ag.nvim</a>. One very common usecase for me is to grep in the current file quickly. Vim offers that out-of-box without any plugin. Sometimes, its convenient to view all results right in one place, instead of having to hop over with n’s.</p><pre>&quot;Load into quickfix. vimgrep is vim itself doing a grep, <br>&quot;  instead of using a external grep<br>&quot;This is okay in our case, as the current file is already a <br>&quot;  buffer in vim&#39;s memory<br>:vimgrep /pattern/ %</pre><pre>&quot;Or if we want in location window<br>:lvimgrep /pattern/ %</pre><p>As is common to any vim work-flow, the sum is greater than parts. Note that the quick-fix and location-lists are almost vim-windows on their own right. So we can vim-around(eg, yank or search/highlight text) within the results in the quick-fix/location-list! After using it for sometime, we eventually want to grep within the grepped-items, as we start from a broader to narrower search. To this effect, there is a nice plugin — <a href="https://github.com/sk1418/QFGrep">QFGrep</a>, which further filters items on quickfix! (The quickfix is non-modifiable buffer, so a simple v/pattern/d wont work here. This plugin kind of does just that!)</p><p>Here is a <a href="https://asciinema.org/a/129042">screencast</a> illustrating, lvimgrep/QFGrep in action.</p><p>In a <a href="https://medium.com/@lakshmankumar12/vim-and-cscope-5f4558c8a8b8">subsequent blog</a>, I will show, how cscope can be combined with this QuickFix/Location-List for efficient code-browsing.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ca0292ac894d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Two+ months of mac’ing :)]]></title>
            <link>https://medium.com/@lakshmankumar12/two-months-of-macing-b71200edb498?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/b71200edb498</guid>
            <category><![CDATA[autohotkey]]></category>
            <category><![CDATA[mac]]></category>
            <category><![CDATA[windows]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Fri, 07 Jul 2017 23:34:05 GMT</pubDate>
            <atom:updated>2017-07-07T23:34:05.068Z</atom:updated>
            <content:encoded><![CDATA[<p>I am pretty late into using a mac. I once had the chance to change to get a mac at work some 5 years back, but stuck with windows as I had a nice 2 monitor setup with a docking station, which I had to relinquish if I changed to mac as my office didn’t provide docking stations for mac. I finally got to shift to mac about two months back.</p><p>I knew mac is popular with the developer community for its swiftness and coolness and was wondering how I would get on with it. I am a very keyboard shortcut’y person and spend most of work in a terminal. I was using auto-hotkey enriched with an application-key-turned-capslock setup, as suggested in <a href="http://duartes.org/gustavo/blog/post/home-row-computing/">this blog</a>, and would do most mouse’y stuff like scrolling, accessing context-menu, from my home-row position, and was wondering If I can live by with same keyboard speeds on the mac.</p><p>After two months of using mac, I am totally in love with it. I thought I will share a summary of how I find it so far.</p><h3>AWESOME in mac</h3><ul><li>weight of the laptop</li></ul><p>Honestly, this is nothing to do with mac per-se. But, all windows laptops I used/owned before were heavy bricks — so, mac is my first feather-weight machine.</p><ul><li>Screen Resolution</li></ul><p>Again, not exactly mac’y and there are good resolution windows machines. But, (I have a 4K monitor driven by windows-10 laptop), the ease with which Mac adjusts to the high resolution display truly tops. In windows, now and then, I will have to rescale/adjust apps. Not sure about the native high-resolution screen laptops though.</p><ul><li>Speed with which its ready to work on — both sleep/boot</li></ul><p>The feature that windows can never come close. Chromebooks are on par though ;) In fact, in my windows laptop, I still can’t figure out, why the Dell-bios-like screen splashes sometimes for seconds on wakeup and sometimes doesn’t.</p><ul><li>its full-screen mode, exactly how I want it. We still get system notifications popped up and when we hover mouse up, we get access to the application menu and system status icons, instead of having to exit full-screen first!</li><li>terminal is a first class citizen, unlike in windows, where I use a terminal off a virtual-box’ed linux!</li><li>iterm integration with opening files by “open”.</li></ul><h4>Awesome, but I don’t really use that much</h4><ul><li>mouse gestures</li><li>The splash screen of all apps on 3-finger-scroll or ctrl-up. I have hotkeys for all apps I frequently use. But once in a while, I do use this to get stock of my desktop.</li></ul><h4>small cute things in mac</h4><ul><li>native ability to map caplock (I mapped to command)</li><li>native ability to O(1) switch to another app by typing its name — spotlight. I although have changed to quick-silver. Further, typing the app, just opens the running instance, instead of spawning a new one, like the win-r run window in windows!</li><li>I used work-rave in windows, to remind me of breaks. At its timer, it would just grab keyboard focus, spoiling what I am typing [perhaps intended :) ]. I now use time-out in mac, which gracefully dims up the screen w/o grabbing keyboard/mouse strokes.</li><li>Amphetamine (switched to this after using caffeine for some time), which allows to not sleep. Very handy, when I am on discussions/meetings.</li></ul><h3>Bummers in that order:</h3><ul><li>Outlook has no format painter! [ :( ] Yikes!</li><li>Auto-hotkey stuff (karabiner seems unavailable in mac-os sierra, that is suggested as alternative). I basically just need scrollup/down, and hjkl map for arrow-keys which I am so used to, in windows.</li></ul><h3>Other minor inconveniences:</h3><ul><li>I would like to change the lock-up screen from the blurred image to a proper image — com.apple.desktop.admin.png <a href="https://www.howtogeek.com/howto/29503/how-to-change-the-logon-background-in-os-x/">solution</a> keeps reverting after some time!</li><li><a href="https://apple.stackexchange.com/questions/119699/how-to-make-right-click-using-keyboard">Absence of a application-key that emulates a right click at a location</a>.</li><li>Having to unlearn and relearn key-sequences. Especially frustrating is typing end-key hoping cursor to come to end of line, but finding it going to end of page. And having to painstaking come back to the current line, when on web-forms. And word-jumping is alt-arrow and not ctrl-arrow.</li></ul><h3>Issues that were bothering me, but found a way out.</h3><ul><li>mission control should have a way to keyboard-select app of choice.<br> — Just use spotlight/quick-silver.</li><li>Hotkey to open up apps. I was doing it the apple-script/services way. Hotkey to lock too has same flaky behavior<br> — Quicksilver’s trigger is now how I assign global-hotkeys to apps.</li><li>How to auto adjust font-size for iTerm based on display?<br> — I am just manually cmd- +/-’ing on demand.</li><li>how to move all windows to another display in dual monitor case, when i haven’t closed my mac-lid<br> — spectacle.app solved this by offering the shortcut to move windows across monitors, although one by one, which is good enough, as long as I don’t have to reach for the mouse.</li><li>zoom/maximize sometimes only vertically maximizes (eg: iTerm, chrome!, no option/shift/command click doesn’t work either)<br> — I found spectacle.app, which does the job now (and with a keyboard shortcut too!)</li><li>Shut display of mac with a second monitor, with mac lid open<br> — Still can’t. But since I found spectacle.app, I don’t mind keeping mac open and having a few windows there.</li><li>One thing I realized after coming out of windows, is how handy the windows calendar is, to pop up from system-tray! Fortunately mac has a itsyscal app that does this.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b71200edb498" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[c++ source code browsing in vim]]></title>
            <link>https://medium.com/@lakshmankumar12/c-source-code-browsing-in-vim-d0afee82b688?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/d0afee82b688</guid>
            <category><![CDATA[clang]]></category>
            <category><![CDATA[vim]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[cpp]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Thu, 06 Jul 2017 02:08:24 GMT</pubDate>
            <atom:updated>2017-07-06T02:08:24.381Z</atom:updated>
            <content:encoded><![CDATA[<p>Buoyed with success of <a href="https://medium.com/@lakshmankumar12/docker-saves-the-day-25db8e8e36e2">installing mosh</a> on my non-root archaic 6.5-centos, I set out to install the clang compiler and the allied modern CXX tools. I wanted a decent auto-completer and go-to-definition jumper. cscope and omni-complete with ctags, are okay, but anyone who uses them would tell, they fall short pretty poorly for C++. Even for c-code, cscope can’t go to definition of struct-member. For instance, say in the following line, when we do a cs find g &quot;&lt;cword&gt;”, keeping cursor on memberC, cscope would just bail out.</p><pre>ptr_typeA-&gt;memberBptr-&gt;memberC;</pre><p>To complicate things, member names like id, for example, can be used across many structures and doing a grep or even (cscope find s) on such identifiers will throw gazillion results. To correctly go to definition on such instances or list all references, we need a compiler-class source code browsing, and cscope isn’t that. I am not very familiar with clang and its internals, but clang offers more than just compilation — it emits source-code information so that the above is possible.</p><p>After some reading and experimentation here and there, I finally found the following working well for me</p><p>1. <a href="https://github.com/zchee/deoplete-clang">Deoplete-clang</a>, for code-completion<br>2. <a href="https://github.com/Andersbakken/rtags">rtags</a>, for code-browsing. rtags was primarily developed for emacs, but a <a href="https://github.com/lyuts/vim-rtags">vim-frontend</a> is available!</p><p>Both of them are dependent on clang. The <a href="https://www.vultr.com/docs/how-to-install-llvm-and-clang-on-centos-6">following site</a> has excellent steps to build clang. clang in turn requires a modern gcc. With the dockered centos, I was able to follow the instructions to the dot and get clang compiled. The results were available in /usr/local/ of the container. I just tar-balled the entire /usr/local and scp’ed it to my dev machine’s $HOME/install/clang folder and untarred there. The $HOME/install/clang/lib/libclang.so had all its dependencies met. In fact, the binaries in $HOME/install/clang/bin too had no trouble finding the libraries from the nearby lib folder. Hurray!</p><p>Both the deoplete-clang and vim-rtags plugin had options to point to the clang library, rc executables via vimrc variables. I updated my PATH and LD_LIBRARY_PATH to pick the clang and other executables. And fortunately rtags has a cute option of wrapping gcc to generate the clang-compilations and that just worked.</p><p>And presto!, my code-completion and source-code browsing is now at a new-level :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d0afee82b688" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Docker saves the day!]]></title>
            <link>https://medium.com/@lakshmankumar12/docker-saves-the-day-25db8e8e36e2?source=rss-1836b4937c96------2</link>
            <guid isPermaLink="false">https://medium.com/p/25db8e8e36e2</guid>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[centos]]></category>
            <category><![CDATA[mosh]]></category>
            <dc:creator><![CDATA[lakshman kumar]]></dc:creator>
            <pubDate>Thu, 29 Jun 2017 18:59:52 GMT</pubDate>
            <atom:updated>2017-06-29T19:01:22.185Z</atom:updated>
            <content:encoded><![CDATA[<p>I have a development machine, which is where I do all my work. Unfortunately there is no root permission for me here, which means, doing any yum install anything is ruled out. Its a centos 6.5 machine. Centos 6.5 is pretty archaic. mosh wasn’t already available here. So, the only option seemed to be installing from source, with a installation prefix set to somewhere inside my home location.</p><p>I thought it would be just doing a</p><pre>wget …mosh..<br>tar xf mosh..tar..z<br>./configure — prefix=$HOME/install<br>make<br>make instal</pre><p>Unfortunately, mosh requires the following development packages:<br>1. perl<br>2. protocol buffers<br>3. ncurses<br>4. zlib<br>5. open-ssl</p><p>Each of them in turn kept depending on something else, and pretty soon, I lost track of what I am compiling, the CXXFLAGS/LD_LIBRARY_PATH I seem to be setting and installing. I just gave up after something complained that the gcc version I had in my machine is too old. I had almost given up on using mosh in my office setup, until I realized I can try installing mosh in a docker centos and finally cp’ing the results back to my machine.</p><p>So, went to docker repository and then realized, even docker doesn’t have a centos 6.5 image and starts only with centos 6.6. Hrmm. Anyway, trusted my luck with centos 6.6 and sure enough, with root powers, quickly yum installed most dependencies. I had to compile-from-source just the proto-buf library and then mosh. Mosh finally compiled and mosh seems to depend on these libraries:</p><pre>[root@31837a315921 sourceInstallations]# ldd mosh_build/bin/mosh-client<br> linux-vdso.so.1 =&gt; (0x00007fff397e6000)<br> libtinfo.so.5 =&gt; /lib64/libtinfo.so.5 (0x00007fb47eac5000)<br> libprotobuf.so.12 =&gt; /usr/local/lib/libprotobuf.so.12 (0x00007fb47e688000)<br> libssl.so.10 =&gt; /usr/lib64/libssl.so.10 (0x00007fb47e41c000)<br> libcrypto.so.10 =&gt; /usr/lib64/libcrypto.so.10 (0x00007fb47e037000)<br> librt.so.1 =&gt; /lib64/librt.so.1 (0x00007fb47de2e000)<br> libz.so.1 =&gt; /lib64/libz.so.1 (0x00007fb47dc18000)<br> libstdc++.so.6 =&gt; /usr/local/lib64/libstdc++.so.6 (0x00007fb47d88b000)<br> libm.so.6 =&gt; /lib64/libm.so.6 (0x00007fb47d606000)<br> libgcc_s.so.1 =&gt; /usr/local/lib64/libgcc_s.so.1 (0x00007fb47d3f0000)<br> libc.so.6 =&gt; /lib64/libc.so.6 (0x00007fb47d05c000)<br> libpthread.so.0 =&gt; /lib64/libpthread.so.0 (0x00007fb47ce3e000)<br> /lib64/ld-linux-x86–64.so.2 (0x000055ab177b4000)<br> libgssapi_krb5.so.2 =&gt; /lib64/libgssapi_krb5.so.2 (0x00007fb47cbfa000)<br> libkrb5.so.3 =&gt; /lib64/libkrb5.so.3 (0x00007fb47c913000)<br> libcom_err.so.2 =&gt; /lib64/libcom_err.so.2 (0x00007fb47c70e000)<br> libk5crypto.so.3 =&gt; /lib64/libk5crypto.so.3 (0x00007fb47c4e2000)<br> libdl.so.2 =&gt; /lib64/libdl.so.2 (0x00007fb47c2de000)<br> libkrb5support.so.0 =&gt; /lib64/libkrb5support.so.0 (0x00007fb47c0d2000)<br> libkeyutils.so.1 =&gt; /lib64/libkeyutils.so.1 (0x00007fb47becf000)<br> libresolv.so.2 =&gt; /lib64/libresolv.so.2 (0x00007fb47bcb5000)<br> libselinux.so.1 =&gt; /lib64/libselinux.so.1 (0x00007fb47ba95000)<br></pre><p>I decided I will start with just cp’ing the mosh binaries alone and then cp the dependent so-files one by one. Fortunately, most libraries were there in my development machine (so, much for all the missing dev-pkg dependencies to compile!), except for the protobuf. Once I cp’ed the libprotobuf.so.12 and set up LD_LIBRARY_PATH in my bashrc to its location, voila!, mosh just worked.</p><p>Yippee! Thanks Docker.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=25db8e8e36e2" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>