Applied for VimConf 2018 talk

I’m a co-organizer of VimConf 2018, and also trying to make my Vim talk proposal to pass.

VimConf 2018 CFP (call for proposals)

Here’s my CFP for your info.


Title: Modes

Abstract (to be displayed): Discover what is happening internally when you switch modes, such as insert mode, normal mode, and operator-pending mode. This talk first revisits how modes are when you use Vim, then I’ll let you dive into the Vim C implementation to see what’s exactly happening there. I’ll even show what modifications can be done when you make change, with using existing pull requests.

This talk is both for Vim beginners and advanced users who don’t always look at the Vim C implementation.

Self promotion for reviewers (not to be displayed): secret. it was very long


I’m looking forward to seeing Bram, the author of Vim, and all other speeches. See you there, people who go to VimConf 2018 this year!

Advertisements

How to use GDB to debug Vim itself

There are many web pages about how to integrate GDB with Vim to debug a program. This blog post is not about that but about how to debug Vim itself with GDB which is not necessarily integrated with Vim.

1. Build Vim with debug_info, not stripped

  1. Download Vim. Just git clone from https://github.com/vim/vim
    • I use ~/git/vim for working directory
  2. After configure, manually edit src/Makefile (see patch below)
  3. :terminal make -C src reconfig clean all install
diff --git a/src/Makefile b/src/Makefile
index f2fafa4dc..8b41d0648 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -591,7 +591,7 @@ CClink = $(CC)
 # When using -g with some older versions of Linux you might get a
 # statically linked executable.
 # When not defined, configure will try to use -O2 -g for gcc and -O for cc.
-#CFLAGS = -g
+CFLAGS = -g
 #CFLAGS = -O

 # Optimization limits - depends on the compiler.  Automatic check in configure
@@ -1006,6 +1006,7 @@ TOOLS = xxd/xxd$(EXEEXT)
 #
 # Uncomment the next line to install Vim in your home directory.
 #prefix = $(HOME)
+prefix = $(HOME)/git/vim/local

 ### exec_prefix	is the top directory for the executable (default $(prefix))
 #
@@ -1156,7 +1157,7 @@ INSTALL_DATA_R	= cp -r

 ### Program to run on installed binary.  Use the second one to disable strip.
 #STRIP = strip
-#STRIP = /bin/true
+STRIP = /bin/true

 ### Permissions for binaries  {{{1
 BINMOD = 755

The prefix part is just for myself. You don’t have to include. But this frees installation process from sudo.

2. Use GDB

That’s pretty much it.

$ gdb ~/git/vim/local/bin/vim -q --tui

Here’s my demo.

In this demo I used

  • start (to pass Vim’s command line options)
  • break to set breakpoints
  • c as continue
  • n as next

“Vim” and “Debug”?

These 2 words imply one of them.

  • Use Vim to debug an arbitrary program with GDB/LLDB/other famous debugging tools
    • e.g.
    • e.g. Vim’s standard plugin Termdebug
  • Use Vim to debug a Vim script program (with :breakadd and :debug)
  • Use GDB/LLDB/other famous debugging tools to debug Vim
    • This blog post!

Note that the above are completely orthogonal.

  • Integrate Vim and GDB/LLDB/other famous debugging tools to debug Vim
    • It’s now trivial. You can just combine the 2 of 3 above

Implement :|┃ in Ruby

:|┃

A tech talk at Tokyu RubyKaigi 12, featuring how to implement musical repeat sign :|┃ in Ruby, using continuation (callcc) which is a killer feature of Ruby.

repeat

# this is a pseudo code
puts 'step 1'
:|┃
puts 'step 2'

If it’s a music score this repeats the first line. Here let’s redefine the repeat sign to repeat forever instead of once. This is nontrivial to provide infinite loop version from finite repeat, but it’s trivial to provide finite repeat with using intinite loop right?

output:
  step 1
  step 1
  step 1
  step 1
  ... (continues forever)

I found one of the possible ways. I’m sure there would be better ways though.

# a.rb
require 'continuation'

class String
  def |(x)
    x.()
  end
end

def ┃
  -> { $c.call($c) }
end

class Proc
  def |(_)
    $c = callcc {|c| c }
  end
end
$c ||= callcc {|c| c }

and its usage:

require 'a'

puts 'before'
%: :|┃
puts 'after'

This repeats the first line forever.

Let’s look at this part carefully.

%: :|┃

%: : is equivalent to a string with a single space " ". | is an operator which means it’s just a method String#| with single argument.
The argument is a unicode character , which is either a local variable or a method. In this case it’s Object#┃ defined in a.rb.
This lets runtime goes back to the line in a.rb

$c ||= callcc {|c| c }

Note that this feature requires Ruby’s continuation. Without callcc, this feature is impossible to implement.

┃|:

You can also specify where to repeat from with using ┃|:

require 'a'

puts 'first'
┃|:"start\n".display
puts 'before'
%: :|┃
p 'after
# output:
  first
  start
  before
  before
  before
  before
  before
  ... (continues forever)

This also requires continuation.

Recent activities

I’ve been focusing on cooking variety of Japanese local fish.

https://platform.twitter.com/widgets.js

https://platform.twitter.com/widgets.js

https://platform.twitter.com/widgets.js

https://platform.twitter.com/widgets.js

https://platform.twitter.com/widgets.js

https://platform.twitter.com/widgets.js

https://platform.twitter.com/widgets.js

https://platform.twitter.com/widgets.js

https://platform.twitter.com/widgets.js

I feel confident making sashimi with most of fish available here, as an amateur chef. Definitely not a professional level, but at least I can constantly make edible ones.

Things I learned that I didn’t expect at first here

  • Aging fish for sashimi enhances umami
  • Fish actually lasts longer than it sounds like, as long as you pre-process properly. This is pretty handy
  • Making sushi and making sashimi require completely different skill set
  • Good fish is guaranteed to be delicious. Bad fish is impossible to eat no matter what you do.

How to use Vital.Async.Promise

Couple months ago, on the new year’s day 2018-01-01, Dog a.k.a. linda_pp or rhysd created a vital.vim module Async.Promise.

INTRODUCTION Vital.Async.Promise-introduction

Vital.Async.Promise is a library to represent the eventual completion or
failure of an asynchronous operation. APIs are aligned to ES6 Promise. If you
already know them, you can start to use this library easily.

Instead of callbacks, Promise provides:

  • a guarantee that all operations are asynchronous. Functions given to .then()
    method or .catch() method is executed on next tick (or later) using
    |timer_start()|.
  • chaining asynchronous operations. Chained operation’s order is sequentially
    run and the order is guaranteed.
  • persistent error handling using .catch() method. Please be careful of
    floating Promise. All Promise should have .catch() call not to squash an
    exception.
  • flow control such as awaiting all Promise objects completed or selecting
    the fastest one of Promises objects.

If you know the detail of APIs, documents for ES6 Promise at Mozilla Developer
Network and ECMA-262 specs would be great.

Mozilla Developer Network:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

ECMA-262:
https://www.ecma-international.org/publications/standards/Ecma-262.htm

https://github.com/vim-jp/vital.vim/blob/master/doc/vital/Async/Promise.txt

As the introduction mentioned, it is an ES6 Promise compatible interface for Vim scripts. You can use it as a fully controllable abstract layer on lowest layer Vim functions job_start/timer_start or vimproc.vim for your plugin developments.

Trivial example: echo message after a while

Let’s implement something like this without blocking Vim.

sleep 5 " This is blocking. We don't want to use `:sleep`
echo 'it has been 5 seconds'

Back then we don’t have timer_start Vim script function, we had to register events such as CursorHold or CursorHoldI to check what time is it and compare with a base you prepared.

Now we have Vim native function timer_start(), so let’s use it first without vital.

function! s:my_echo(timer_id) abort
echo 'it has been 5 seconds'
endfunction

echo timer_start(5000, function('s:my_echo'))

It works. When you evaluate them your Vim won’t block you; you can do anything. And after 5 seconds you get the message shown.

You can shorten that with using Vim8 lambda. The below and the above are conceptually same.

echo timer_start(5000, {_ ->
\ execute('echo "it has been 5 seconds"', '')
\})

Let’s use Vital.Async.Promise this time.

let s:P = vital#vital#import('Async.Promise')

call s:P.new({resolve -> timer_start(5000, resolve)})
\.then({->
\ execute('echo "it has been 5 seconds"', '')
\})

They look quite similar so far.

Let’s continue into a little bit more complicated example.

Example: fault tolerant chained operations with job_start/channel

Coming soon…

Talked at RubyKaigi 2017

I gave a lightning talk at RubyKaigi 2017 as How to develop CRuby easily with Vim.

My talk and its slides

I was so nervous there.

A RubyKaigi staff personally took that videos of me presenting. I’ll replace them with RubyKaigi official videos on youtube once it’s available.

I used Google Slides and showtime.vim for projector to use, and focused mostly on live demo with GVim on my Gentoo Linux.

The final page has some links for the tools I used there.

FYI I collected tweets with #rubykaigi hashtag during my talk.
(Mostly in Japanese)

Additional notes for my talk

  • The 2 games I played at the beginning
    • mario.vim, made by rbtnn with his own game_engine.vim
      • It generates the stage randomly, so you can play forever.
      • I personally play puyo.vim occasionally for fun sometimes.
    • vim-game-code-break
      • Block-breaking game, but the blocks are made with text in the current buffer.
      • (I was too nervous to set this up properly. Audiences couldn’t see the buffer text..)
  • https://github.com/mrkn/vim-cruby is a handy config for CRuby development
    • Note that it needs you to set its own filetype=cruby instead of filetype=c
    • Follow the README for that
    • This allows syntax completions (e.g. RUBY_DATA_FUNC, NUM2SSIZET, StringValuePtr) based on its syntax keywords
    • These keywords are manually added by mrkn.
  • Jump from Ruby code to CRuby implementation (like ctags for Ruby to Ruby and C to C)
    • Many ways are possible but no clean nice ways available yet
    • Maybe a good idea just to use regexp with ctags or something like that
    • I myself want the ujihisa/cruby-defs.vim mentioned in the slides so I may make it later
  • quicklearn.vim to see RubyVM::ISeq on the fly
    • I think I have written an article for that in 2012
    • I found it http://vim-jp.org/vim-users-jp/2012/01/01/a-happy-new-year.html (Japanese)
    • The main focus of this Vim plugin was to visualize assembly code from C, and YARV ISeq was just a byproduct at the time.
      • e.g. gcc32, gcc32 with optimization, gcc64, gcc64 with optimization, llvm ir, and llvm ir with optimization
    • Good thing is that you can use quicklearn.vim effectively to learn what the final keynote by vlad was that. It mentioned about optimization in the internal representation layer.
  • I was happy that @shioyama mentioned that my talk was good!

//platform.twitter.com/widgets.js

I was moved by the fact that llvm opt could optimize my slow inefficient fib function written in brainf**k that compiled to llvm ir by my compiler to an immediate value. It must be beyond awesome when it works with one of the complex languages such as Ruby

a thing that I couldn’t make it during 5 min lightning talk

I fast-forwarded at the end of lightning talk but I didn’t have enough time advertising Fablic, inc where I currently work at.

Personal notes

I have given talks at RubyKaigi twice and RubyConf once in the past. I have experienced a quick and not-really-prepared lightning talk at RubyConf 2009 as well, but not at the very serious and time-restricted RubyKaigi; it was the first time for me. I was so nervous.

The RubyKaigi 2017 this year was really amazing. It didn’t only have great talks, but also helped me seeing lots of friends I haven’t seen for long time. Great also for meeting somebody new.

Thanks again to the organizers of RubyKaigi 2017 including Akira Matsuda, all the staffs and sponsors, and speakers. You are awesome.
I can say with confident that RubyKaigi 2017 was a great success.

Next steps for myself

  • VimConf 2017 in Nov
  • RubyConf 2017 in Nov

Heading to RubyKaigi 2017

I’ll be attending RubyKaigi 2017 on 2017-09-18 to 2017-09-20 in Hiroshima, Japan. See you there!

My short lightning talk: http://rubykaigi.org/2017/presentations/lt/ I’ll upload slides later.

Oedo RubyKaigi 06

I went to Oedo RubyKaigi 06 on 2017-03-20 in Tokyo and gave a talk about random stuff.

https://asakusarb.github.io/oedo06/

My talk

高濃度雑談

“Random topics, but overly high dense”

Since I came to Japan, I tried doing everything opposite to what I’ve done, so instead of organizing things and cutting unnecessary noise out, I included everything, and kept unorganized.

Topics included

  • Ruby m17n
  • Ruby continuation (code example demo below)
  • Vim quickrun
  • The implementation of quickrun
  • How Vim spawns a process and interact with it
  • How to achieve cuncurrency in Vim script
  • Vim script
  • vim + ruby (if_ruby)
  • continuation can SEGV
  • Vim = OS
  • Vim 8 job
  • quickrun with job
  • vital.vim
  • Conventional difference how rubyists document and how vimmers document
  • reading implementations
  • music score and cooking recipe
  • Cooking for Geeks
  • The Art of Fermentation
  • Sourdough, Mead, and Sauerkraut
  • Illegal to name Engineer in BC
  • FRIL
  • Fablic, inc
  • Japan

The continuation simple example

loop version:

5.times do |i|
 puts "Current i is #{i}"
end
puts :done

This outputs this

Current i is 0
Current i is 1
Current i is 2
Current i is 3
Current i is 4
done

The other version with continuation:

require 'continuation'
cont = nil
i = callcc {|c| cont = c; 0 }
puts "Current i is #{i}"
cont.(i + 1) if i < 4
puts :done

 

 

 

 

 

 

 

 

 

 

 

 

 

Baguette

IMG_7795 IMG_7796 IMG_7797 IMG_7798

I prefer longer ones, but I don’t have a plate that can hold.

Ingredients

  • 500g flour (roughly 250g whole grain wheat flour, and 250g white all-purpose wheat flour)
  • 400g water
  • 6 ~ 10g salt
  • 6 ~ 10g sugar
  • 4 ~ 6g dry yeast
  • more flour for sprinkling to avoid sticking

Steps (total ≤20min labour)

  • Mix all but flour (water, salt, sugar, and dry yeast) together in a big bowl
  • Put flour and mix.
    • It may be tough at first. Leave some time and try again; it should be easier
  • Put a cover and leave like for 8 hours
    • I usually do above steps at night, and do below at the next morning
  • Form it
    • Sprinkle enough flour both to the top of the bowl and the plate to bake, otherwise you will have hard time removing the baked bread out later.
  • Preheat oven to 470F
    • It’s pretty hot!
    • I preheat after forming the dough, so that dough have enough time to rest.
  • Sprinkle water and make some coupe
    • I usually use scissors to cut
    • Water is to make the dough moisture. Don’t put too much to make them wet
  • Insert into oven, reduce the heat to 450F, and wait for 25min
    • Don’t undercook or overcook
    • If you can see some edges have tiny black line, that’s the time
    • Undercooked baguettes make it hard to slice and eat, particularly the skin. This may sound opposite, but that was true for me.
  • Take the bread out, and leave for 30min to cool down
    • It’s still cooking inside
    • It’s also extremely hard to slice when it’s too moisture
  • Slice
    • Use breadknife. Don’t press. Google how to slice bread

Notes

  • Baking breads, particularly baguettes, needs the oven to be somewhat moisture. Also the oven needs to be hot even after opening the door to put the doughs in. One solution is to put stones and small bowl with water in advance. But I think that they don’t have to be pure objects that achieve the breads’ requirements, but they can be something that give us additional benefit. Last time I put chicken thighs with some herbs. Since I put chicken in advance, they should have kept high temperature when I re-open the door to put doughs in, and also chicken should have generated some vapour that moisturize the oven room. The baguettes I got were good, and also I got the chicken to be roasted for free.
  • Buy a big bag of yeast, and keep it in freezer. If it’s inconvenient for you to use, take some batch out into an empty jar or anything.
  • They taste amazing. Considering the fact that it’s easy for me to make and it costs very low, I think this is really practical recipe that I can keep doing.
  • I keep the brown baked sprinkled flour into ziploc. They can be used for making white sauce with butter.
  • I form dough directly on the plate to bake. One less object to clean.
  • I’m calling this recipe as my bread making version 2. I have published version 1 article in Japanese in the past, but this current version is better and easier.
    • Currently experimenting making version 3 which won’t use dry yeast but uses sourdough starter.

Natural Scrolling + Left Handed Mouse Buttons

Things described below are done on my Gentoo Linux on 2015-08-15. However they should apply any X11 Systems such as Debian, Ubuntu, or Arch Linux as well, because none of them are depending on Gentoo specific tools.

Problem: Natural scrolling

This should be easy. Both xfce4 and gnome have config to reverse scroll direction. However, they don’t always reverse only on some GUI apps (such as evince pdf viewer)

xmodmap seems to solve this issue, but it does not.

xmodmap has another issue that if you unplug/plug USB mouse you have to apply xmodmap again.

Let’s find a solution which doesn’t depend on xmodmap, and which also works for any apps including evince.

Also I want to swap left click and right click.

Solution: /etc/X11/xorg.conf.d

Add /etc/X11/xorg.conf.d/99-ujihisa.conf

Section "InputClass"
        Identifier "natural scrolling for mouse"
        MatchDriver "evdev"
        Option "ButtonMapping" "3 2 1 5 4"
EndSection

Section "InputClass"
        Identifier "natural scrolling for touchpad"
        MatchDriver "synaptics"
        Option      "VertScrollDelta"          "-111"
        Option      "HorizScrollDelta"         "-111"
EndSection

After spending couple days I figured out that the above config works.

Notes for the process finding that solution

  • Tried to modify files under /usr/share/X11/xorg.conf.d/ which at-home-modifier (i.e. x11-drivers/xf86-input-evdev) also uses
  • Specifying wrong value (e.g. Driver "mouse") is very dangerous. It can disable any user inputs, and you may have to shutdown computer by holding the power button.
  • If you give wrong value the config can be silently ignored. /var/log/Xorg.0.log can be helpful for debugging
  • man xorg.conf.d, man synaptics, and man evdev are helpful
  • You may have seen ZAxisMapping for inverting scroll. Forget about it. It won’t work

Appendix