How to use Sharp AN-SS1 neck speaker both as speaker/microphone

ArchLinux

  1. Install ofono, besides bluez and pulseaudio stuff.
  2. Edit /etc/pulse/default.pa
load-module module-bluetooth-policy ag=true
...
load-module module-bluetooth-discover headset=native

to

load-module module-bluetooth-policy
...
load-module module-bluetooth-discover

Useful tools

$ pacmd ls
...
    index: 1
    name: <alsa_card.pci-0000_25_00.3>
    driver: <module-alsa-card.c>
    owner module: 7
    properties:
        alsa.card = "1"
        alsa.card_name = "HD-Audio Generic"
        alsa.long_card_name = "HD-Audio Generic at 0xfe800000 irq 65"
        alsa.driver_name = "snd_hda_intel"
        device.bus_path = "pci-0000:25:00.3"
        sysfs.path = "/devices/pci0000:00/0000:00:08.1/0000:25:00.3/sound/card1"
        device.bus = "pci"
        device.vendor.id = "1022"
        device.vendor.name = "Advanced Micro Devices, Inc. [AMD]"
        device.product.id = "1457"
        device.product.name = "Family 17h (Models 00h-0fh) HD Audio Controller"
        device.string = "1"
        device.description = "Family 17h (Models 00h-0fh) HD Audio Controller"
        module-udev-detect.discovered = "1"
        device.icon_name = "audio-card-pci"
    profiles:
        input:analog-stereo: Analog Stereo Input (priority 65, available: no)
        output:analog-stereo: Analog Stereo Output (priority 6500, available: no)
        output:analog-stereo+input:analog-stereo: Analog Stereo Duplex (priority 6565, available: no)
        off: Off (priority 0, available: unknown)
    active profile: <off>
    ports:
        analog-input-front-mic: Front Microphone (priority 8500, latency offset 0 usec, available: no)
            properties:
                device.icon_name = "audio-input-microphone"
        analog-input-rear-mic: Rear Microphone (priority 8200, latency offset 0 usec, available: no)
            properties:
                device.icon_name = "audio-input-microphone"
        analog-input-linein: Line In (priority 8100, latency offset 0 usec, available: no)
            properties:

        analog-output-lineout: Line Out (priority 9900, latency offset 0 usec, available: no)
            properties:

        analog-output-headphones: Headphones (priority 9000, latency offset 0 usec, available: no)
            properties:
                device.icon_name = "audio-headphones"
0 sink input(s) available.
0 source output(s) available.
0 cache entrie(s) available.
Advertisements

Going to talk about Ruby’s local variables at RubyKaigi 2019

https://rubykaigi.org/2019/presentations/ujm.html#apr20

Play with local vars

This 40min talk is only about Ruby’s local variables. I’m not going to talk about anything else.

I’ll demonstrate, or more precisely, play with Ruby local variables, including a discussion about the following common pitfall:

  eval 'a = 1'
  eval 'p a' #=> NameError!
  

Ruby has multiple different types of variables: global vars, instance vars, class vars, constants, local vars, and pseudo vars such as self. Identifiers without sigils such as @ are considered either local vars, methods, method arguments, block parameters, pseudo variables, or other reserved words. Particularly important aspect I believe is that Ruby intentionally tries to make local vars and methods indistinguishable for human. This talk focuses only on local vars among other variables or methods.

Keywords: parse.y, binding, yarv iseq, continuation, flip-flop operator, regular expression, and gdb
Oh by the way, the whole presentation is likely going to be done inside my Vim.

My talk is the 3rd day; on 2019-04-20.
See you at the conference in Fukuoka, Japan!

How to get caller’s token in Ruby

TL;DR You can’t, so far as I know.

Problem

When you are in a method, how do you get the caller’s token location?

Screenshot_2019-02-18_10-16-41

def f(x)
  if x == 234
    # I want to get caller's token as filename, line number, and column number,
    # such as a.rb:8:9
  end
end

f(123); f(234)

Solutions

It is easy to get the filename and line number by caller and caller_locations methods in Kernel.

caller
#=> ["/tmp/vD5fH5c/566:7:in `'"]  ["/tmp/vD5fH5c/567:7:in `'"]  [:absolute_path, :base_label, :label, :lineno, :path]

However, it doesn’t give you column number.

See VM iseq

With using Kernel#.caller_locations you have the caller file, let’s first dump the iseq with using RubyVM::InstructionSequence#disasm

def f(x)
  if x == 234
    filepath = caller_locations[0].path
    iseq = RubyVM::InstructionSequence.compile_file(filepath)
    puts iseq.disasm
  end
end

f(123); f(234)

result:

== disasm: #<ISeq:<main>@/tmp/vD5fH5c/581:1 (1,0)-(9,14)> (catch: FALSE)
0000 putspecialobject             1                                   (   1)[Li]
0002 putobject                    :f
0004 putiseq                      f
0006 opt_send_without_block       <callinfo!mid:core#define_method, argc:2, ARGS_SIMPLE>, <callcache>
0009 pop
0010 putself                                                          (   9)[Li]
0011 putobject                    123
0013 opt_send_without_block       <callinfo!mid:f, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0016 pop
0017 putself
0018 putobject                    234
0020 opt_send_without_block       <callinfo!mid:f, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0023 leave

== disasm: #<ISeq:f@/tmp/vD5fH5c/581:1 (1,0)-(7,3)> (catch: FALSE)
local table (size: 3, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 3] x@0<Arg>   [ 2] filepath@1 [ 1] iseq@2
0000 getlocal_WC_0                x@0                                 (   2)[LiCa]
0002 putobject                    234
0004 opt_eq                       <callinfo!mid:==, argc:1, ARGS_SIMPLE>, <callcache>
0007 branchunless                 48
0009 putself                                                          (   3)[Li]
0010 opt_send_without_block       <callinfo!mid:caller_locations, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0013 putobject_INT2FIX_0_
0014 opt_aref                     <callinfo!mid:[], argc:1, ARGS_SIMPLE>, <callcache>
0017 opt_send_without_block       <callinfo!mid:path, argc:0, ARGS_SIMPLE>, <callcache>
0020 setlocal_WC_0                filepath@1
0022 opt_getinlinecache           31, <is:0>                          (   4)[Li]
0025 getconstant                  :RubyVM
0027 getconstant                  :InstructionSequence
0029 opt_setinlinecache           <is:0>
0031 getlocal_WC_0                filepath@1
0033 opt_send_without_block       <callinfo!mid:compile_file, argc:1, ARGS_SIMPLE>, <callcache>
0036 setlocal_WC_0                iseq@2
0038 putself                                                          (   5)[Li]
0039 getlocal_WC_0                iseq@2
0041 opt_send_without_block       <callinfo!mid:disasm, argc:0, ARGS_SIMPLE>, <callcache>
0044 opt_send_without_block       <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0047 leave                                                            (   7)[Re]
0048 putnil                                                           (   5)
0049 leave                                                            (   7)[Re]

Following caller_locations[0].lineno == 9, let’s extract iseq that belongs to line 9.

def f(x)
  if x == 234
    filepath, lineno = caller_locations[0].then {|l| [l.path, l.lineno] }
    iseq = RubyVM::InstructionSequence.compile_file(filepath)
    lines = iseq.disasm.each_line.select {|l|
      true if (/^\d+ .*\(\s*#{lineno}\)/ =~ l) .. (/^$|^\d .*\(\s*\d+\)/ =~ l)
    }
    puts lines
  end
end

f(123); f(234)

Result:

/tmp/vD5fH5c/606:6: warning: flip-flop is deprecated
0010 putself                                                          (  12)[Li]
0011 putobject                    123
0013 opt_send_without_block       , 
0016 pop
0017 putself
0018 putobject                    234
0020 opt_send_without_block       , 
0023 leave

/tmp/vD5fH5c/606:6: warning: flip-flop is deprecated

You can see 2 method calls to f, but you can’t tell which of them it’s from. In this code example it’s trivial since there are literal 123 and 234 right above, but in general you can’t reason easily.

Alternatively you can use RubyVM::InstructionSequence#to_a instead of RubyVM::InstructionSequence#disasm, which returns a little bit more structured than disasm, seems making it easier to exact. to_a has less info than disasm though, like it doesn’t show local variable names for getlocal instruction.

def f(x)
  if x == 234
    filepath, lineno = caller_locations[0].then {|l| [l.path, l.lineno] }
    iseq = RubyVM::InstructionSequence.compile_file(filepath)
    # lines = iseq.disasm.each_line.select {|l|
    #   true if (/^\d+ .*\(\s*#{lineno}\)/ =~ l) .. (/^$|^\d .*\(\s*\d+\)/ =~ l)
    # }
    pp iseq.to_a
  end
end

f(123); f(234)

result:

["YARVInstructionSequence/SimpleDataFormat",
 2,
 7,
 1,
 {:arg_size=>0,
  :local_size=>0,
  :stack_max=>3,
  :node_id=>51,
  :code_location=>[1, 0, 12, 14]},
 "",
 "/tmp/vD5fH5c/607",
 "/tmp/vD5fH5c/607",
 1,
 :top,
 [],
 {},
 [],
 [1,
  :RUBY_EVENT_LINE,
  [:putspecialobject, 1],
  [:putobject, :f],
  [:putiseq,
   ["YARVInstructionSequence/SimpleDataFormat",
    2,
    7,
    1,
    {:arg_size=>1,
     :local_size=>4,
     :stack_max=>2,
     :node_id=>40,
     :code_location=>[1, 0, 10, 3]},
    "f",
    "/tmp/vD5fH5c/607",
    "/tmp/vD5fH5c/607",
    1,
    :method,
    [:x, :filepath, :lineno, :iseq],
    {:lead_num=>1},
    [[:break,
      ["YARVInstructionSequence/SimpleDataFormat",
       2,
       7,
       1,
       {:arg_size=>1,
        :local_size=>1,
        :stack_max=>2,
        :node_id=>24,
        :code_location=>[3, 48, 3, 73]},
       "block in f",
       "/tmp/vD5fH5c/607",
       "/tmp/vD5fH5c/607",
       3,
       :block,
       [:l],
       {:lead_num=>1, :ambiguous_param0=>true},
       [[:redo, nil, :label_1, :label_13, :label_1, 0],
        [:next, nil, :label_1, :label_13, :label_13, 0]],
       [3,
        :RUBY_EVENT_B_CALL,
        [:nop],
        :label_1,
        :RUBY_EVENT_LINE,
        [:getlocal_WC_0, 3],
        [:opt_send_without_block,
         {:mid=>:path, :flag=>16, :orig_argc=>0},
         false],
        [:getlocal_WC_0, 3],
        [:opt_send_without_block,
         {:mid=>:lineno, :flag=>16, :orig_argc=>0},
         false],
        [:newarray, 2],
        :label_13,
        [:nop],
        :RUBY_EVENT_B_RETURN,
        [:leave]]],
      :label_9,
      :label_21,
      :label_21,
      0]],
    [2,
     :RUBY_EVENT_LINE,
     :RUBY_EVENT_CALL,
     [:getlocal_WC_0, 6],
     [:putobject, 234],
     [:opt_eq, {:mid=>:==, :flag=>16, :orig_argc=>1}, false],
     [:branchunless, :label_55],
     :label_9,
     3,
     :RUBY_EVENT_LINE,
     [:putself],
     [:opt_send_without_block,
      {:mid=>:caller_locations, :flag=>28, :orig_argc=>0},
      false],
     [:putobject_INT2FIX_0_],
     [:opt_aref, {:mid=>:[], :flag=>16, :orig_argc=>1}, false],
     [:send,
      {:mid=>:then, :flag=>0, :orig_argc=>0},
      false,
      ["YARVInstructionSequence/SimpleDataFormat",
       2,
       7,
       1,
       {:arg_size=>1,
        :local_size=>1,
        :stack_max=>2,
        :node_id=>24,
        :code_location=>[3, 48, 3, 73]},
       "block in f",
       "/tmp/vD5fH5c/607",
       "/tmp/vD5fH5c/607",
       3,
       :block,
       [:l],
       {:lead_num=>1, :ambiguous_param0=>true},
       [[:redo, nil, :label_1, :label_13, :label_1, 0],
        [:next, nil, :label_1, :label_13, :label_13, 0]],
       [3,
        :RUBY_EVENT_B_CALL,
        [:nop],
        :label_1,
        :RUBY_EVENT_LINE,
        [:getlocal_WC_0, 3],
        [:opt_send_without_block,
         {:mid=>:path, :flag=>16, :orig_argc=>0},
         false],
        [:getlocal_WC_0, 3],
        [:opt_send_without_block,
         {:mid=>:lineno, :flag=>16, :orig_argc=>0},
         false],
        [:newarray, 2],
        :label_13,
        [:nop],
        :RUBY_EVENT_B_RETURN,
        [:leave]]]],
     :label_21,
     [:nop],
     [:expandarray, 2, 0],
     [:setlocal_WC_0, 5],
     [:setlocal_WC_0, 4],
     4,
     :RUBY_EVENT_LINE,
     [:opt_getinlinecache, :label_38, 0],
     [:getconstant, :RubyVM],
     [:getconstant, :InstructionSequence],
     [:opt_setinlinecache, 0],
     :label_38,
     [:getlocal_WC_0, 5],
     [:opt_send_without_block,
      {:mid=>:compile_file, :flag=>16, :orig_argc=>1},
      false],
     [:setlocal_WC_0, 3],
     8,
     :RUBY_EVENT_LINE,
     [:putself],
     [:getlocal_WC_0, 3],
     [:opt_send_without_block, {:mid=>:to_a, :flag=>16, :orig_argc=>0}, false],
     [:opt_send_without_block, {:mid=>:pp, :flag=>20, :orig_argc=>1}, false],
     10,
     :RUBY_EVENT_RETURN,
     [:leave],
     :label_55,
     8,
     [:putnil],
     10,
     :RUBY_EVENT_RETURN,
     [:leave]]]],
  [:opt_send_without_block,
   {:mid=>:"core#define_method", :flag=>16, :orig_argc=>2},
   false],
  [:pop],
  12,
  :RUBY_EVENT_LINE,
  [:putself],
  [:putobject, 123],
  [:opt_send_without_block, {:mid=>:f, :flag=>20, :orig_argc=>1}, false],
  [:pop],
  [:putself],
  [:putobject, 234],
  [:opt_send_without_block, {:mid=>:f, :flag=>20, :orig_argc=>1}, false],
  [:leave]]]

See the parser

TODO

Use TracePoint

TODO

How to paste clipboard in Vim :terminal

Vim 8’s :terminal requires some :terminal-specific knowledge. Pasting from your clipboard is one of them.

h ctrl-w_.

Special in the terminal window:         *CTRL-W_.*  *CTRL-W_N* 
    CTRL-W .    send a CTRL-W to the job in the terminal
    CTRL-W CTRL-\   send a CTRL-\ to the job in the terminal
    CTRL-W N    go to Terminal-Normal mode, see |Terminal-mode|
    CTRL-\ CTRL-N   go to Terminal-Normal mode, see |Terminal-mode|
    CTRL-W " {reg}  paste register {reg}       *CTRL-W_quote*
            Also works with the = register to insert the result of
            evaluating an expression.
    CTRL-W CTRL-C   ends the job, see below |t_CTRL-W_CTRL-C|

As h ctrl-w_. in terminal.txt mentions, CTRL-W " {reg} can be used for this purpose. "+ does that job.

My solution

Add this to your .vimrc assuming you are using gVim.

tnoremap <M-v> <C-w>"+

That way you can use Alt-V like Cmd-V to paste clipboard.

Side note

Why is wordpress.com missing [code language="vim script"] syntax highlighter?

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!

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