# End of input error

**URL:** <https://forums.sketchup.com/t/end-of-input-error/118882>\
**Category:** Ruby API\
**Tags:** error\
**Created:** [March 14, 2020, 9:58pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882 "2020-03-14T21:58:40Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![caydenwilson017](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/caydenwilson017/32/70340_2.png) [@caydenwilson017](https://forums.sketchup.com/u/caydenwilson017)\
**Post date:** [March 14, 2020, 9:58pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/1 "2020-03-14T21:58:40Z")

</div>

I keep getting this error…what am I doing wrong?

**Error**

Error: #\<NameError: undefined local variable or method `sketchup\_extension’ for CaydenWilson::ProTrim:Module\>

:22:in `' :10:in `' :9:in `' SketchUp:1:in `eval'

**Code**

```auto
#Loading in handles
model=Sketchup.active_model
selection=Sketchup.active_model.selection
entities=Sketchup.active_model.entities
materials=Sketchup.active_model.materials
layer_array=Sketchup.active_model.layers

require "sketchup.rb"

module CaydenWilson
  module ProTrim

    #Input to gather data for trim
    prompts=["Trim Height: ", "Trim Thickness:", "Quarter Round:", "R:", "G:", "B:"]
    defaults=[5.0,0.5,"No",255.0,255.0,255.0]
    list=["","","Yes|No","","",""]
    input=UI.inputbox prompts, defaults, list, "ProTrim"
      height,thickness,quarter_round,red,green,blue=input
    if quarter_round=='Yes'
      quarter_round_width=0.75
      quarter_round_height=0.75
    end
    notification=UI::Notification.new(sketchup_extension, "Select the trim path.")
    notification.show

    def get_points(axis, height, thickness)
      case axis
      when X_AXIS
        [[0,0,0], [0,0,height], [thickness,0,0], [thickness,0,height] ]
      when Y_AXIS
        [[0,0,0], [0,0,height], [0,thickness,0], [0,thickness,height] ]
      end
    end

    def create_trim_material(materials)
      trim_material=Sketchup.active_model.materials.add "Trim"
      trim_material.color=[red, green, blue]
      trim_group.material=trim_material
    end

    def build_trim(axis, selection, height, thickness)
      pts=get_points(axis, height, thickness)
      #Creating a face using array
      face=entities.add_face(pts)
      edges = face.edges
      connected=face.all_connected
      face.back_material = "Trim"
      material = trim.back_material
      face.material = trim
      #Selecting edges (path) to extrude on
      face.followme( selection.grep(Sketchup::Edge) )
    end

    def create_trim_layer(layer_array, entities)
      new_layer=model.layers.add ("Trim")
      model.active_layer=new_layer
      name=trim
      visable=True
    end
  end
end
```

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [March 14, 2020, 10:23pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/2 "2020-03-14T22:23:37Z")

</div>

add `end` to close the top module…

john

---

<div class="post-metadata">

**Author:** ![caydenwilson017](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/caydenwilson017/32/70340_2.png) [@caydenwilson017](https://forums.sketchup.com/u/caydenwilson017)\
**Post date:** [March 14, 2020, 10:25pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/3 "2020-03-14T22:25:45Z")

</div>

I did before…it still throws me an error…

---

<div class="post-metadata">

**Author:** ![slbaumgartner](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/slbaumgartner/32/7302_2.png) [@slbaumgartner](https://forums.sketchup.com/u/slbaumgartner)\
**Post date:** [March 14, 2020, 10:44pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/4 "2020-03-14T22:44:14Z")

</div>

There’s no end for the if statement near the top.

---

<div class="post-metadata">

**Author:** ![john\_drivenupthewall](https://avatars.discourse-cdn.com/v4/letter/j/c67d28/32.png) [@john\_drivenupthewall](https://forums.sketchup.com/u/john_drivenupthewall)\
**Post date:** [March 14, 2020, 10:44pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/5 "2020-03-14T22:44:17Z")

</div>

move the handles into the module?

john

---

<div class="post-metadata">

**Author:** ![caydenwilson017](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/caydenwilson017/32/70340_2.png) [@caydenwilson017](https://forums.sketchup.com/u/caydenwilson017)\
**Post date:** [March 14, 2020, 10:47pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/6 "2020-03-14T22:47:26Z")

</div>

Now I’m getting variable errors when I run it…any idea? Inputbox appears and data is able to be imputed, but once ok is clicked I get these errors

Error: #\<NameError: undefined local variable or method `sketchup\_extension’ for CaydenWilson::ProTrim:Module\>

:22:in `' :10:in `' :9:in `' SketchUp:1:in `eval'

---

<div class="post-metadata">

**Author:** ![caydenwilson017](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/caydenwilson017/32/70340_2.png) [@caydenwilson017](https://forums.sketchup.com/u/caydenwilson017)\
**Post date:** [March 14, 2020, 10:51pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/7 "2020-03-14T22:51:07Z")

</div>

Doesn’t seem to be an issue…but I’ll try it! 😉

---

<div class="post-metadata">

**Author:** ![slbaumgartner](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/slbaumgartner/32/7302_2.png) [@slbaumgartner](https://forums.sketchup.com/u/slbaumgartner)\
**Post date:** [March 14, 2020, 11:40pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/8 "2020-03-14T23:40:00Z")

</div>

> [@caydenwilson017](#):
>
> Error: #\<NameError: undefined local variable or method `sketchup\_extension’ for CaydenWilson::ProTrim:Module\>

UI.Notification is designed to be used with reference to a SketchupExtension object. The first argument to UI.Notification.new (named sketchup\_extension) must be a reference to a SketchupExtension object _that your code has created and registered with the Sketchup engine._ Consult the API documentation about SketchupExtension.

Side note: to avoid the forum markup engine mangling error messages, put triple backtick on the lines before and after where you paste the error messages. The \< and \> characters otherwise are taken as markup tags and create a mess.

---

<div class="post-metadata">

**Author:** ![caydenwilson017](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/caydenwilson017/32/70340_2.png) [@caydenwilson017](https://forums.sketchup.com/u/caydenwilson017)\
**Post date:** [March 14, 2020, 11:41pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/9 "2020-03-14T23:41:42Z")

</div>

Perfect! Didn’t know I should do that.

---

<div class="post-metadata">

**Author:** ![slbaumgartner](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/slbaumgartner/32/7302_2.png) [@slbaumgartner](https://forums.sketchup.com/u/slbaumgartner)\
**Post date:** [March 15, 2020, 12:12am UTC](https://forums.sketchup.com/t/end-of-input-error/118882/10 "2020-03-15T00:12:36Z")

</div>

By the way, I agree with @john_drivenupthewall that the “handles” should be inside the module, not at the global level. You never know when global variables will collide with ones someone else defined!

---

<div class="post-metadata">

**Author:** ![Aerilius](https://avatars.discourse-cdn.com/v4/letter/a/e19b73/32.png) [@Aerilius](https://forums.sketchup.com/u/Aerilius)\
**Post date:** [March 15, 2020, 12:35am UTC](https://forums.sketchup.com/t/end-of-input-error/118882/11 "2020-03-15T00:35:21Z")

</div>

Best they would be in a method. You won’t be able to access these local variables anyways from other methods.

Create a method to wrap all orphan code.

```auto
module CaydenWilson
  module ProTrim
    def init
      model = Sketchup.active_model # Use spaces around operators
      selection = model.selection # Use the same model reference
      # …
      prompts = ["Trim Height: ", "Trim Thickness:", "Quarter Round:", "R:", "G:", "B:"]
      # …
      notification.show
    end
    # …
    self.init # Instead of calling it here, you can do this in a menu item's command handler.
  end
end

```

Then call the method.

Now you have more flexibility and control to run this code when you need it. You probably don’t want to force this notification onto the user when SketchUp starts.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [March 15, 2020, 1:59pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/12 "2020-03-15T13:59:37Z")

</div>

> [@caydenwilson017](#):
>
> Perfect! Didn’t know I should do that.

> [@slbaumgartner](#):
>
> UI.Notification is designed to be used with reference to a [`SketchupExtension`](http://ruby.sketchup.com/SketchupExtension.html) object.

Yes, and I’ve told Cayden previously **not** to use [`UI::Notification`](http://ruby.sketchup.com/UI/Notification.html) objects.  
They are not designed to be used for workflow prompts (and their display time cannot be controlled [yet.])  
Cayden should use normal modal [messageboxes](http://ruby.sketchup.com/UI.html#messagebox-class_method) instead.

(Cayden, FYI, **modal** means that the [messagebox](http://ruby.sketchup.com/UI.html#messagebox-class_method) or dialog seizes the focus and does not release it until the user dismisses the window.)

* * *

With regard to the [`SketchupExtension`](http://ruby.sketchup.com/SketchupExtension.html) object, it’s registrar file is a separate file that goes in the “Plugins” folder. All your extensions other files go in a subfolder that has the same name as the registrar file.  
If the extension registrar file is **`"CaydenWilson_ProTrim.rb"`** then your extension subfolder must be named **`"CaydenWilson_ProTrim"`**.

> [@caydenwilson017](#):
>
> > [@john\_drivenupthewall](#):
> >
> > move the handles into the module?
> 
> Doesn’t seem to be an issue…but I’ll try it!

The handles are not an issue because your code is **not** using them.

The most prime rule for coding in a shared ObjectSpace is that ALL YOUR CODE MUST be within your toplevel namespace module (ie, the `CaydenWilson` module in the above example,) and any code specific to a CERTAIN EXTENSION should ALL be within that extension’s submodule (in the example the `CaydenWilson::ProTrim` submodule.)

Even the lonely …

```ruby
require "sketchup.rb"

```

… method call can be within your modules. It is a frivolous call because the SketchUp engine loads **it** (and the other `"Tools"` subfolder files `"extensions.rb"` and `"langhandler.rb"`) during the startup cycle ever since the release of SketchUp 2014. These loads happen before **any** extensions ever begin to load.

> [@caydenwilson017](#):
>
> Now I’m getting variable errors when I run it…any idea? Inputbox appears and data is able to be imputed, but once ok is clicked I get these errors

You do not “run” code like this (ie, a module definition) repeatedly in an event-driven programming environment. Instead the module is loaded at startup and waits for an event to fire off the display of the inputbox.

The event will be the user either choosing a command from a menu or clicking a toolbar button. So this means you need a “eval once” block at the bottom of your module that creates the UI elements (your extension’s submenu and /or toolbar and the command objects that will be attached to the menu items and toolbar buttons.)

```auto
    if !@loaded
      submenu = UI.menu("Extensions").add_submenu("ProTrim")
      cmd = UI::Command.new("Build Trim") { build_trim_command() }
      submenu.add_item(cmd)
      # Set the @loaded var to true so this block is only evaluated ONCE:
      @loaded = true
    end

```

Such a block that evaluates only once, will prevent multiple submenus, menu items and toolbars, etc., from getting created, if you tweak your code and need to reload it during development.

Reference class documentation for:

- [`UI::Command`](http://ruby.sketchup.com/UI/Command.html)
- [`UI::Toolbar`](http://ruby.sketchup.com/UI/Toolbar.html)
- [`Sketchup::Menu`](http://ruby.sketchup.com/Sketchup/Menu.html)

* * *

So as shown in the eval once block above, you need a command method that will be fired by the user when they start your command. I called it `"build_trim_command()"`but you can name it what you like.

**Put the inputbox code inside this method.**

Also I’ve told you repeatedly, you **must always** check that the return value from the input box is “truthy” (ie only two things in Ruby are falsehoods and these are **`false`** and **`nil`**. Everything else evals booleanwise as a truth.)  
So this means that if the user cancels the inpubox then the variable **`input`** will eval as a falsehood.  
If the user enters values (or accepts the default values) and clicks OK, then **`input`** will be an array instance and eval as a truth, so your subsequent code can go ahead and treat it as an array of values.  
A simple one liner inserted just after the call to `UI.inpubox` would be …

```ruby
return unless input

```

It tests that **`input`** evals as **`true`** (and therefore cannot be **`false`** or **`nil`** ,) and so must be an array instance. If the user has cancelled the inputbox, your code should assume the user wishes to cancel the command, and so the **`return`** statement will exit the method, and nothing will happen.

Some extensions do display a “Command Cancelled” messagebox, just so the user knows their cancel has worked and they know nothing in they model changed. (Your code, your choice.)

* * *

**Lastly** , in order for your methods to call each other without qualification, you need to extend the module with itself. Put this statement at the top of the module.

```ruby
extend self

```

---

<div class="post-metadata">

**Author:** ![caydenwilson017](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/caydenwilson017/32/70340_2.png) [@caydenwilson017](https://forums.sketchup.com/u/caydenwilson017)\
**Post date:** [March 15, 2020, 10:53pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/13 "2020-03-15T22:53:33Z")

</div>

Sorry about the notification being in there…I edited the file and forgot to save it, and then didn’t fix that. I think I’ve fixed the code to what you’ve been saying…I just need to figure out how to execute the face build/follow me if the user clicks OK in the messagebox. Also, I keep getting an error on my toolbar section…and my icons do not appear on my toolbar or as an option to add to my toolbar. Thanks for your help!

```auto
module CaydenWilson
  module ProTrim

    extend self

    def init
      #Loading in handles
      model=Sketchup.active_model
      selection=Sketchup.active_model.selection
      entities=Sketchup.active_model.entities
      materials=Sketchup.active_model.materials
      layer_array=Sketchup.active_model.layers

      require 'sketchup.rb'
      require 'extensions.rb'

      pro_trim=SketchupExtension.new('ProTrim", "ProTrim/base.rb"')
      pro_trim.version='1.0'
      Sketchup.register_extension(pro_trim, true)

      self.init
    end

    def get_points(axis, height, thickness)
      case axis
      when X_AXIS
        [[0,0,0], [0,0,height], [thickness,0,0], [thickness,0,height] ]
      when Y_AXIS
        [[0,0,0], [0,0,height], [0,thickness,0], [0,thickness,height] ]
      end
    end

    def create_trim_material(materials)
      trim_material=Sketchup.active_model.materials.add "Trim"
      trim_material.color=[red, green, blue]
      trim_group.material=trim_material
    end

    def build_trim(axis, selection, height, thickness)
      #Input to gather data for trim
      prompts=["Trim Height: ", "Trim Thickness:", "Quarter Round:", "R:", "G:", "B:"]
      defaults=[5.0,0.5,"No",255.0,255.0,255.0]
      list=["","","Yes|No","","",""]
      input=UI.inputbox prompts, defaults, list, "ProTrim"
      return unless input
        height,thickness,quarter_round,red,green,blue=input
      if quarter_round=='Yes'
        quarter_round_width=0.75
        quarter_round_height=0.75
      end
      message="Select edges for your trim path."
      result=UI.messagebox(message, MB_OKCANCEL)
      if result==IDCANCEL
        return
      end
      pts=get_points(axis, height, thickness)
      #Creating a face using array
      face=entities.add_face(pts)
      edges = face.edges
      connected=face.all_connected
      face.back_material = "Trim"
      material = trim.back_material
      face.material = trim
      #Selecting edges (path) to extrude on
      face.followme( selection.grep(Sketchup::Edge) )
    end

    def create_trim_layer(layer_array, entities)
      new_layer=model.layers.add ("Trim")
      model.active_layer=new_layer
      name=trim
      visable=True
    end
    if !@loaded
      submenu = UI.menu("Extensions").add_submenu("ProTrim")
      toolbar=UI::Toolbak.new "ProTrim"
      cmd = UI::Command.new("Build Trim") { init() }
      cmd.small_icon="IconSmall.png"
      cmd.large_icon="IconLarge.png"
      cmd.menu_text="ProTrim"
      toolbar.add_item cmd
      toolbar.show
      submenu.add_item(cmd)
      # Set the @loaded var to true so this block is only evaluated ONCE:
      @loaded = true
    end
  end
end
```

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [March 15, 2020, 10:56pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/14 "2020-03-15T22:56:29Z")

</div>

Once again you are listening … reread what was written.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [March 15, 2020, 11:15pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/15 "2020-03-15T23:15:04Z")

</div>

> [@caydenwilson017](#):
>
> ```ruby
> toolbar=UI::Toolbak.new "ProTrim"
> 
> ```

There is NO class named `UI::Toolbak` … it’s `UI::Toolbar`.

> [@caydenwilson017](#):
>
> and my icons do not appear on my toolbar

You may need to use absolute paths to the icon files, or relative paths from the Plugins folder. I can’t remember which.

The Ruby global function ` __FILE__ ` returns the absolute path to the file it is called from.  
The Ruby global function ` __dir__ ` returns the absolute directory path where the file it’s called from is located.  
So if the icon files are in the same folder …

```ruby
cmd.small_icon = File.join( __dir__ ,"IconSmall.png")

```

If they were in an `"images"` subfolder from where the file is …

```ruby
cmd.small_icon = File.join( __dir__ ,"images","IconSmall.png")

```

* * *

```ruby
cmd = UI::Command.new("Build Trim") { init() }

```

Andreas gave you some general advice that does not apply in this case.  
**You don’t need anything in the init() method. Delete it.**

And (as said above) the following …

```ruby
module CaydenWilson
  module ProTrim
    pro_trim = SketchupExtension.new('ProTrim", "CaydenWilson_ProTrim/base.rb"')
    pro_trim.version = '1.0'
    pro_trim.description = 'Professioanl Trim Building extension.'
    pro_trim.creator = 'Cayden Wilson'
    pro_trim.copyright = '2020'
    Sketchup.register_extension(pro_trim, true)
  end
end

```

… all goes into a registrar file named **`"CaydenWilson_ProTrim.rb"`** outside your extension subfolder, which **must** be named **`"CaydenWilson_ProTrim"`**.

The registrar file gets installed into the “Plugins” folder, and is automatically run by SketchUp at startup to register your extension.

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [March 15, 2020, 11:21pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/16 "2020-03-15T23:21:45Z")

</div>

> [@caydenwilson017](#):
>
> new\_layer=model.layers.add (“Trim”)

Do not insert spaces between a method name and it’s argument list. This will usually cause a warning.

There is **no** good reason for Ruby code to change the active layer (tag). **ALL geometric primitives** should always be untagged (associated with “Layer0”.) Only the trim groups or components should be assigned to other layer/tags.

* * *

Also you are not helping the interpreter or **US** to read your code by omitting spaces before and after operators.

---

<div class="post-metadata">

**Author:** ![Aerilius](https://avatars.discourse-cdn.com/v4/letter/a/e19b73/32.png) [@Aerilius](https://forums.sketchup.com/u/Aerilius)\
**Post date:** [March 16, 2020, 8:12am UTC](https://forums.sketchup.com/t/end-of-input-error/118882/17 "2020-03-16T08:12:13Z")

</div>

> [@caydenwilson017](#):
>
> ```ruby
> def init
> # …
> self.init
> end
> 
> ```

Once the method is called you have infinite recursion… but it is never called.

---

<div class="post-metadata">

**Author:** ![caydenwilson017](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/caydenwilson017/32/70340_2.png) [@caydenwilson017](https://forums.sketchup.com/u/caydenwilson017)\
**Post date:** [March 16, 2020, 2:25pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/18 "2020-03-16T14:25:20Z")

</div>

I fixed all the spaces for better readability…Its been a bad habit of mine not using them previously. Also, I am going to look into creating a group for the trim, which has always been my intention.

---

<div class="post-metadata">

**Author:** ![caydenwilson017](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/caydenwilson017/32/70340_2.png) [@caydenwilson017](https://forums.sketchup.com/u/caydenwilson017)\
**Post date:** [March 16, 2020, 2:27pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/19 "2020-03-16T14:27:07Z")

</div>

When you say I don’t need anything in the `init` method, do you mean to delete the handles or do you mean to just remove the `init` method?

---

<div class="post-metadata">

**Author:** ![DanRathbun](https://sea2.discourse-cdn.com/sketchup/user_avatar/forums.sketchup.com/danrathbun/32/500_2.png) [@DanRathbun](https://forums.sketchup.com/u/DanRathbun)\
**Post date:** [March 16, 2020, 2:40pm UTC](https://forums.sketchup.com/t/end-of-input-error/118882/20 "2020-03-16T14:40:09Z")

</div>

> [@caydenwilson017](#):
>
> do you mean to just remove the `init` method?

Yes remove the whole method. Why would you need a method if it’s not needed or it’s empty of code ?

[Next page](https://forums.sketchup.com/t/end-of-input-error/118882.md?page=2)
