I’m not clear how Mojave is relevant? It doesn’t change how SketchUp’s Ruby interpreter or API methods behave…
I know it shouldn’t, but…
maybe, an extension is redefining stdout
?
john
I hope not! That will almost surely break the Ruby Console!
Just unloaded all plugins and extensions… same thing.
what returns for
SKETCHUP_CONSOLE.private_methods
SKETCHUP_CONSOLE.private_methods
[:file_loaded?, :file_loaded, :add_separator_to_menu, :inputbox, :require_all, :show_ruby_panel, :puts, :runNudgeStackUndo, :Digest, :initialize_copy, :initialize_dup, :initialize_clone, :sprintf, :format, :Integer, :Float, :String, :Array, :Hash, :warn, :raise, :fail, :global_variables, :method, :callee, :dir, :eval, :local_variables, :iterator?, :block_given?, :catch, :throw, :loop, :respond_to_missing?, :trace_var, :untrace_var, :at_exit, :syscall, :open, :printf, :print, :putc, :gets, :readline, :select, :readlines, :`, :p, :test, :srand, :rand, :trap, :load, :require, :require_relative, :autoload, :autoload?, :proc, :lambda, :binding, :caller, :caller_locations, :exec, :fork, :exit!, :system, :spawn, :sleep, :exit, :abort, :Rational, :Complex, :set_trace_func, :gem, :gem_original_require, :initialize, :singleton_method_added, :singleton_method_removed, :singleton_method_undefined, :method_missing]
SKETCHUP_CONSOLE == $stdout
should return true…
does pp 'digging'
work…
john
> SKETCHUP_CONSOLE == $stdout
true
> pp 'digging'
Error: #<NoMethodError: undefined method `pp' for main:Object>
<main>:in `<main>'
SketchUp:1:in `eval'
and that crashed SU.
Have I missed something? The return value of a method is shown on the Ruby console only if control returns to the console. Otherwise it just goes to whatever invoked the method.
but the puts
issue?
Going to create a separate issue about puts
… this thread was about abort.
still getting crashes and not stopping code from:
def self.z_die
# grab the current model
my_model = Sketchup.active_model
my_model.abort_operation
print "script killed\n"
return nil
end #def
This works… its ugly an feels wrong but at least it kills the script!
def self.z_die
print fake_var
end #def
hopefully we will find your real issue, in the other thread…
I’ll clarify that 6 yr old thread.
The OP was not clear on how his code was contained. TIG assumed it must be (or should be) contained within a method at the very least, … and I myself said so. So I did not really disagree with TIG. ALL code should be contained within your Author module namespace, and within it’s subdivisons of modules, classes and their methods.
So, using a conditional return
statement is the easiest and most normal way to short circuit a method.
This thread is quite old and community coding standards have evolved over the years. It is sometimes considered (by some coding style guides) to be “bad form” to use exception handling to accomplish conditional branching, even though some of the best Ruby books describe doing just that (such as the old “Pick Axe” book,) by raising custom exception “on the fly”. See Chapter: Exceptions, Catch and Throw
It might have seemed like a disagreement but wasn’t really. Just two suggestions taking different tacks.
Note that there was a third that was basically void as it assumed the user was coding a tool which they were not.
So I really do agree with TIG. Don’t use #exit
()
as it is designed for standalone Ruby running in it’s own process not an embedded Ruby running under another application’s process. Back in the early days when SketchUp used Ruby 1.8.x I seem to also remember using Kernel#exit()
would crash SketchUp.
I know I said THEN in that thread that my idea was the answer but that was only if the OP insisted on using #exit()
which needs to trap the SystemExit
exception. BUT, … we’ve since all come to agree that using #exit
is terribly bad form and is not meant for embedded Ruby. The old Google Groups are now locked and read-only so we cannot edit our posts or add to those old discussions.
I reality, from a method, return
is the keyword to use along with a conditional statement.
A simple question like this should use the UI.messagebox
method (see below).
Your expectations here are incorrect. This API method is not about abort code per se, it’s about aborting changes made to the model data (ie an abort of an undoable geometric operation.)
In your example, the easiest way is …
def some_script()
response = UI.messagebox( "Question?", MB_YESNO )
return unless response == IDYES
# things to do ....
Generally, … SketchUp code is event-driven code and not linear command script. You seem to be stuck in the latter kind of thinking.
Even if you are coding a menu item command that runs in a linear do it then exit fashion, it still helps to divide up the code into small chunks (as methods) for maintainability, within a module of class.
A note about your code snippets. Ruby uses 2 space indents (not 4.)
Outdenting totally sucks! Please don’t post code when the nesting levels are all lined up. It makes it much harder to read and understand.
I get the 2 spaces thing. My code editor uses 4 and its more legible on my system but I have no idea what the outdenting thing means.
Whats wrong with…
def some_def
#some code
#some more code
end
which is the format I’m (trying) to adhere to. What does “all lined up” mean?
Thanks.
Thanks Dan.
Yes, I think that seems to be the issue here! In PHP, I could write a single long function and catch problems along the way anywhere I wanted. The Ruby approach of breaking everything up as much as possible is new to me.
So you are saying if I have 10 things I need a script to do and 5 of them involve some sort of gate-keeping function like “something with that name was found” that I need 5 defs to do it?
Another way of saying that is only one gate-keeping check per def.
In your example, that would translate to…
def some_script()
response = UI.messagebox( "Question?", MB_YESNO )
return unless response == IDYES
# things to do ....
# if any of these things to do involve
# checks that might return nil
# dont do it!
# they should be in their own defs
end
(Incidentally, I count that you indented that code snippet with 4 spaces when I think you said it should be 2? Maybe my Mac is converting your tabs to 4 spaces or something.)
Please, read, if it has already been explained.
Did you try to understand what you are doing there and why it seemingly “works”?
I did and thank you for all the info. It is very informative. As far as solving the specific issue I am trying to understand…
- return: yes, basically what I was looking for but not the complete answer since return needs to be paired with something else like unless or if in a specific way as in:
def some_script()
response1 = UI.messagebox( "Question 1?", MB_YESNO )
return unless response == IDYES
# OR
return if(response != IDYES)
# some code
end
- raise: still researching as you did not provide an example and the difference with return is not clear to me from your descriptions. Again, looks like it needs to be paired with a conditional.
- break: for loops and procs not gatekeeping
- end: not the issue
- exit: don’t use it as has been discussed.
- Sketchup::Model#abort_operation: pertinent but not exactly the issue
OF COURSE! That is why we are here. You could also have responded with ‘Google it’ but that would not be very helpful, would it.
Return just does an ordinary (duh!) return of control to whatever called a method, just as if you reached the end. The only difference is that you can code it anywhere in the flow of the method instead of just having it happen automatically when you reach end.
Raise invokes an entirely different mechanism: exceptions. When an Exception is raised, Ruby examines back up the chain of method invoked method etc looking for one that has a rescue statement for the kind of exception that was raised. If none is found, Ruby invokes the interpreter’s default rescue, which prints a message and terminates your code. As you can guess from that description, exceptions are a pretty heavyweight mechanism meant for catching situations that weren’t supposed to happen but somehow did anyway, that is bugs.
OK now THAT makes perfect sense! Thank you!
I think my need in this case is strictly the return
scenario as I just want to check if
- the user wants to proceed
- certain objects/entities are found in the model
Thanks again everyone.