groff: Incorrect line width after page break - groff

I'm using groff version 1.22.4 to create a two-page letter. The first page has three columns, the second page has 2 columns.
The macros for printing columns 1-3 on the first page work as expected. The macro for starting the second page always gives a first line that is the width of the column on the previous page. .
How can I get the first line on the second page to have the correct width?
Below is the groff:
.ll 2.25i \" Line length of a column 2.25 inches. Good for three columns.
.vs 15p \" 11 points between lines of text in the same paragraph
.ps 12 \" 12 point font size
.nr bottom-margin 0.75i \" Bottom margin
.de START-COLUMN-0
. mk \" Mark top of column
. wh -\\n[bottom-margin]u START-COLUMN-1 \" At bottom of 1st column, run next macro.
..
.de START-COLUMN-1
. po +2.55in \" Add offset for second column.
. rt \" Return to top of column.
. wh -\\n[bottom-margin]u START-COLUMN-2 \" At bottom of 2nd column, run next macro.
..
.de START-COLUMN-2
. po +2.55in \" Add offset for second column.
. rt \" Return to top of column.
. wh -\\n[bottom-margin]u START-PAGE-2 \" At bottom of 2nd column, run next macro.
..
.de START-PAGE-2 \"Page break.
'll 3.55i \" Line length of a column 3.55 inches. Good for two columns.
'bp \" Break page.
'po 0.5in \" left margin
'mk \" Mark top of column
'wh -\\n[bottom-margin]u END-PAGE-2 \" At bottom of 1st column, run next macro.
..
.de END-PAGE-2
. po +3.85in \" Add offset for second column.
. rt \" Return to top of column.
. wh -\\n[bottom-margin]u \" Terminate at second column on second page.
..
.START-COLUMN-0
Lots of text here.

Posted as an answer, because I need a picture in it and the size of the comment is too large.
Are you sure? The result is completely different from what you describe. The second page is two columns, instead of the 1 column in your description.
When I run your code (GNU groff version 1.22.4), I get:
or as nroff:
laoreet arcu eros vi‐ faucibus, lacus lectus cus. Quisque mattis
tae lorem. Morbi con‐ ullamcorper massa, euismod tortor, sit
vallis massa lacus, quis fermentum leo me‐ amet hendrerit lacus
vel mollis velit tus sed ipsum. Maece‐ tristique a. Aenean
vulputate nec. nas sagittis pharetra fermentum sapien pu‐
rus,
vel interdum tellus tincidunt nec. Ut euismod massa risus.
Aenean rutrum, sem sed sodales mattis, magna felis ullamcorper dolor, ac
convallis nulla diam vel erat. Donec in turpis velit. Nunc elit arcu, cur‐
sus et condimentum in, efficitur et nisi. Vivamus suscipit porttitor nunc
consectetur malesuada. Vivamus sodales non lacus quis porttitor. Aenean
viverra nulla ut lacus dignissim bibendum. Nulla gravida sem quis ex cursus
I also get a single column on the second page, and not two columns as you have in the output.

Related

Would filtering by order ID from nvarchar(MAX) column benefit from fulltext search?

In my table I have a nvarchar(MAX) column which holds data about our orders in XML form. Another department often has to get information from the table by, most commonly, looking for a certain order ID in that column but we all need to be able to look for any part of the text in the column.
The problem is that the order IDs and other filter/search criteria are unique to each order and are not words I can define in stopwords or stoplists and new ones are generated for new orders, ofc.
Since the table is growing in size queries with a LIKE clause take a really long time, yet I cannot think how my colleagues can get information about an order except by looking for things like its order ID, a part serial number or a piece of text. We have no control over the XML order data, furthermore it doesn't have a standardised structure, which is to say every order type has its own XML structure and there are too many to separate into different tables and we can't extract separate elements into different columns as we don't have control over the processing, only over the storage of the data.
Since an index would be futile in this case I started reading about fulltext search, but would that help because of the reasons I mentioned and if not is there a better alternative?
EDIT:
Adding example messages being stored in the nvarchar(MAX) column (there are approx. 23 other types not shown here, for the moment):
<?xml version='1.0' encoding='UTF-8'?>
<ServiceRequest>
<OrderID>GT123456789123465</OrderID>
<CreatedBy>some.person</CreatedBy>
<CreationTime>2021-08-18</CreationTime>
<CustomerReference>INC123456</CustomerReference>
<CustomerContract>123456</CustomerContract>
<ShortDescription>A little bit of text</ShortDescription>
<StockLocation>Text-Identifier</StockLocation>
<DueDate>2021-08-19</DueDate>
<ExpectedDeliveryDate>2021-08-19T10:30:00</ExpectedDeliveryDate>
<ServiceLevel>Same-Day</ServiceLevel>
<DeliveryLocation>SITE</DeliveryLocation>
<Site>Address of a building or something</Site>
<ContactName>Name of a person</ContactName>
<ContactPhone>0123456789</ContactPhone>
<DocTypeID>123</DocTypeID>
<DeliveryAddress>
<Address1>Address1</Address1>
<Address2>More details about address</Address2>
<City>Some city</City>
<Postcode>LOL KEK</Postcode>
<Country>Narnia</Country>
</DeliveryAddress>
<Parts>
<Part>
<UniqueID>168468468</UniqueID>
<PartNumber>#ABCDE-1234-ABCDE</PartNumber>
<Description>Example TV set with model name</Description>
<Quantity>1</Quantity>
<Returnable>Y</Returnable>
<ReturnInformation>TBC</ReturnInformation>
<LinkedDemandId>123456789</LinkedDemandId>
</Part>
</Parts>
</ServiceRequest>
.
<?xml version='1.0' encoding='UTF-8'?>
<Engineer>
<PersonId>some.guy</PersonId>
<SearchName>Some Guy</SearchName>
<personemail>some.guy#company.com</PersonEmail>
<PersonPhone>00000000000</PersonPhone>
<Address>
<Zip>LOL KEK</Zip>
<CountryId>US</CountryId>
</Address>
</Engineer>
.
<WarehouseUpdate>
<WarehouseId>Warehouse-name-123456</WarehouseId>
<WarehouseDescription>Friendlier WH name</WarehouseDescription>
<CurrencyId>USD</CurrencyId>
<CostDomainId>MAIN</CostDomainId>
<NodeId>SSL</NodeId>
<SupplySource>W</SupplySource>
<ReturnWarehouse>Warehouse-ID</ReturnWarehouse>
<IsAutoReceive>Y</IsAutoReceive>
<IsRepairWhse>N</IsRepairWhse>
<IsReplenishable>Y</IsReplenishable>
<SupplyWarehouse>Warehouse-ID</SupplyWarehouse>
<WarehouseTypeId>ABC</WarehouseTypeId>
<Address>
<Zip>LOL KEK</Zip>
<CountryId>US</CountryId>
</Address>
</WarehouseUpdate>
.
<briefing>
<incident>
<serviceProvider>A long name of a company that provides a service</serviceProvider>
<receiverURL>https://www.google.com/some/url/that/is/used</receiverURL>
<incidentNumber>123456789</incidentNumber>
<taskNumber>123456789</taskNumber>
<taskAssignmentID>123456789</taskAssignmentID>
<taskCreationDate>2021-02-31</taskCreationDate>
<taskCreationTime>10:32:13</taskCreationTime>
<sendDate>2021-02-31</sendDate>
<sendTime>10:32:27</sendTime>
<request>ABC</request>
<urgency>ABC</urgency>
<severity>D</severity>
<customerName>Name of a company</customerName>
<helpdeskNumber>123456789</helpdeskNumber>
<originalCustomerReference>123456789</originalCustomerReference>
<projectNumber/>
<project/>
<callerFirstName>Some</callerFirstName>
<callerLastName>Person</callerLastName>
<callerPhone>123456789123456789</callerPhone>
<callerPhoneType>ABC</callerPhoneType>
<callerEmailaddress/>
<callerPreferredLanguage/>
<communicationPreference/>
<installedAtAddress1>Address short</installedAtAddress1>
<installedAtAddress2/>
<installedAtAddress3>More address details</installedAtAddress3>
<installedAtAddress4>Even more address details</installedAtAddress4>
<installedAtCity>Washington</installedAtCity>
<installedAtState/>
<installedAtProvince/>
<installedAtPostalCode>LOL KEK</installedAtPostalCode>
<installedAtCountry>US</installedAtCountry>
<installedAtPhone/>
<installedAtFax/>
<installedAtEmail/>
<productSerialNumber>ABCDF123456789</productSerialNumber>
<productTag>ABCDF123456789</productTag>
<productSystem>123456</productSystem>
<productItemNumber>123456789123456789</productItemNumber>
<productItemDescription>This is a thingy</productItemDescription>
<productComponentNumber/>
<productComponentDescription/>
<productServiceGroupNumber>12</productServiceGroupNumber>
<customerSerialNumber/>
<defectDescription>ABCD::ABCD::ABCD EF::ABCD EF</defectDescription>
<orderDescription>Lorem ipsum</orderDescription>
<taskType>In summet idit</taskType>
<customerErrorCode/>
<problemCode>corpsem mepsem dopsem</problemCode>
<resolutionSummary/>
<resolutionCode/>
<reporteddate>2021-05-12</reporteddate>
<reportedtime>10:30:44</reportedtime>
<customerTimezone>EET</customerTimezone>
<coverage>-ABC-EF-</coverage>
<contractServiceNumber>123456789123456789</contractServiceNumber>
<plannedStartDate>2021-05-12</plannedStartDate>
<plannedStartTime>10:32:13</plannedStartTime>
<plannedEndDate>2021-05-14</plannedEndDate>
<plannedEndTime>10:32:44</plannedEndTime>
<chargeableFlag/>
<vkOrg>12AB</vkOrg>
<attribute1/>
<attribute2/>
<attribute3>AB</attribute3>
<attribute4/>
<attribute5/>
<attribute6/>
<attribute7/>
<attribute8/>
<attribute9/>
</incident>
<incidentNotes>
<technicianNote>Went to lunch, bought a snack</technicianNote>
<technicianNote>AB 11.11 11/11/2021
A huge block of text incoming
Here a monumental, monolithic, megalithic block of text resides that has numerous details written in freeform however the person doing the thing decides
There is some structure to the text but it is completely specific to this one type of XML message.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eu feugiat enim. Praesent malesuada, diam ut ornare tristique, ipsum dolor rutrum enim, et sodales lectus mi at ex. Nulla in varius nisl. Nunc non enim augue. Integer condimentum tempor lacus, non maximus tortor dictum a. Donec dapibus urna nulla, ac tempus justo sodales sed. Cras lacinia tempus lacinia. Sed fermentum libero vel lectus ornare, at egestas eros dignissim. Quisque ac vehicula erat. Morbi id ultrices sem, auctor dapibus ligula. Vivamus vestibulum consectetur ligula non viverra. Proin id mi non ipsum consectetur interdum. Aenean id posuere metus.
Aenean diam justo, ultrices sed cursus eget, posuere eget justo. Maecenas egestas mi et rutrum auctor. Fusce tincidunt ac purus ut gravida. Proin ac condimentum nibh, id venenatis nibh. Sed eu turpis non sem venenatis posuere eu sit amet leo. Vivamus velit lacus, tempor quis dolor vel, sagittis vulputate risus. Praesent dignissim sed turpis vel porta. Duis elit ante, pellentesque sit amet nisl eu, ullamcorper varius ex. Aenean tortor ligula, posuere sed tempor eget, consequat ut orci. Vestibulum eu aliquet ante. Ut eros ex, dignissim nec accumsan eu, posuere nec ligula. Cras tempor volutpat tempor. Duis vitae dui sit amet diam porttitor viverra. Aliquam ornare, turpis ut pulvinar bibendum, urna eros sodales turpis, sed malesuada felis massa in neque. Etiam venenatis volutpat diam eget placerat. Integer ultrices vulputate neque ut ullamcorper.
</technicianNote>
</incidentNotes>
<ibaseNotes>
<serialnumberNote/>
</ibaseNotes>
</briefing>
Also I think I deceived you by accident, most commonly order IDs are being searched but we need to be able to search/filter by any part of the XML message, for example I need to be able to find all messages that contain "some.person" in them. I'll go back and edit that.
Ideally you should store XML in an xml column. Then you can use XQuery to search. An XML index on the column may be wise.
But you can also cast the data to XML (at a cost of lower eficiency), like this
CROSS APPLY (VALUES (
CAST(CAST(yourData AS varchar(max)) AS xml)
) ) v(xmlData)
Cast to varchar is necessary because the XML is defined with UTF-8.
Then you can use XQuery, like this for example
WHERE v.xmlValue.exist('/Engineer/PersonId[contains(text()[1], "some.guy")]') = 1
or v.xmlValue.exist('/Engineer/PersonEmail[contains(text()[1], "some.guy")] ') = 1
Or pass through a SQL variable
WHERE v.xmlValue.exist('/Engineer/PersonId[contains(text()[1], sql:variable("#toSearch"))]') = 1
or v.xmlValue.exist('/Engineer/PersonEmail[contains(text()[1], sql:variable("#toSearch"))] ') = 1
SQL Fiddle
To find text in any node, you can use //*, which means "descend any depth, matching any node name"
WHERE v.xmlValue.exist('//*[contains(text()[1], sql:variable("#toSearch"))]') = 1
That can be inefficient though.

Annotate Data in between Markup

I'm trying to write a rule to detect Data in between Markup tags.
Input data format is fixed for example
<1> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim</1>
<2> nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim</2>
What i basically need here to detect data in between start and end tag
in my case output should be 1 and 2
I'm trying below rule.
Document{->ADDRETAINTYPE(MARKUP)};
STRING sStart = "<";
STRING sEnd = ">";
DECLARE spanStart;
DECLARE spanEnd;
DECLARE ZONE;
sStart -> spanStart;
sEnd -> spanEnd;
spanStart NUM spanEnd{->MARK(ZONE,2)};
But value is not getting detected as 1 & 2 are not detected as number
"1" and "2" are not detected as NUM because they are MARKUP. The seeding creates a disjunct non-overlapping partitioning of the document. If you want to create an annotation within a currently smallest part, e.g., in your use case MARKUP, you can do that with a simple regex rule as you did in your question with spanStart and spanEnd.
I would use something like:
MARKUP->{"\\d+"-> ZONE;};
or
MARKUP->{"</?(\\d+)>"-> 1 = ZONE;};
DISCLAIMER: I am a developer of UIMA Ruta

Insert string randomly into another string

Does anyone have a good method for inserting all items from a list randomly into another string? For example if I have paragraph of text and I want to insert urls randomly after sentences. The Urls are stored in a list object. How would I go about doing this? I was thinking I could count the number of periods and other punctuation, but I would somehow have to store the location of each period as well. If anyone could point me in the right direction i would appreciate it.
I think the logic is as follows:
count periods,
store period indexes in list,
get random index from list,
insert text after that index by adding 1 to the index
Does this work for you?
var rnd = new Random();
var urls = new [] { "www.a.com", "www.b.com" };
var text = "I like apples. I like bananas.";
var query =
from t in text.Split(new [] { '.' }, StringSplitOptions.RemoveEmptyEntries)
from x in new [] { t, ". ", urls[rnd.Next(urls.Length)] }
select x;
var result = String.Join("", query);
I like apples. www.b.com I like bananas. www.a.com
Here you go.
Module Module1
' String to insert into
Const target As String = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse vel posuere neque, quis suscipit diam. Proin congue dapibus elit, ut tempus leo. Suspendisse suscipit mi quis purus laoreet facilisis. Sed eget arcu eu risus sodales posuere. Nulla ut nulla urna. Quisque eu eleifend metus. Mauris suscipit rhoncus eros at ultrices. Cras sodales facilisis mauris, vitae condimentum mi tempus a. Suspendisse hendrerit, arcu sit amet viverra placerat, eros quam venenatis enim, id tincidunt felis mauris id augue. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur ac ullamcorper sem, sed porta orci. Praesent euismod, ipsum et sagittis gravida, purus ipsum venenatis ipsum, quis congue risus erat in magna. Donec nec elit ut velit faucibus efficitur. Donec facilisis, tellus et volutpat hendrerit, dui sem pulvinar lectus, sit amet fringilla sem mi eget elit."
' Urls to insert
Private injections As String() = New String() {"http://lorempixel.com/output/cats-q-c-640-480-1.jpg", "http://lorempixel.com/output/cats-q-c-640-480-2.jpg", "http://lorempixel.com/output/cats-q-c-640-480-3.jpg", "http://lorempixel.com/output/cats-q-c-640-480-4.jpg"}
Sub Main()
Dim sentence As New System.Text.RegularExpressions.Regex("[^.!?]+[.!?]")
Dim result As New System.Text.StringBuilder()
Dim n As Integer = injections.Count()
' Break sentence at punctuation.
For Each m As System.Text.RegularExpressions.Match In sentence.Matches(target)
' Get index of one of our injection strings at random.
Dim i As Integer = CInt(Math.Ceiling(Rnd() * n)) - 1
result.Append(m).Append(injections(i))
Next
Console.WriteLine(result.ToString())
Console.ReadKey()
End Sub
End Module

How to set same "STRING" as start and end reference to copy the message within those references?

I have an email that has a long body. I want to send part of the email body by setting a starting "STRING" reference and an ending same "STRING" reference.
Let's say the "STRING" = "Good day!"
Whenever the macro set the first string "Good day!" in the email body, I want the next "Good day!" string to be the ending reference without searching/finding another "Good day!" string so that the message within those two references can be copied to be sent as a new mail.
I found this code that uses a UNIQUE string but I need the next string occurrence only after the first string reference.
http://www.outlookcode.com/codedetail.aspx?id=985
With this on hand, I'm thinking just to replace the 2nd "Good day!" with a UNIQUE string so that I can use this code but I still don't know how to search/find for the 2nd occurrence of the same string.
Consider the following approximation of an email's 'body text'
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque fringilla mi et aliquam ornare. Sed et dolor posuere, feugiat mi ac, mattis augue. Good day! Ut lorem sem, pulvinar a erat a, tempus congue lorem. Nulla semper cursus ante ac euismod. Sed rutrum odio a nulla consectetur, scelerisque lacinia risus consectetur. Good day! Fusce sit amet vulputate lorem, eu aliquam diam.
Pass that text as a string through this function.
Function partial_body(sBDY As String, Optional sFND As String = "Good day!", Optional bINCL As Boolean = False)
Dim s As Long, f As Long
s = InStr(1, sBDY, sFND, vbTextCompare) - ((Not bINCL) * Len(sFND))
f = InStr(s + 1, sBDY, sFND, vbTextCompare) + (bINCL * Len(sFND))
partial_body = Trim(Mid(sBDY, s, f - s - (bINCL * Len(sFND)) * 2))
End Function
Result for partial_body(<body>)
Ut lorem sem, pulvinar a erat a, tempus congue lorem. Nulla semper cursus ante ac euismod. Sed rutrum odio a nulla consectetur, scelerisque lacinia risus consectetur.
Result for partial_body(<body>, "Good day!", True)
Good day! Ut lorem sem, pulvinar a erat a, tempus congue lorem. Nulla semper cursus ante ac euismod. Sed rutrum odio a nulla consectetur, scelerisque lacinia risus consectetur. Good day!

How do I modify that string?

Good day,
I don't know how to describe my problem (which is more like a challenge)
but I'll do my best.
I am working on a text-based game and as your character moves, you get informations such as the room name and below, a description (Lorem ipsum in the example) which is an array of string. I would like to know how to append characters to it. I am actually
trying to display a minimap made of ASCII character. See the second bloc
code for an example.
From:
Room Name Here
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis tempus
orci diam. Curabitur hendrerit augue et lorem vulputate semper. Nullam
aliquam eleifend sapien nec bibendum. Donec accumsan leo eu orci
elementum semper in mollis metus. Ut ipsum diam, suscipit vel bibendum
non, congue eu nisi. Donec justo dolor, scelerisque nec fringilla nec,
aliquet sit amet elit. Morbi elementum pharetra odio, nec accumsan
velit lacinia quis.
[Exits: none] [Doors: none]
Into:
Room Name Here
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis +-----+
tempus orci diam. Curabitur hendrerit augue et lorem vulputate | # |
semper. Nullam aliquam eleifend sapien nec bibendum. Donec |#-#-#|
accumsan leo eu orci elementum semper in mollis metus. Ut ipsum | # |
diam, suscipit vel bibendum non, congue eu nisi. Donec justo +-----+
dolor, scelerisque nec fringilla nec, aliquet sit amet elit. Morbi
elementum pharetra odio, nec accumsan velit lacinia quis.
[Exits: none] [Doors: none]
The game itself is made in VB.NET but a solution in pseudo-code is also
welcomed.
Also, each line's length is aproximatively the maximum length it must be.
Thank you guys!
Edit:
The desired output must be an array of strings because this data is later send to a client connected using sockets.
If we use an assumption that your line length is 80 characters, Limit the max length of your text line to 70 characters. If the actual length is less than 70 add the difference in spaces to the front of the map data you are wishing to add. This is also dependent on using a monospaced font.
Dim LineOfText As String = "This is a test text"
Dim LineOfMap As String = "+------+"
Dim newLine As String
newLine = LineOfText & LineOfMap.PadLeft(80 - LineOfText.Length)
edit: added arrays, used Courier New Font
Dim LineOfText(6) As String
Dim LineOfMap(4) As String
Public Sub CreateArray()
LineOfMap(0) = "+-----+"
LineOfMap(1) = "| # |"
LineOfMap(2) = "|#-#-#|"
LineOfMap(3) = "| # |"
LineOfMap(4) = "+-----+"
LineOfText(0) = " Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis tempus"
LineOfText(1) = "orci diam. Curabitur hendrerit augue et lorem vulputate semper. Nullam"
LineOfText(2) = "aliquam eleifend sapien nec bibendum. Donec accumsan leo eu orci"
LineOfText(3) = "elementum semper in mollis metus. Ut ipsum diam, suscipit vel bibendum"
LineOfText(4) = "non, congue eu nisi. Donec justo dolor, scelerisque nec fringilla nec,"
LineOfText(5) = "aliquet sit amet elit. Morbi elementum pharetra odio, nec accumsan"
LineOfText(6) = "velit lacinia quis."
Dim x As Integer
For x = 0 To 4
LineOfText(x) = LineOfText(x) & LineOfMap(x).PadLeft(80 - LineOfText(x).Length) & vbCrLf
Next
For x = 0 To 6
Label1.Text = Label1.Text & LineOfText(x)
Next
End Sub
Edit: You can create a function and grow the array if the number of lines is less than 5 to make sure you have space for the map.
Public Function CreateArray(text() As String, map() As String) as String()
Dim x As Integer
If text.Length < map.Length Then
For x = 0 To map.Count - 1
If x < text.Count - 1 Then
text(x) = text(x) & map(x).PadLeft(80 - text(x).Length) & vbCrLf
Else
Array.Resize(text, text.Count + 1)
text(x) = map(x).PadLeft(80) & vbCrLf
End If
Next
Else
For x = 0 To map.Count - 1
text(x) = text(x) & map(x).PadLeft(80 - text(x).Length) & vbCrLf
Next
End If
return text
End Sub
It sounds like you're trying to build the window contents as one long string?
IMO you would be better off dividing the console window into logical regions, ie one for the text, one for the room map, and the exits/doors area could be separate areas or a single one.
There are escape sequences you can send to the terminal / console window to reposition the cursor, or there are libraries to do this sort of thing for you, in particular [n]curses on Unix/Linux -- look for something similar for Windows.