Generally printing is done in a loop, printing each page. Each page must be begun with newPage(), and finished with endPage(). The contents of the page must be formatted to the page size, which we can't get until calling newPage(). With one page size supported we could assume 25x21 but getting the page size from the printer is more exact. The write() method, as on the terminal, will just keep printing past the right side of the page. The text must be broken into lines of the page width.
Both newPage() and endPage() can fail, if the printer is not ready or the out tray is full.
In the following, wrapString() breaks the string into lines of a maximum of the given width, returning an indexed table of the lines. printOut() is the printing loop. readFile() does just that, returning a single string.
The abort clauses allow the printing to be stopped easily if we are mistakenly about to print 500 pages, for example. Aborting at a failed endPage() will leave the last page in the printer until the next print on that printer.
local args = {...}
local function wrapString(str, maxWidth)
local result = { "" }
local line, start, pos, lastBreak = 1, 1, 1, maxWidth + 1
while pos <= string.len(str) do
local char = string.byte(str, pos)
if char == 13 or char == 10 then
--# hard break
if (pos - start) > 0 then
result[line] = string.sub(str, start, pos - 1)
else
result[line] = ""
end
line = line + 1
if char == 13 and pos < string.len(str) then
if string.byte(str, pos + 1) == 10 then
--# windows/dos eol
pos = pos + 1
end
end
start = pos + 1
lastBreak = start + maxWidth
elseif char == 32 or char == 9 then
--# last potential soft break
lastBreak = pos + 1
end
if (pos - start) >= maxWidth then
--# line at max, must break
result[line] = string.sub(str, start, lastBreak - 1)
line = line + 1
start = lastBreak
char = string.byte(str, start)
if char == 32 or char == 9 then
--# skip first white space
start = start + 1
end
lastBreak = start + maxWidth
end
pos = pos + 1
end
if (pos - start) > 0 then
--# get the left overs
result[line] = string.sub(str, start)
end
return result
end
local function printOut(title, contents, side)
local printer;
local continue = true
local lines;
local page = 1
if not side then
printer = peripheral.find("printer")
assert(printer, "Could not find a printer")
else
assert(peripheral.getType(side) == "printer",
"Expected printer on "..side)
printer = peripheral.wrap(side)
assert(printer, "Failed to connect printer "..side)
end
while continue do
--# start a page, fails if no ink/paper
while not printer.newPage() do
print("Check printer...")
local event, key = os.pullEvent("key")
if key == keys.delete then
print("Print aborted")
return
end
end
--# get the page size (in chars)
--# must be called after newPage()
local width, height = printer.getPageSize()
--# split contents into lines if not done yet
--# assumes all pages same width
if not lines then
lines = wrapString(contents, width)
print("Printing "..tostring(math.ceil(#lines / height)).." pages")
end
--# no page number on first page
--# first page is also title if made into book
if page == 1 then
printer.setPageTitle(title)
else
printer.setPageTitle(title.." "..tostring(page))
end
--# work out the lines to print on this page
local lastLine = page * height
local firstLine = lastLine - height + 1
--# if at end trim lastLine and flag drop out
if lastLine >= #lines then
continue = false
lastLine = #lines
end
--# write the lines to the page
for line = firstLine, lastLine, 1 do
printer.setCursorPos(1, line - firstLine + 1)
printer.write(lines[line])
end
--# next page
page = page + 1
--# spit page into out tray
while not printer.endPage() do
print("Empty tray...")
local event, key = os.pullEvent("key")
if key == keys.delete then
print("Print aborted")
return
end
end
end
print("Print complete")
end
local function readFile(path)
local hFile = fs.open(path, "r")
assert(hFile, "Could not open file "..path)
local contents = hFile.readAll()
hFile.close()
assert(contents, "Could not read file "..path)
return contents
end
if #args < 1 then
print("Usage: "..fs.getName(shell.getRunningProgram()).." filePath [printer]")
else
printOut(fs.getName(args[1]), readFile(args[1]), args[2])
end
Customize as desired.