Reading docs in irb - ruby-on-rails

One thing I miss about ipython is it has a ? operator which diggs up the docs for a particular function.
I know ruby has a similar command line tool but it is extremely inconvenient to call it while I am in irb.
Does ruby/irb have anything similar?

Pry is a Ruby version of IPython, it supports the ? command to look up documentation on methods, but uses a slightly different syntax:
pry(main)> ? File.dirname
From: file.c in Ruby Core (C Method):
Number of lines: 6
visibility: public
signature: dirname()
Returns all components of the filename given in file_name
except the last one. The filename must be formed using forward
slashes (/'') regardless of the separator used on the
local file system.
File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work"
You can also look up sourcecode with the $ command:
pry(main)> $ File.link
From: file.c in Ruby Core (C Method):
Number of lines: 14
static VALUE
rb_file_s_link(VALUE klass, VALUE from, VALUE to)
{
rb_secure(2);
FilePathValue(from);
FilePathValue(to);
from = rb_str_encode_ospath(from);
to = rb_str_encode_ospath(to);
if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
sys_fail2(from, to);
}
return INT2FIX(0);
}
See http://pry.github.com for more information :)

You can start with
irb(main):001:0> `ri Object`
Although the output of this is less than readable. You'd need to filter out some metacharacters.
In fact, someone already made a gem for it
gem install ori
Then in irb
irb(main):001:0> require 'ori'
=> true
irb(main):002:0> Object.ri
Looking up topics [Object] o
= Object < BasicObject
------------------------------------------------------------------------------
= Includes:
Java (from gem activesupport-3.0.9)
(from gem activesupport-3.0.9) [...]

No, it doesn't. Python has docstrings:
def my_method(arg1,arg2):
""" What's inside this string will be made available as the __doc__ attribute """
# some code
So, when the ? is called from ipython, it probably calls the __doc__ attribute on the object. Ruby doesn't have this.

Related

Sourcing nvim.init does not source required Lua files

I have neovim 0.7.0 running and my .vimrc is at ~/.config/nvim/init.vim
I also have the following file: ~/.config/nvim/lua/statusline.lua with one line of code:
print('message from statusline.lua')
Inside init.vim I have:
echo 'from init.vim'
lua require('statusline')
When I start nvim I get both messages printed out ('from init.vim' and 'message from statusline.lua') which is what I would expect.
When I run :source $MYVIMRC I only see 'from init.vim'. I would expect the other message ('message from statusline.lua') to appear as well.
I assume this means any changes I make in statusline.lua will not take effect when I run :source $MYVIMRC. How should I source my init.vim file plus any files it requires without closing and restarting neovim?
Either invalidate cache entry by appending return false to the end of a module.
Or don't use require at all, as you need neither cache nor path search anyway. E.g.
for k, v in ipairs(vim.fn.glob("~/.config/nvim/init.d/*.lua", false, true)) do
dofile(v)
end
P.S. Lua is not a "config tool". It is a full-featured programming language. If you don't like wasting your time by learning it properly (i.e. reading books and tutorials) you're highly suggested to use VimScript instead. It has some "dark corners" of its own but it is much better suited for writing config.
It depends on the design of your statusline.lua and knowledge about Lua' module loader system.
It looks, because i have to riddle about statusline.lua, that it nothing returns.
Because the return is going into package.loaded and same require in same session looks first there for statusline
So give following a try...
-- statusline.lua
print('message from statusline.lua')
return 'message from package.loaded.statusline'
I have tested above with...
$ lua -i
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> require('statusline')
message from statusline.lua
message from package.loaded.statusline ./lua/statusline.lua
> require('statusline')
message from package.loaded.statusline
> require('statusline')
message from package.loaded.statusline
EDIT
Another design for doing something usefull...
-- ~.config/nvim/init.vim
lua print("init.vim")
lua dump = require("dump")
And...
-- ~/.config/nvim/lua/dump.lua
local dump = function(tab)
for key, value in pairs(tab) do
print(key, '=>', value)
end
end
return dump
Than you have a table viewer and you can see where the functions and tables come from with...
:lua dump(_G) -- The global environment table
:lua dump(vim) -- The nvim stuff (aka Module)
:lua dump(vim.api) -- The nvim API functions (aka Library)
:lua dump(jit) -- The Just In Time Compiler ;-)
:lua dump([Table Name]) -- Any table that looks interesting
:lua dump(package.loaded) -- The required or requireable stuff
Above function can be executed without defining dump first with: :lua require('dump')(_G)
So: First require loads dump.lua into package.loaded.dump and returning it and every further require returning: package.loaded.dump
If you have an sharp eye than take a look on _G.dump thats only a reference (pointer/link) to package.loaded.dump.
EDIT2
Preparing dump.lua for using it with vim.api.nvim_input()
-- ~/.config/nvim/lua/dump.lua
local dump = function(tab)
local tmp = ''
for key, value in pairs(tab) do
tmp = tmp .. ('%s %s %s\n'):format(key, '=>', value)
end
return tmp
end
return dump
Now the dump function returning a string and the output can be loaded into nvim with: :lua vim.api.nvim_input('i') vim.api.nvim_input(dump(vim.api))
Since many nvim API functions returning a table the dump function becomes handy with...

How can I reload my Neovim config written in lua with a shortcut?

I want to reload my neovim configuration files with just a couple of keystrokes instead of having to restart the app. I was able to do this when using an init.vim with the following command:
nnoremap <leader>sv <cmd>source $MYVIMRC<CR>
$MYVIMRC points correctly to my config entry point.
The problem is that I switched to using lua, and now I can't do the same. I have read the docs and tried variants of the following without success:
util.nnoremap("<leader>sv", "<cmd>luafile $MYVIMRC<CR>")
Finally, I found a solution doing this:
function load(name)
local path = vim.fn.stdpath('config') .. '/lua/' .. name .. '.lua'
dofile(path)
end
load('plugins')
load('config/mapping')
load('lsp/init')
Which is buggy and feels wrong.
Is there any way to do this? I read the example in vimpeccable, but I want to see the other available options since I would rather not install another plugin.
I know that plenary includes a function to reload modules, but I don't understand how to use it. A complete example of that would be good too since I already use plenary in my config.
I am a new Neovim user, so I guess my solution may not work for some edge cases.
This function flushes the module of current buffer:
local cfg = vim.fn.stdpath('config')
Flush = function()
local s = vim.api.nvim_buf_get_name(0)
if string.match(s, '^' .. cfg .. '*') == nil then
return
end
s = string.sub(s, 6 + string.len(cfg), -5)
local val = string.gsub(s, '%/', '.')
package.loaded[val] = nil
end
You can call it whenever you write to a buffer with this autocommand:
autocmd BufWrite *.lua,*vim call v:lua.Flush()
This way, after you execute :source $MYVIMRC it will also reload changed Lua modules.

Mix debugger commands and ruby code evaluation

I'm currently upgrading an old project from and old version of ruby(1.8.7)/rails(3.0) to 1.9.3/3.1 (as a stepping stone to newer versions).
I'm using gems debugger for 1.9.3 and ruby-debug for 1.8.7
When I run , I can run commands like info variables to get the list and values of all currently-scoped variables:
...
#current_phone = nil
#fields = {}
#global = {:source_type=>"pdf"}
#images = []
#index = {}
#lines = []
...
Also I can run arbitrary ruby code - a useful one I've been using is
File.open("/tmp/new_version", "w"){|f|f.write(#fields)}
which is useful for me to quickly compare between the old version and the new version using a file diff program.
Can I link these together so I can write to a file all the output of info variables? It would be sufficient if I could do
tempvar = info variables
or something along those lines, of course, but that gives
*** NameError Exception: undefined local variable or method `variables' for <ClassWhatever>
instance_variables.map { |v| [v, instance_variable_get(v)] }
Not exactly hash map, but you'll be good with it.

read and execute ruby script

script.rb:
puts 'hello'
puts 'foo'
main.rb:
puts `jruby script.rb` # receive the expected result
The question:
How can the same be achieved with reading the "script" before execution?
main.rb:
code=File.open('script.rb', 'r').read.gsub('"', '\"')
# puts `jruby -e '#{code}'` # Does not work for relatively big files;
Windows and unicode are the reasons of this question;
Please note that `jruby script.rb' creates a new process which is essential.
Store the modified script in a Tempfile and run that instead of passing the whole contents as an eval argument:
require 'tempfile'
code = IO.read('script.rb').gsub('"', '\"')
begin
tempfile = Tempfile.new 'mytempfile'
f.write code
f.close
puts `jruby '#{f.path}'`
ensure
f.close
f.unlink
end
The reason you’re likely getting an error is either a lack of proper escaping or a limit on the maximum argument length in the shell.
Also, beware that in your original implementation you never close the original file. I’ve fixed that by instead using IO.read.
In the command line, using
$ getconf ARG_MAX
will give the upper limit on how many bytes can be used for the command line argument and environment variables.
#Andrew Marshall's answer is better, but suppose you don't want to use a temp file, and assuming we can use fork in JRuby,
require 'ffi'
module Exec
extend FFI::Library
ffi_lib FFI::Platform::LIBC
attach_function :fork, [], :int
end
code = IO.read('script.rb')
pid = Exec.fork
if 0 == pid
eval code
exit 0
else
Process.waitpid pid
end
use require
main.rb:
require "script.rb"

HMAC SHA256 hex digest of a string in Erlang, how?

I am trying to interact with third party real time Web messaging System created and maintained by Pusher.com. Now, i cannot send anything through the API unless i produce an HMAC SHA256 hex digest of my data. A sample source code written in ruby could try to illustrate this:
# Dependencies
# gem install ruby-hmac
#
require 'rubygems'
require 'hmac-sha2'
secret = '7ad3773142a6692b25b8'
string_to_sign = "POST\n/apps/3/channels/test_channel/events\nauth_key=278d425bdf160c739803&auth_timestamp=1272044395&auth_version=1.0&body_md5=7b3d404f5cde4a0b9b8fb4789a0098cb&name=foo"
hmac = HMAC::SHA256.hexdigest(secret, string_to_sign)
puts hmac
# >> 309fc4be20f04e53e011b00744642d3fe66c2c7c5686f35ed6cd2af6f202e445
I checked the erlang crypto Library and i cannot even generate a SHA256 hex digest "directly"
How do i do this whole thing in Erlang ? help....
* UPDATE *
I have found solutions here: sha256 encryption in erlang and they have led me to erlsha2. But still, how do i generate the HMAC of a SHA256 hexdigest output from this module ?
With erlsha2, use the following to get the equivalent of your Ruby code:
1> hmac:hexlify(hmac:hmac256(<<"7ad3773142a6692b25b8">>, <<"POST\n/apps/3/channels/test_channel/events\nauth_key=278d425bdf160c739803&auth_timestamp=1272044395&auth_version=1.0&body_md5=7b3d404f5cde4a0b9b8fb4789a0098cb&name=foo">>)).
"309FC4BE20F04E53E011B00744642D3FE66C2C7C5686F35ED6CD2AF6F202E445"
I just stumbled through this myself and finally managed it just using crypto, so thought I would share. For your usage I think you would want:
:crypto.hmac(:sha256, secret, string_to_sign) |> Base.encode16
The hmac portion should take care of digest + hmac and then piping to encode 16 should provide the hex part. I imagine you probably moved on some time ago, but since I just had the same issue and wanted to try and figure it out in stdlib stuff I thought I would share.
The same project (erlsha2) has a module for this:
https://github.com/vinoski/erlsha2/blob/master/src/hmac.erl
If you're using Elixir, you can use
:crypto.hash(:sha256, [secret, string_to_sign])
|> Base.encode16
|> String.downcase
This is a one-liner (Erlang 24):
[begin if N < 10 -> 48 + N; true -> 87 + N end end ||
<<N:4>> <= crypto:mac(hmac, sha256, Secret1, StringToSign1)].
>>> "309fc4be20f04e53e011b00744642d3fe66c2c7c5686f35ed6cd2af6f202e445"
No need for external libs.

Resources