This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
samdeman22's profile picture

Splitting a massive string to print with

Started by samdeman22, 06 March 2013 - 08:59 AM
samdeman22 #1
Posted 06 March 2013 - 09:59 AM
So I have a log system where I add lines to a file through an API, but when I want to print part of it I thought I'd be able to use fs.readLine() with a number to read a specific line, but it apparently doesn't work like that (it just reads the 'next' line?).

In short, I must add the entire log to the page, how do I split up the massive string so it can fit on the pages?
SuicidalSTDz #2
Posted 06 March 2013 - 10:06 AM
Do you have any code we can see to get a better understanding?
samdeman22 #3
Posted 06 March 2013 - 10:12 AM
ok, I show you then


function printLog(log, fromLn, copies)
if open == true then
  error("Log must be ended before printing")
end


--printer setup

local side = nil
local sides = { 1 = "front", 2 = "back", 3 = "left", 4 = "right", 5 = "top", 6 = "bottom" }
local no = 1
for i = 1, 6 do
  if no == 1 then
   side = sides[no]
  elseif no == 2 then
   side = sides[no]
  elseif no == 3 then
   side = sides[no]
  elseif no == 4 then
   side = sides[no]
  elseif no == 5 then
   side = sides[no]
  elseif no == 6 then
   side = sides[no]
  else
   error("no printer found")
  end
end
local p = peripheral.wrap(side)
h = fs.open("log/"..log..".log", r)
local printstr = nil
for i = 1, fromLn do
  h.readLine()
end
printstr = h.readAll()
fs.close()
end

its not quite finished as you'll see (the actual printing part is missing)
SuicidalSTDz #4
Posted 06 March 2013 - 10:52 AM
h = fs.open("log/"..log..".log", r)

When opening a file the mode must be in string format like so:

h = fs.open("log/"..log..".log", "r")

Also since you defined the file as "h", you must close it like so:

h.close()

I think storing all the data in a table then printing it will be your best bet

EDIT: "printing" should be indexing (Nub)
Lyqyd #5
Posted 06 March 2013 - 10:57 AM
You can read the entire file into a table, line by line, then index the table to retrieve the line you want.
samdeman22 #6
Posted 06 March 2013 - 12:20 PM
Yeah, I'll reshape this based on what you guys say tomorrow and show you.
SuicidalSTDz #7
Posted 06 March 2013 - 12:21 PM
Sounds like a plan :)/>
remiX #8
Posted 06 March 2013 - 05:52 PM
You can store the whole thing in a string and use an awesome function made by TheOriginalBit which splits it into a table with the desired length of each line. You can find it in his Extended Library api. Check it out at the programs section.
Lyqyd #9
Posted 06 March 2013 - 06:23 PM
You can store the whole thing in a string and use an awesome function made by TheOriginalBit which splits it into a table with the desired length of each line. You can find it in his Extended Library api. Check it out at the programs section.

If it is the same function I am thinking of, it was not written by him, but is actually an example function found in the PIL. The one I'm thinking of is the one that's been floating around the forums for quite some time. I simply don't wish it to be misattributed if that is the case.
remiX #10
Posted 06 March 2013 - 07:13 PM
You can store the whole thing in a string and use an awesome function made by TheOriginalBit which splits it into a table with the desired length of each line. You can find it in his Extended Library api. Check it out at the programs section.

If it is the same function I am thinking of, it was not written by him, but is actually an example function found in the PIL. The one I'm thinking of is the one that's been floating around the forums for quite some time.  I simply don't wish it to be misattributed if that is the case.

Oh, sorry if that is the case. He has it licensed in his api and told me that he did make it.
samdeman22 #11
Posted 15 March 2013 - 08:40 AM
Right I've left the printing part for a while, the rest of the code is completely buggering me… here's a pastebin http://pastebin.com/YHBpSVyG and here's the code…

--The Log API 1.1
runningProgram = "test"
function openLog(name)
h = fs.open("logs/"..name..".log", "a")
end
function closeLog()
h.close()
end
--function setRunningProgram(name)
-- runningProgram = name
--end
function generateLog() --will create the Dir "log" in the root and create a .log file based on the running program (if if is not already there)
if not fs.exists("log") then
  fs.mkDir("log")
end

if runningProgram == nil then
  error("program not specified")
end
  h = fs.open("logs/"..runningProgram..".log", "a")
  h.writeLine("--- The "..runningProgram.." event log ---")
  h.writeLine(" ")
  h.close()
end
 
function addEntry(type, str)
local time = os.time()
local day = os.day()
h.writeLine("["..day.."]".."["..time.."]".."["..type.."] | #"..str)
end
function startLog()
open = true
local time = os.time()
local day = os.day()
openLog()
h.writeLine("["..day.."]".."["..time.."] | #STARTING LOG")
end
function endLog()
open = false
local time = os.time()
local day = os.day()
h.writeLine("["..day.."]".."["..time.."] | #ENDING LOG")

end
function setPrinterSide(side)
printside = side
end
function printLog(log, fromLn, copies)
if open == true then
  error("Log must be ended before printing")
end
end
samdeman22 #12
Posted 15 March 2013 - 08:44 AM
It comes up with an error "log:5:attempt to concatenate nil and string" in this case its talking about the line h = fs.open("logs/"..name..".log", "a") which is strange because it actually gets past that part EVERY time and outputs the generateLog() stuff into the log properly.
samdeman22 #13
Posted 15 March 2013 - 08:56 AM
this is when calling log.openLog("test")
Lyqyd #14
Posted 15 March 2013 - 10:09 AM
The startLog function calls openLog with no parameters.
samdeman22 #15
Posted 15 March 2013 - 12:11 PM
Thanks, that makes sense.
samdeman22 #16
Posted 17 March 2013 - 02:05 AM
Ok, returning to the printLog function, I have got it so it reads the entire thing line by line into a table, now printing it in a way that looks good, eugh.
You can store the whole thing in a string and use an awesome function made by TheOriginalBit which splits it into a table with the desired length of each line. You can find it in his Extended Library api. Check it out at the programs section.
what was the name of the function? there are too many to choose from!
samdeman22 #17
Posted 17 March 2013 - 02:21 AM
also could someone make me a function that gets how many pages are needed based on the length of the string?
samdeman22 #18
Posted 30 March 2013 - 07:03 AM
Right, I'm hoping this will be the final iteration of the printLog(log, side, fromLn, toLn) function

-- a function you cant access ;P
local function round(num idp)
  local mult = 10 ^ (idp or 0)
  return (math.floor(num * mult + 0.5) / mult)
end
function printLog(log, side, fromLn, toLn)
  if open == true then
    error("Log must be ended before printing")
  end
  if not fs.exists( "logs/"..log..".log") then
    error("Log does not exist")
  end
 
  h = fs.open("logs/"..log..".log", "r")
  page = {}
  while h.readLine() ~= nil do
    local ln = h.readLine()
    table.insert(page, ln)
  end
 
  p = peripheral.wrap(side)
  local paper = p.getPaperLevel()
  local ink = p.getInkLevel()
  local w, h = p.getPageSize()
 
  local doc = {}
  for i = fromLn, toLn do
    table.insert(doc, page[i])
  end
 
  local length = 0
  for i = 0, #doc do
    length = length + doc[i]
  end
 
  local size = w*h
  local pages = round(length/size, 0)
  if pages > paper then
    error("not enough paper")
  end
  if pages > ink then
    error("not enough ink")
  end
 
  for i = 0, #doc do
    p.write(doc[i])
  end
 
end
This looks good to me but on loading the API I get "bios:338: [string "log"]:59: ' ) ' expected". Why ?
samdeman22 #19
Posted 30 March 2013 - 07:05 AM
ok, fixed the error as soon as I posted it *facepalm, I forgot a comma on the round(num, idp) function :)/>
samdeman22 #20
Posted 30 March 2013 - 07:13 AM
ok, there are some things to do yet with the printer stuff :(/> will work on it tho!
samdeman22 #21
Posted 30 March 2013 - 08:21 AM
Aha, a new problem,

-- a function you cant access ;P
local function round(num, idp)
  local mult = 10 ^ (idp or 0)
  return (math.floor(num * mult + 0.5) / mult)
end
function printLog(log, side, fromLn, toLn)
  if open == true then
    error("Log must be ended before printing")
  end
  if not fs.exists( "logs/"..log..".log") then
    error("Log does not exist")
  end
 
  h = fs.open("logs/"..log..".log", "r")
  page = {}
  while h.readLine() ~= nil do
    local ln = h.readLine()
    table.insert(page, ln)
  end
 
  p = peripheral.wrap(side)
  p.newPage()
  local paper = p.getPaperLevel()
  local ink = p.getInkLevel()
  local w, h = p.getPageSize()
 
  local doc = {}
  for i = fromLn, toLn do
    table.insert(doc, page[i])
  end
 
  local length = 0
  for i = 0, #doc do
    length = length + #doc[i]
  end
 
  local size = w*h
  local pages = round(length/size, 0)
  if pages > paper then
    error("not enough paper")
  end
  if pages > ink then
    error("not enough ink")
  end
  for i = 0, pages do
  p.newPage()
  p.setPageTitle(log.." page:"..i)
    for indx = 0, size do
	  p.write(doc[indx])
    end
  p.endPage()
  end
 
end
"log:91 attempt to get length of nil" it says, any suggestions?
faubiguy #22
Posted 30 March 2013 - 08:31 AM
You're starting the loop
for i = 0, #doc do
  length = length + #doc[i]
end
at 0 instead of 1.
if there isn't a value at doc[0], it can't get the length of it.
samdeman22 #23
Posted 30 March 2013 - 11:43 AM
You're starting the loop
for i = 0, #doc do
  length = length + #doc[i]
end
at 0 instead of 1.
if there isn't a value at doc[0], it can't get the length of it.
I maybe thought about that briefly and then forgot it, thanks, will try this soon, expect to see the log API out soon!
samdeman22 #24
Posted 30 March 2013 - 12:55 PM
nope, this time it actually runs, but it just fills the tray with 5 blank pages :/ Can anyone suggest a better print function to what I have? I need to be able to print a file from a certain line to a certain line so basically (log, side, fromLn, toLn) where log is the file, side is the printer, and from/toLn are the from/to line.
samdeman22 #25
Posted 30 March 2013 - 12:57 PM
oh and you must use this at the beginning

  if open == true then
    error("Log must be ended before printing")
  end
  if not fs.exists( "logs/"..log..".log") then
    error("Log does not exist")
  end

  h = fs.open("logs/"..log..".log", "r")
ok :)/>

open is defined in the rest of the API
samdeman22 #26
Posted 31 March 2013 - 02:31 AM
could the reason it prints blank pages be:

  for i = 0, pages do
  p.newPage()
  p.setPageTitle(log.." page:"..i)
    for indx = 0, size do
		  p.write(doc[indx])
    end
  p.endPage()
  end
should this be for i = 1, pages and indx = 1, size rather than 0, pages and 0, size?
remiX #27
Posted 31 March 2013 - 11:13 AM
Yes.. doc table doesn't have a 0 index
samdeman22 #28
Posted 02 April 2013 - 07:20 AM
Yes.. doc table doesn't have a 0 index
ok, still haven't had a chance to test this out but you know, I need to get it in my head "tables do not have a position:0". :)/>