sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    How to debug?

    Scheduled Pinned Locked Moved Developers' Forum
    46 Posts 13 Posters 78.3k Views 13 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • PixeroP Offline
      Pixero
      last edited by

      Could you tell me how you debug your ruby scripts?
      I'm using the most basic techique and would like to learn from the pro's.
      I use Notepad++ and when I get an error in the console I check that line number and try to fix the problem.
      I then restart SU and reload my test scene.
      There must be a better/faster way... 😳

      1 Reply Last reply Reply Quote 0
      • TIGT Offline
        TIG Moderator
        last edited by

        @pixero said:

        Could you tell me how you debug your ruby scripts?
        I'm using the most basic techique and would like to learn from the pro's.
        I use Notepad++ and when I get an error in the console I check that line number and try to fix the problem.
        I then restart SU and reload my test scene.
        There must be a better/faster way... 😳

        That's basically the way I do it...
        You need to split you code into parts that fail/succeed and as they succeed you add more functions until one breaks - tht way you know where you made the balls-up and so you can try to fix it... 😕

        TIG

        1 Reply Last reply Reply Quote 0
        • T Offline
          todd burch
          last edited by

          I don't do the "start and stop SU" piece, unless I'm working with menu items. If I have a static scene I'm working with, and the script corrupts it, I'll just delete everything in the scene and reload the model. Then, I reload the script, and keep going. (unless of course there are pieces of the script that require restarting SU, like constant definition changes, etc. During development, I'll usually put logic aroud constant definitions (et al) to not re-execute if they are already defined)

          1 Reply Last reply Reply Quote 0
          • thomthomT Offline
            thomthom
            last edited by

            I use puts thoughout my code when I find issues to track the flow of the data and ensure it is what I expect it to be.
            When I make changes to the script I use use the load method to reload the .rb file without reloading SketchUp.

            Occationally I make changes to the code that requires me to restart SketchUp, but that's rare.

            I also use Jim's Ruby Console plugin that allows me to clear the text of the console - as the more text there is in the console, the slower it performs.

            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund

            1 Reply Last reply Reply Quote 0
            • J Offline
              Jim
              last edited by

              As the others have said, you don't need to close/re-open SketchUp after each minor edit. You can re-load a script from the Ruby Console.

              load "dev/test_script.rb" (Assume you have a dev/ folder in Plugins.)

              From there, you could use a temporary menu and shortcut to reload the script; just enter it in the Ruby Console:

              UI.menu("Plugins").add_item("Reload My Script") { load("dev/test_script.rb") }

              This is how my Ruby Toolbar started - on Windows, it can open/close the Ruby Console, Clear it, and load/reload a file.

              Then for the truly lazy - automatically reloading a script.

              http://forums.sketchucation.com/viewtopic.php?f=180&t=31394
              http://forums.sketchucation.com/viewtopic.php?f=180&t=31463

              Hi

              1 Reply Last reply Reply Quote 0
              • PixeroP Offline
                Pixero
                last edited by

                Thanks for your answers.
                I use a lot of puts too to check values and also Jims Ruby toolbar.
                Seems I'm doing something right. 😒
                About reloading, doesnt that create a duplicate of the plugin name in the plugin menu list?
                I've tried this before and got a new duplicate for each reload.
                Maybe it's because the dev script has a menu?
                Is it "good practice" to NOT create a menu until the script is finished?

                Maybe a "quit_without_save_and_reload_last_used_scene_with_ruby_console_open.rb" button. 😉

                1 Reply Last reply Reply Quote 0
                • TIGT Offline
                  TIG Moderator
                  last edited by

                  If you make your menu code in the script something like this

                  if not file_loaded?(__FILE__)
                     UI.menu("Plugins").add_item("xxxxx"){xxxx.new()}
                  end#if
                  file_loaded(__FILE__)
                  

                  then you only get one menu entry UNLESS you rename the file itself then you'll get another!

                  TIG

                  1 Reply Last reply Reply Quote 0
                  • PixeroP Offline
                    Pixero
                    last edited by

                    Ok, thanks!

                    1 Reply Last reply Reply Quote 0
                    • thomthomT Offline
                      thomthom
                      last edited by

                      Remember to use those file_loaded method you must require 'sketchup.rb' before using them.

                      Thomas Thomassen — SketchUp Monkey & Coding addict
                      List of my plugins and link to the CookieWare fund

                      1 Reply Last reply Reply Quote 0
                      • J Offline
                        Jim
                        last edited by

                        Also, you can define your own version of "puts" which writes the message to a file:

                        
                        def debug_puts(s)
                          File.open("/sketchup_log.txt", "a+") { |fp|  fp.puts(s) }
                        end
                        
                        

                        (Which should work on Windows or Mac.)

                        If on Windows, you could send the output to a system debugger: http://forums.sketchucation.com/viewtopic.php?f=180&t=31216

                        Hi

                        1 Reply Last reply Reply Quote 0
                        • PixeroP Offline
                          Pixero
                          last edited by

                          Wow, I think this thread is turning into something great!
                          Keep 'em coming!

                          1 Reply Last reply Reply Quote 0
                          • AdamBA Offline
                            AdamB
                            last edited by

                            And if you get really stuck as what is going wrong, turning on tracing can be invaluable. That is logging every single call made - it will slow down your script execution to a crawl, so only turn on when needed.

                            (This is a single line of code)

                            set_trace_func proc { |event, file, line, id, binding, classname| File.open("mylogfile","a+") {|fp| fp.write "%8s %s:%-2d %10s %8s\n" % [event, file, line, id, classname]}}

                            From where you put this line onward, every call is logged - so choose a spot when your script does something useful.

                            Developer of LightUp Click for website

                            1 Reply Last reply Reply Quote 0
                            • PixeroP Offline
                              Pixero
                              last edited by

                              @adamb said:

                              And if you get really stuck as what is going wrong, turning on tracing can be invaluable. That is logging every single call made - it will slow down your script execution to a crawl, so only turn on when needed.

                              (This is a single line of code)

                              set_trace_func proc { |event, file, line, id, binding, classname| File.open("mylogfile","a+") {|fp| fp.write "%8s %s:%-2d %10s %8s\n" % [event, file, line, id, classname]}}

                              From where you put this line onward, every call is logged - so choose a spot when your script does something useful.

                              Ah, you seem to have read my mind.
                              I was about to ask something along this line but didn't quite know how to express what I was after. 👍

                              Is there no way of ending it if you want to check something in the middle of a script?

                              1 Reply Last reply Reply Quote 0
                              • thomthomT Offline
                                thomthom
                                last edited by

                                Good one Adam.
                                Jim - one for your Ruby Console plug?

                                Thomas Thomassen — SketchUp Monkey & Coding addict
                                List of my plugins and link to the CookieWare fund

                                1 Reply Last reply Reply Quote 0
                                • thomthomT Offline
                                  thomthom
                                  last edited by

                                  And under Windows you have this snippet to output the data to debuggers like DebugView:
                                  http://forums.sketchucation.com/viewtopic.php?f=180&t=31216&p=274668#p274467

                                  Thomas Thomassen — SketchUp Monkey & Coding addict
                                  List of my plugins and link to the CookieWare fund

                                  1 Reply Last reply Reply Quote 0
                                  • J Offline
                                    Jim
                                    last edited by

                                    If you want to trace specific functions, you can output the caller.

                                    Also, special variables exist for the file and line #:

                                    puts "line no. #{ __LINE__ }" puts "File: #{ __FILE__ }"

                                    But these are less useful in scrambled plugins.

                                    Hi

                                    1 Reply Last reply Reply Quote 0
                                    • Dan RathbunD Offline
                                      Dan Rathbun
                                      last edited by

                                      @jim said:

                                      Because of Ruby's weak typing, the cause of many errors can be detected by simple type checking.

                                      fail unless face.is_a? Sketchup::Face

                                      No output required, so no need to go through later and remove them later unless it's inside a critical loop.

                                      assuming your code is namespaced wrapped (within a module or a class,) what I do is declare local boolean constants like TRACE, DEBUG, POPUP and use them to conditionally execute or not, certain debug statements.

                                      To use Jim's example:
                                      fail unless face.is_a?(Sketchup::Face) && TYPECHECK
                                      where TYPECHECK would be a local boolean constant.
                                      EDIT: actually the code would run faster like:
                                      fail unless TYPECHECK && face.is_a?(Sketchup::Face)

                                      Often I use POPUPS to control debug messagebox calls from inside one of my methods:
                                      UI.messagebox(%[MyModule method:'widget'\n\nArgs:\n#{args.join("\n")}]) if POPUPS
                                      that way I can turn on and off my debug popup dialogs at the top of a module declaration.

                                      I'm not here much anymore.

                                      1 Reply Last reply Reply Quote 0
                                      • J Offline
                                        Jim
                                        last edited by

                                        Because of Ruby's weak typing, the cause of many errors can be detected by simple type checking.

                                        fail unless face.is_a? Sketchup::Face

                                        No output required, so less of a need to go through later and remove them unless it's inside a critical loop.

                                        Hi

                                        1 Reply Last reply Reply Quote 0
                                        • Dan RathbunD Offline
                                          Dan Rathbun
                                          last edited by

                                          @pixero said:

                                          @adamb said:

                                          And if you get really stuck as what is going wrong, turning on tracing can be invaluable.
                                          set_trace_func proc { |event, file, line, id, binding, classname| File.open("mylogfile","a+") {|fp| fp.write "%8s %s:%-2d %10s %8s\n" % [event, file, line, id, classname]}}

                                          From where you put this line onward, every call is logged - so choose a spot when your script does something useful.

                                          Is there no way of ending it if you want to check something in the middle of a script?

                                          Yes there is.
                                          set_trace_func(nil)

                                          This method is actually defined in the Kernel module, which is mixed-in to Object class, and therefore inherited by all other clases and modules.
                                          So for it's reference, see Kernel.set_trace_func in the Ruby Core Reference (CHM.)

                                          One reason Adam's example is slow, is that it has to open the logfile, write a line to it, then close the file for safety, in case of an exception.

                                          HOWEVER.. the block can be any Ruby code. If you are only interested in certain events such as a call to a ruby method, then you can test for that using an if clause, and ignore all other events, so as to speed up tracing.

                                          <span class="syntaxdefault">def start_logging</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">stopclass</span><span class="syntaxkeyword">=</span><span class="syntaxstring">''</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">stopmethod</span><span class="syntaxkeyword">=</span><span class="syntaxstring">''</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  set_trace_func proc </span><span class="syntaxkeyword">{</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">|</span><span class="syntaxdefault">event</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> file</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> line</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> id</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> binding</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> classname</span><span class="syntaxkeyword">|<br /></span><span class="syntaxdefault">    if event</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_s</span><span class="syntaxkeyword">==</span><span class="syntaxstring">'call'<br /></span><span class="syntaxdefault">      File</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">open</span><span class="syntaxkeyword">(</span><span class="syntaxstring">"mylogfile"</span><span class="syntaxkeyword">,</span><span class="syntaxstring">"a+"</span><span class="syntaxkeyword">)</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">{|</span><span class="syntaxdefault">fp</span><span class="syntaxkeyword">|<br /></span><span class="syntaxdefault">        fp</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">write </span><span class="syntaxstring">"%8s %s;%-2d %10s %8s\n"</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">%</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">[</span><span class="syntaxdefault">event</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> file</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> line</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> id</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> classname</span><span class="syntaxkeyword">]<br /></span><span class="syntaxdefault">      </span><span class="syntaxkeyword">}<br /></span><span class="syntaxdefault">      </span><span class="syntaxcomment"># stop logging if it was stopclass and stopmethod<br /></span><span class="syntaxdefault">      stop_logging if classname</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_s</span><span class="syntaxkeyword">==</span><span class="syntaxdefault">stopclass</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_s </span><span class="syntaxkeyword">&&</span><span class="syntaxdefault"> id</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_s</span><span class="syntaxkeyword">==</span><span class="syntaxdefault">stopmethod</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_s<br />    end<br />  </span><span class="syntaxkeyword">}<br /></span><span class="syntaxdefault">end<br /><br />def stop_logging<br />  set_trace_func</span><span class="syntaxkeyword">(</span><span class="syntaxdefault">nil</span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">end</span>
                                          
                                          • example only

                                          P.S. @ThomThom (in regards to another topic on overriding API methods,) this method is one of the ways you can trace a method back to the file that overrode it.

                                          I'm not here much anymore.

                                          1 Reply Last reply Reply Quote 0
                                          • J Offline
                                            Jim
                                            last edited by

                                            You could set an environmental variable, then enable/disable debugging based on it. By using a unique variable name, you can gurantee debugging is enabled only on the machine you are working on.

                                            Hi

                                            1 Reply Last reply Reply Quote 0
                                            • 1
                                            • 2
                                            • 3
                                            • 1 / 3
                                            • First post
                                              Last post
                                            Buy SketchPlus
                                            Buy SUbD
                                            Buy WrapR
                                            Buy eBook
                                            Buy Modelur
                                            Buy Vertex Tools
                                            Buy SketchCuisine
                                            Buy FormFonts

                                            Advertisement