I'm following along with a tutorial book, and in order to step through my code I've required pry and added a binding.pry reference in a method which gets executed:
require 'pry'
module Rulers
module Model
class FileModel
def initialize(filename)
#filename = filename
binding.pry
basename = File.split(filename)[-1]
...
When I load the code which executes this constructor method, I successfully hit my binding.pry debugger point as expected. However, when I start typing commands at the prompt, the characters I enter are printed out in the same prompt:
[7] pry(#<Rulers::Model::FileModel>)> .whic.whichh
In the above example, I typed .which. I had gotten all the way to .whic when the REPL added the characters I had typed thus far (i.e. it added .whic to .whic, resulting in .whic.whic). The last character I typed was h, which registers after .whic.whic. Finally, the last h I typed was also appended to the chars on the prompt.
Interestingly, the duplicated chars do not appear to affect the REPL's ability to understand the commands I type in. For example, the following:
[8] pry(#<Rulers::Model::FileModel>)> .which .which vim
[8] pry(#<Rulers::Model::FileModel>)> .which vim
/usr/bin/vim
In the above example, I was successful in typing .which quickly enough to not result in a muddled version of the which command, and I also pressed Enter before vim could be duplicated erroneously. If the redundant 2nd .which command were to affect my ability to return the expected output, I would expect to see an error returned. Instead, I see /usr/bin/vim as I would expect when typing which vim in my regular, non-pry command line prompt.
I have no theories on where to begin debugging this. Any ideas?
Related
require 'rubygems'
require 'mechanize'
require 'io/console'
flag = 0
t2 =Thread.new do
puts flag
loop do
temp = STDIN.getch
if temp=="\n"
flag = (flag+1)%2
puts flag
end
end
end
# => Some foreground code
t2.join
When i run the code i get the value of flag printed 0 as it should. But the thread does not change the value of flag on the first Enter I hit. Hitting Enter the second time changes flag to 1 although. The thread works normally toggling the value of flag on further Enter hits. Why is this happening? What have I done wrong?
Problem seems to be only with getch
as when I use gets in place of getch the problem disappears. But I cant use gets because I want the user to hit a single key without needing to press Enter after the key to give input.
For example flag should not change when the user inputs a instead of Enter and so I have used getch to make sure the input is given after a single keyboard hit.
A similar problem was described here but it isn't a duplicate.
Edit 1:
The problem seems to be with getch and not the check what do ever.
flag = 0
t2 =Thread.new do
puts flag
loop do
temp = STDIN.getch
flag = (flag+1)%2
puts flag
end
end
t2.join
Even after removing the if statement, the first Enter is ignored no matter what but other characters seem to respond to the first time. The problem is coming only when I hit Enter. It doesn't count the first Enter I hit.
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
I tried your code on a Windows machine and was able to re-create the problem. As you correctly guessed it has nothing to do with threading and everything with how getch works (on Windows).
If you add a p temp.inspect to your loop you will see that it is not so much that the first '\n' is swallowed, rather it is that it is somehow "held back". The best way to see this if you press Enter and another key alternatively. You will see that the inspect is "off-by-one".
A good explanation about the problem is discussed here:
https://www.rubytapas.com/2016/12/14/ruby-code-on-windows/
With that information, a simple solution (that has the added benefit to run also on Linux, not sure about Mac) is:
require 'rubygems'
require 'mechanize'
require 'io/console'
STDIN.binmode #this line added to prevent line-end translation
flag = 0
t2 =Thread.new do
puts flag
loop do
temp = STDIN.getch
if temp=="\r" # note: changed from LF to CR
flag = (flag+1)%2
puts flag
end
end
end
# => Some foreground code
t2.join
Notes:
Admittedly I don't fully get the way it works. I was expecting that Enter would cause a "\r\n" sequence in binmode, but I only see "\r". Not sure what happens to the "\n", but it seems to work reliably this way.
Also note that in the current version the program can not be terminated with Ctrl+C. You'll have to add a check for that.
So I am studying Build Awesome Command-Line Applications in Ruby. On page 81, we're supposed to use STDIN to enter more than one task into a project.
File.open(global_options[:filename], 'a+') do |todo_file|
if task_names.empty?
puts "Reading new tasks from stdin..."
task_names = STDIN.readlines.map {|a| a.chomp}
end
tasks = 0
task_names.each do |task|
todo_file.puts [task, Time.now].join(', ')
tasks+=1
end
if tasks == 0
raise "You must provide tasks on the command-line or standard input"
end
end
The usual way to enter tasks into a project it's like this $todo new "Rake leaves but with the code above we can to what's in the example below.
It does work. But how do I tell STDIN to stop listening? The example on how to use it is this...
$ todo new
Rake leaves
Take out trash
Clean garage
Put away dishes
^D
What does the ^D represent?
It’s an end-of-file character. You can type this literally on Unix systems with Ctrl+D or on Windows with Ctrl+Z. The traditional way of displaying the Ctrl modifier is with a ^ prefix, e.g., ^D.
Be aware that this closes standard input entirely. If you want to read more data after entering these lines, you’ll need to check the input itself for a different delimiter—for instance, an empty line.
You can close STDIN by pressing Ctrl-d on Unix-like systems or Ctrl-z on Windows.
What does the ^6 represent?
Are you sure it says ^6 and not ^d? If so, that's probably a typo.
I'm having a problem with jumping to a Ruby bang method using Exhuberant Ctags. I have searched for others having a similar problem and am unable to find anything. An example of the problem can be shown using the following small Ruby class:
class Hello
def start
method!
end
def method
# Blah
end
def method!
# Blah
end
end
When ctags -R . is run on this file the resulting tags file contains the following 2 lines demonstrating that both methods are discovered at generation:
method test.rb /^ def method$/;" f class:Hello
method! test.rb /^ def method!$/;" f class:Hello
However, if I place my cursor on the call to method! on line 3 and press ^] then the cursor jumps to the method definition rather than to the correct bang version. It seems as if the exclamation mark is not being included in the identifier that is searched for.
Is there a way to fix this so the correct method is jumped to?
I realize this is super-old, but I ran into the same thing in both Vim 8.0 and Neovim. If I enter :tag mymethod! from vim's command-line, it finds the relevant tag, but if I try <C-]> with my cursor on the method name, it errors E426: tag not found: mymethod (note the lack of ! in the name it searched for).
You can fix this by adding ! to the list of characters recognized as keyword characters in Ruby syntax:
:set iskeyword+=!
You could add this to ~/.vim/after/syntax/ruby.vim to apply it in any Ruby file you open. I haven't tested this though, so can't say whether it will adversely affect anything else. I know it will change word jumping behavior. w will, for instance, treat the ! as part of the "small" word.
On second thought, it will definitely mishandle things like !some_test. If you were to hit <C-]> with the cursor anywhere in there, it would search for a method named !some_test, which is definitely not what you want. A better solution would be to write a wrapper function around the tag lookup for Ruby files. I'm actually working on something for that, so I'll post when I have something that presentable.
Update: I found a surprisingly simple workaround:
nnoremap <buffer><silent> <C-]> :tag <C-R><C-W><CR>
For some reason, the behavior of <C-R><C-W> in command-line mode differs from that of expand('<cword>'), and arguably from the documentation. Even though ! is not an 'iskeyword' character, and expand('<cword>') results in mymethod, <C-R><C-W> results in mymethod!. The same applies to is_this_your_method?. You could apply this workaround by putting the following in ~/.vim/ftplugin/ruby.vim:
nnoremap <buffer><silent> <C-]> :tag <C-R><C-W><CR>
nnoremap <buffer><silent> g] :tselect <C-R><C-W><CR>
nnoremap <buffer><silent> g<C-]> :tjump <C-R><C-W><CR>
Update 2
It turns out the special behavior of <C-R><C-W> was provided by vim-ruby (and included in Vim's runtime files by default). That script customizes <C-R><C-W> and also adds a <Plug><cword> mapping to correctly identify the Ruby cursor identifier. I only ran into the mishandling of ! because I had inadvertently clobbered the mappings already provided by vim-ruby when adding what I find to be more a comfortable keybinding:
nnoremap <C-.> <C-]>
If I'd done nmap instead, vim-ruby's mapping could have done its job. Alternatively, you could leverage what vim-ruby provides by doing (in a ruby ftplugin file):
nnoremap <buffer><silent> <C-]> :<C-U>exe v:count1."tag <Plug><cword>"<CR>
nnoremap <buffer><silent> g] :<C-U>tselect <Plug><cword><CR>
nnoremap <buffer><silent> g<C-]> :<C-U>tjump <Plug><cword><CR>
You can always use :tag:
:tag method!
Or visual mode - if you highlight any text (with v + movement) before you hit ^], it will use the highlighted text as the tag instead of trying to find an 'identifier' under the cursor. So if your cursor is on the m in method!, then
vE^]
should do the trick. If your cursor is elsewhere in the word, then hit b first.
I was using MacVim snapshot 63 at the time I posted this question. I'm now using snapshot 72 and the problem has gone. The only advice I can give here is to upgrade the version of Vim that you are using.
Wnen you use irb with auto indent mode, the end statements get indented one level extra
def foo
...
end
instead of showing the ordinary indenting convention:
def foo
...
end
because you cannot tell irb in advance that you are going to escape one level in the next line. This question has been addressed elsewhere like here or here, but neither gives a satisfactory answer. They just suggest giving up.
However, if we can minimally overwrite some irb methods so that auto indent will insert white spaces not in the prompt area but at the beginning of the line you type in, then by default, irb will still be inserting spaces, but we will be able to erase some spaces with backspace. Is this possible?
Or, if that is not realistic, then is it possible to make irb erase the last line from the screen and redisplay it with proper indentation right after you press Enter on a line including end?
Rewriting the last line is possible. Doing it in irb is difficult due to its lack of documentation and consistent api across versions. An irb alternative, ripl, has already solved this issue for itself with an auto-indent plugin. If you want to give ripl and its auto-indenting a try:
$ gem install ripl-auto_indent
$ echo "require 'ripl/auto_indent'" >> ~/.riplrc
# Auto-indent away
$ ripl
>> def foo
>> puts "it's auto-magic!"
>> end
I'm a bit confused with the input's of Ruby.
Whenever I try to get input, it doesn't register the 'Backspace' key. Also, it never accepts the 'Enter' first time. I always have to push 'Enter' after my input usually 3 times before it actually inputs it.
For example,
view source
print?
1 my_var = gets.chomp
If I wanted to enter 'Hello', I would have to type it followed by pressing the return key 3 times before it actually entered it.
Now I did find a way to solve this using...
view source
print?
1 STDOUT.flush
2 my_var = gets.chomp
But...
1) This seems wierd having to enter that EVERY time before I want input?
2) It still doesn't solve the problem of registering backspace.
If I was to type directly 'Hello World' but with two accidental keystrokes such as this: Hello Worpold
Even if I used the backspace so it appeared as I was entering: Hello World
If I then went on to 'puts' or 'print' that it would output: Hello Worpold
Know how I can fix it so it accepts backspace and know any other ways of missing out STDOUT.flush?
Thanks in advance
Use the readline module.
What environment are you running Ruby in ? If you're unsure, check with ruby -v
>ruby -v
ruby 1.8.6 (2008-08-11 patchlevel 287) [i386-mswin32]
I'm running v1.8.6 on Windows XP
a = gets
puts "I just got #{a}"
Saved the above snippet to c:\temp.rb and run it with ruby c:\temp.rb
Backspace key works, I can correct strings before pressing enter once to confirm my input.