Is it possible to show pint statements inside an app?

I have an app I created and it has a debugger mode that provides some useful info but I was wondering if I can show a console type thing inside the app itself? I would love to be able to see print statements on the fly without having to have the device hooked up to a computer. 

Hi there,

This is definitely possible. It’s not something I’d thought of until now, but I’m gonna whip up a quick module to display print statements on-device (so you can drop it into your project with one line of code). Give me at least a few hours, possibly a day. The first iteration may be a little rough around the edges, but it’ll work. Stay tuned.

Ohh wow that’s even more then I was expecting! Thanks for the generosity. 

fwiw you can redefine print() to do whatever you want instead (should first save a ref to the original), fe:

local original\_print = print -- save function print(...) -- redefine local txt = table.concat(arg," ") someTextObject.text = txt -- show that text somewhere in your app original\_print(unpack(arg)) -- optional: call original to print as before end

@davebollinger: that’s the core of what I’m packing into my module, but I’m taking this as an opportunity to make a nice-looking (and show/hide-able) on-screen console. :slight_smile:

Hi @dmglakewood:

Here you go! I whipped up a simple little module that you can plug in by simply adding one lua file to your project directory, and one line of code to your main.lua. Just drop onScreenPrint.lua (from the attached zip file: ) into your project’s root directory (alongside main.lua ) and add this line of code to your main.lua :

[lua]

local onScreenPrint = require(“onScreenPrint”)

[/lua]

onScrenPrintPreview.png

The module adds in a “print console” that takes up the lower 1/4 of your device’s screen and displays any print statements along with a timestamp. Traditional “offscreen” print statements will still be generated as well.

The on-screen print statements will text-wrap so that they don’t go off the screen, and the console is scrollable, so you can go back and re-read earlier statements. Tap the bar along the top of the console to show or hide the console. Hiding it takes it down to 50% alpha, and just along the bottom of the device screen. Any time a new print statement is generated, the console automatically scrolls to that new statement. 

I think I’ll add this to my website as a tutorial next week, and maybe add the ability to copy a print statement to the device’s pasteboard. I didn’t include that functionality here, partly because I didn’t want to spend too much time on it today, and partly because I wanted to keep the module very lightweight. Thanks for prompting this fun little exercise! It’s just what I needed to clear my head today. :slight_smile:

Here is the content of onScreenPrint.lua, in case you are interested:

[lua]


– CREATE TABLE TO HOLD MODULE FUNCTIONS


local onScreenPrint = {}


– REQUIRE WIDGET LIBRARY


local widget = require(“widget”)


– DEFINE LOCAL VARIABLES


local centerX = display.contentCenterX

local centerY = display.contentCenterY

local screenTop = math.floor(display.screenOriginY)

local screenLeft = math.floor(display.screenOriginX)

local screenBottom = display.contentHeight - screenTop

local screenRight = display.contentWidth - screenLeft

local screenWidth = screenRight - screenLeft

local screenHeight = screenBottom - screenTop

local fontSize = screenHeight*.03


– CREATE ON-SCREEN CONSOLE TO DISPLAY PRINT STATEMENTS


local group = display.newGroup()

local bg, scrollView, button, buttonTap

bg = display.newRect(group, centerX, screenBottom, screenWidth, screenHeight * .25 + fontSize*2)

bg.anchorX, bg.anchorY = .5, 1

bg:setFillColor(0, 22/255, 10/255, .5)

bg:addEventListener(“touch”, function() return true end)

bg:addEventListener(“tap”, function() return true end)

scrollView = widget.newScrollView({

     top = screenBottom - screenHeight*.25 + fontSize*.5,

     left = screenLeft,

     width = screenWidth,

     height = screenHeight*.25 - fontSize,

     hideBackground = true,

})

scrollView.lastY = 0

group:insert(scrollView)

function buttonTap(event)

     if group.y <= 0 then

          transition.cancel(group)

          transition.to(group, {y = bg.height - fontSize, alpha = .5, transition = easing.outBack})

     else

          transition.cancel(group)

          transition.to(group, {y = 0, alpha = 1, transition = easing.inBack})

     end

     group:toFront()

end

button = widget.newButton({

     label = “↑ print console ↓”,

    --properties for a rounded rectangle button…

    shape=“rect”,

    width = screenWidth,

    height = fontSize*1.5,

    fontSize = fontSize,

    font = “Courier”,

    fillColor = { default={ 0, 22/255, 10/255, .5 }, over={ 0, 22/255, 10/255, .5 } },

    labelColor = { default={ 1, 1, 1, 1 }, over={ 1, 1, 1, 1 } },

    onRelease = buttonTap,

})

group:insert(button)

button.x, button.y = centerX, screenBottom - bg.height

button.anchorX, button.anchorY = .5, 0


– ADD NEW STATEMENT TO CONSOLE


local function newStatement(statement)

     local time = os.date("%I")…":"…os.date("%M")…":"…os.date("%S")

     local text = display.newText({

          text = time…": "…statement,

          x = centerX,

          y = scrollView.lastY,

          width = bg.width - fontSize,

          height = 0,

          font = “Courier”,

          fontSize = fontSize,

          align = “left”,

     })

     text.anchorX, text.anchorY = .5, 0

     text:setFillColor(20/255, 246/255, 119/255)

     

     local box = display.newRect(text.x, text.y - fontSize*.25, bg.width - fontSize*.25, text.height + fontSize*.5)

     box.anchorX, box.anchorY = text.anchorX, text.anchorY

     box:setFillColor(10/255, 122/255, 58/255, .5)

     

     scrollView:insert(box)

     scrollView:insert(text)

     scrollView.lastY = box.y + box.height + fontSize

     

     scrollView:scrollToPosition({x = 0, y = -box.y})

     group:toFront()

end


– AMEND PRINT() TO INCLUDE ON-SCREEN PRINTING & RETURN MODULE


_G.oldPrint = print

print = function(statement)

     _G.oldPrint(statement)

     newStatement(statement)

     

end

return onScreenPrint

[/lua]

This is something I have saved for future use but not tried yet: 

http://forums.coronalabs.com/topic/50004-corona-advanced-logging/#entry258805

Remote debugging over network from Lerg (link not working though): http://spiralcodestudio.com/corona-sdk-pro-tip-of-the-day-22/

This is way more amazing then I was expecting. Great work!

I found a bug in your script schroederapps your print will only accept 1 variable but the real print accepts any number of variables. So if you do:

print(“test”, “test2”, “test3”)

only test will show not the other two. I fixed this with the following. (Thanks to davebollinger for his post above showing the args)
 

  1. _G.oldPrint = print
  2. print = function(…)
  3.      _G.oldPrint(arg)
  4.      newStatement(table.concat(arg,"    ")) 
  5. end

Thanks again for the code though it’s working beautifully. I modified it to fit my debug console this is what it looks like: 

74IZPEx.png
 

Thanks @dmglakewood and also thanks @davebollinger! I’ll update the code before posting to my site next week. Also, that debug console looks pretty sweet!

Hi there,

This is definitely possible. It’s not something I’d thought of until now, but I’m gonna whip up a quick module to display print statements on-device (so you can drop it into your project with one line of code). Give me at least a few hours, possibly a day. The first iteration may be a little rough around the edges, but it’ll work. Stay tuned.

Ohh wow that’s even more then I was expecting! Thanks for the generosity. 

fwiw you can redefine print() to do whatever you want instead (should first save a ref to the original), fe:

local original\_print = print -- save function print(...) -- redefine local txt = table.concat(arg," ") someTextObject.text = txt -- show that text somewhere in your app original\_print(unpack(arg)) -- optional: call original to print as before end

@davebollinger: that’s the core of what I’m packing into my module, but I’m taking this as an opportunity to make a nice-looking (and show/hide-able) on-screen console. :slight_smile:

Hi @dmglakewood:

Here you go! I whipped up a simple little module that you can plug in by simply adding one lua file to your project directory, and one line of code to your main.lua. Just drop onScreenPrint.lua (from the attached zip file: ) into your project’s root directory (alongside main.lua ) and add this line of code to your main.lua :

[lua]

local onScreenPrint = require(“onScreenPrint”)

[/lua]

onScrenPrintPreview.png

The module adds in a “print console” that takes up the lower 1/4 of your device’s screen and displays any print statements along with a timestamp. Traditional “offscreen” print statements will still be generated as well.

The on-screen print statements will text-wrap so that they don’t go off the screen, and the console is scrollable, so you can go back and re-read earlier statements. Tap the bar along the top of the console to show or hide the console. Hiding it takes it down to 50% alpha, and just along the bottom of the device screen. Any time a new print statement is generated, the console automatically scrolls to that new statement. 

I think I’ll add this to my website as a tutorial next week, and maybe add the ability to copy a print statement to the device’s pasteboard. I didn’t include that functionality here, partly because I didn’t want to spend too much time on it today, and partly because I wanted to keep the module very lightweight. Thanks for prompting this fun little exercise! It’s just what I needed to clear my head today. :slight_smile:

Here is the content of onScreenPrint.lua, in case you are interested:

[lua]


– CREATE TABLE TO HOLD MODULE FUNCTIONS


local onScreenPrint = {}


– REQUIRE WIDGET LIBRARY


local widget = require(“widget”)


– DEFINE LOCAL VARIABLES


local centerX = display.contentCenterX

local centerY = display.contentCenterY

local screenTop = math.floor(display.screenOriginY)

local screenLeft = math.floor(display.screenOriginX)

local screenBottom = display.contentHeight - screenTop

local screenRight = display.contentWidth - screenLeft

local screenWidth = screenRight - screenLeft

local screenHeight = screenBottom - screenTop

local fontSize = screenHeight*.03


– CREATE ON-SCREEN CONSOLE TO DISPLAY PRINT STATEMENTS


local group = display.newGroup()

local bg, scrollView, button, buttonTap

bg = display.newRect(group, centerX, screenBottom, screenWidth, screenHeight * .25 + fontSize*2)

bg.anchorX, bg.anchorY = .5, 1

bg:setFillColor(0, 22/255, 10/255, .5)

bg:addEventListener(“touch”, function() return true end)

bg:addEventListener(“tap”, function() return true end)

scrollView = widget.newScrollView({

     top = screenBottom - screenHeight*.25 + fontSize*.5,

     left = screenLeft,

     width = screenWidth,

     height = screenHeight*.25 - fontSize,

     hideBackground = true,

})

scrollView.lastY = 0

group:insert(scrollView)

function buttonTap(event)

     if group.y <= 0 then

          transition.cancel(group)

          transition.to(group, {y = bg.height - fontSize, alpha = .5, transition = easing.outBack})

     else

          transition.cancel(group)

          transition.to(group, {y = 0, alpha = 1, transition = easing.inBack})

     end

     group:toFront()

end

button = widget.newButton({

     label = “↑ print console ↓”,

    --properties for a rounded rectangle button…

    shape=“rect”,

    width = screenWidth,

    height = fontSize*1.5,

    fontSize = fontSize,

    font = “Courier”,

    fillColor = { default={ 0, 22/255, 10/255, .5 }, over={ 0, 22/255, 10/255, .5 } },

    labelColor = { default={ 1, 1, 1, 1 }, over={ 1, 1, 1, 1 } },

    onRelease = buttonTap,

})

group:insert(button)

button.x, button.y = centerX, screenBottom - bg.height

button.anchorX, button.anchorY = .5, 0


– ADD NEW STATEMENT TO CONSOLE


local function newStatement(statement)

     local time = os.date("%I")…":"…os.date("%M")…":"…os.date("%S")

     local text = display.newText({

          text = time…": "…statement,

          x = centerX,

          y = scrollView.lastY,

          width = bg.width - fontSize,

          height = 0,

          font = “Courier”,

          fontSize = fontSize,

          align = “left”,

     })

     text.anchorX, text.anchorY = .5, 0

     text:setFillColor(20/255, 246/255, 119/255)

     

     local box = display.newRect(text.x, text.y - fontSize*.25, bg.width - fontSize*.25, text.height + fontSize*.5)

     box.anchorX, box.anchorY = text.anchorX, text.anchorY

     box:setFillColor(10/255, 122/255, 58/255, .5)

     

     scrollView:insert(box)

     scrollView:insert(text)

     scrollView.lastY = box.y + box.height + fontSize

     

     scrollView:scrollToPosition({x = 0, y = -box.y})

     group:toFront()

end


– AMEND PRINT() TO INCLUDE ON-SCREEN PRINTING & RETURN MODULE


_G.oldPrint = print

print = function(statement)

     _G.oldPrint(statement)

     newStatement(statement)

     

end

return onScreenPrint

[/lua]

This is something I have saved for future use but not tried yet: 

http://forums.coronalabs.com/topic/50004-corona-advanced-logging/#entry258805

Remote debugging over network from Lerg (link not working though): http://spiralcodestudio.com/corona-sdk-pro-tip-of-the-day-22/

This is way more amazing then I was expecting. Great work!

I found a bug in your script schroederapps your print will only accept 1 variable but the real print accepts any number of variables. So if you do:

print(“test”, “test2”, “test3”)

only test will show not the other two. I fixed this with the following. (Thanks to davebollinger for his post above showing the args)
 

  1. _G.oldPrint = print
  2. print = function(…)
  3.      _G.oldPrint(arg)
  4.      newStatement(table.concat(arg,"    ")) 
  5. end

Thanks again for the code though it’s working beautifully. I modified it to fit my debug console this is what it looks like: 

74IZPEx.png
 

Thanks @dmglakewood and also thanks @davebollinger! I’ll update the code before posting to my site next week. Also, that debug console looks pretty sweet!