Line Breaks, Line Breaks, Line Breaks

If there is one thing I do not get in Inform 7 right now, it is line breaks. Here is how I am working at the moment:

  1. Write text.
  2. Run it.
  3. Note where line breaks appear.
  4. Add [line break] or [no line break] as appropriate.

Take the following example:

[code]The garage is a room.

The block is in the garage. The block can be this way or that way. The block is that way.

Carry out pushing the block:
say “First sentence.[if the block is that way] Second, conditional sentence.[end if]”;
rule succeeds.[/code]
This produces the following output:

Okay, noobishness, I don’t know why that “Nothing obvious happens.” is there, because I thought “rule succeeds” should stop that, but let’s ignore that. I have two questions about this code:

  1. How do I fix this? I have tried any combination of spacing, moving full stops, swearing - and I can’t make the text output look right for both conditions. To clarify, I want the first and second sentences on the same line.

  2. Why in the name of sweet flying kittens would I possibly want output like that? What is the utility of this feature? Why does Inform want to insert newlines all over the place - not even paragraph breaks, but newlines!

On a related note, why does the IDE indent text within indented blocks of code? It may make it look legible in the editor, but the text then line breaks and indents all oddly in the game.

In short, why does Inform want so much to make me look bad? I understand that some people will need fine control over line breaks and spacing. That’s fine, give them the option. But why on Earth can’t I7 just, by default, assume that I want block paragraph spacing, between paragraphs that I have specifically requested, and no crazy indentation.

Or, in other words, why can’t it just be like TADS 3, where I never had to worry about any of this stuff, where you get paragraphs and newlines when you ask for them, where everything is single spaced by default, where even if your conditional text mistakenly spews out multiple new paragraph tags you still only get one. You know, an intuitive environment for outputting computer-generated text, where rather than getting a headache over complex logic puzzles (how do I make sure this sentence ends in a full stop? if this condition is false will that space trigger a newline? if the middle clause isn’t displayed, will I have too many spaces?), I can just bloody write.

Having de-stressed a bit, I came up with:

Carry out pushing the block: say "First sentence. [if the block is that way]Second, conditional sentence.[otherwise][line break][end if]"; rule succeeds.
I still challenge anyone to tell me that this is intuitive.

Ah man, that sort of thing drives me INSANE… especially when working with a project that takes a long time to compile just to see if you got the break right.

This drives me nuts too. My code always ends up with a crazy mishmash of simple punctuated texts, [line break], [no line break], [run paragraph on], and [command clarification break] (this last one in contexts that have nothing to do with clarifying commands; it just seems like the only way to get the spacing I want sometimes.)

One thing that I picked up from Section 5.8 of the docs that helped a little is the fact that Inform adds an automatic paragraph break between two texts that are printed by different rules, but not if they are simply printed by different phrases. But I still don’t understand the line break system fully, and like you, I end up doing a lot by trial and error.

Since this is something I’ve been meaning to figure out anyway, I’ll run some sample code and try out all the permutations of different break types and where they appear (internal to a line of text, at the end of a line of text, as the last text produced by a phrase, as the last text produced by a rule, etc…) I’ll see if I can boil the whole thing down to a logical set of rules, and let you know if I have any luck.

For this case, I always do:

Carry out pushing the block:
    instead say "First sentence[if the block is that way]. Second, conditional sentence[end if].";

This provides the correct result with the minimum of cruft.

The crucial observation is that I7 goes newline-happy if a period is immediately followed by an open-square-bracket. In your second example below, you got a space in between the period and the bracket, which is why it started behaving the way you wanted.

The IDE expects you to only hit Enter inside a quoted string if really want a line break there. (If you do this – and don’t add any extra indentation – the string will print with no unexpected indentation.)

Forgot to add the other part of the answer: a “carry out” rule can’t abort the action. That’s why you get the “nothing obvious happens” message; it always moves on to the report phase. Either place your customized print message in the report phase, or divert everything in an instead rule.

The line break rules are specified pretty clearly:

I agree that it can be awfully freakin’ persnickety, and I suspect that at least some of the reason for it is that Inform has always been this way and longtime users are used to it. It’d be helpful, at least, if (a) explicitly stated that a space after a full stop doesn’t count.

That said, I think getting rid of (b) would cause far more work than it would remove; making it behave differently is fairly rare and can easily be dealt with by using [run paragraph on]. It does seem as if (a) could be handled better – line breaks are really kind of crap in most cases – but I’m sure that this discussion has happened a half-dozen times already.

1 Like

So here’s what I just found after some experimentation. This is just the results of some quick test code, and I could easily be missing something. Take everything that follows with a grain of salt:

There are six distinct ways to end a text block. From least likely to produce line feeds to most likely, they are:

[run paragraph on with special look spacing]
[no line break]
[command clarification break]
[line break]
[paragraph break]

If you don’t use any of these instructions explicitly, then ending a text block with a period, exclamation mark, or question mark is equivalent to typing [line break]. Ending a text block with any other character (including a space after a punctuation mark) is the equivalent to typing [no line break].

Also note that the end of a text block can be either a close-quotes, or any bracketed instruction. Hence,

"Some text.[if x is 5]  Some other text.[end if]"

is two text blocks, not one. (As the original poster discovered.)

The exact behavior of each of these block endings is:

                         If not the last text       If it is the last text
Instruction:             produced by current rule:  produced by current rule:
------------             -------------------------  ----------------------
[run paragraph on]       No line feed               No line feed
                                                    (next command prompt may
                                                     appear on the same line.)

[run paragraph on        No line Feed               No line feed
 with special                                        (single line feed before 
 look spacing]                                       a command prompt.)

[no line break]          No line feed               Single line feed
(or block ends without
punctuation)

[command                 Single line feed           Single line feed
 clarification break]

[line break]             Single line feed	        Double line feed
(or block ends with
period, exclamation, etc.)

[paragraph break]        Double line feed           Triple line feed

Oddly, there’s no command for “print a double line feed, regardless of whether the current rule produces more text”. For this, you need to use two [command clarification break] commands in a row (or a [line break] followed by a [command clarification break]).

Finally, I could find no difference between the behavior of a [conditional paragraph break] and a regular [paragraph break]. (I was hoping the conditional version gave the missing “double line feed no matter what” behavior.) In all likelihood, there is a difference, just not one I was able to find.

I’m not arguing for getting rid of the present system, just for documenting it better (and maybe reworking a few of its quirkier aspects…)

1 Like

Thanks very much – that’s very useful.

Example 113, “Don Pedro’s Revenge,” demonstrates the difference – it uses a conditional paragraph break after reading a command, which prints one blank line after the command. If you substitute a paragraph break or line break, it prints two blank lines instead of one.

Why this happens, I cannot tell you.

Thank you all for your input and forbearance.

But trying to get sentences in that form gives me a massive headache. And what if one of them ended in a question mark?

Look, my point isn’t that there is a bug, or that Inform 7 isn’t consistent, it’s just that I don’t want to have to think about any of this.

In an environment supposedly aimed at writers, I don’t want to have to bend my writing around programming conventions.

1 Like

If there’s a question mark, you have to go back to one of the cruftier solutions.

I want many things out of life. :confused:

It seems like the reason it’s so complicated is so that you don’t have to think about it in the majority of cases. Just like Microsoft, this strategy can backfire by making things even more complicated when “Do what I mean” doesn’t.

The reason it’s more complicated than TADS 3 is because T3 adds the abstraction layer of the transcript, where output can be tweaked and fixed up before being printed to the screen.

There are default rules in the adv3 library that weed out superfluous line breaks and paragraph tags, as well as removing or replacing HTML tags based on the capabilities of the interpreter at runtime.

To the best of my knowledge, Inform does not distinguish between queuing up output for eventual display and the actual VM level print operations. (Output may be buffered at the interpreter / library level but that is not guaranteed, and comes too late to assist the author in any case.)

You would need something like Eric Eve’s Text Capture extension to make this work in Inform, running at a global level and with no length restrictions on captured output. Performance concerns and the lack of Z-Machine compatibility probably preclude this from becoming a standard feature.

Oh, it’s z-machine compatible if your game is otherwise very tiny :slight_smile:, but those performance concerns are nothing to sneeze at. I refer you to my short game, “Sugar” (Parchment and download links here), which is pretty much unplayable through Parchment.

The particular annoyance with the current line-break system is that the printing mechanism can keep track of one pending line break. That is, if you do

  say "Hello.";

…then the system will print one line break, and then set a flag indicating that a second may be coming. (It depends on various factors, such whether the next print statement occurs in the same rule, or whether it starts with a special paragraph substitution.)

I wish it would instead print no line breaks, and set a flag indicating that one or two may be coming. That would be more flexible, obviously; an upcoming substitution could continue on the same line. (Which is not currently possible.) This would not require any additional I/O buffering; only an adjustment of how I7 generates I6 code.

However, I understand that the print mechanism is already a mare’s nest, and any adjustment would probably break plenty of existing (working) code.

1 Like

Had to get home from work to prove to myself that I didn’t dream this. I am using the Windows IDE. (Line breaks in quoted text are ignored, paragraph breaks - double line breaks - produce the weird indentation. Unless you use the explicit tags [line break], [paragraph break])

Then we are practically life aim twins.

You’re right, and my answer (about hitting return inside a quoted string) was wrong. This is both more complicated and buggier than I understood.

The case I was thinking of is this:

When play begins:
	say "Alpha.
	
Beta.";

If you do this, you’ll get a paragraph break (two line breaks) between “Alpha” and “Beta”, with no indentation. This is probably what you want. However, it’s not what the IDE editor naturally does – it autoindents when you hit Enter, so you wind up with this:

When play begins:
	say "Alpha.
	
	Beta.";

This was your original complaint, and I misunderstood it. Sorry about that. I was thinking only about the behavior of the compiler, not of the editor. If you go back and delete the indentation before “Beta”, you get back to the correct case.

The other reason I was confused was that I had never noticed the behavior of the compiler with a single line break. As you note, it collapses the line break and any associated indentation into a single space character. That’s these cases:

When play begins:
	say "Alpha.
	One.";
	say "Alpha.
Two.";

I don’t know why it converts the line break to a space – I’d expect it to keep it. But given that it does, it certainly makes sense to drop the indentation, and it should be doing that for the double-line-break case too.

(In fact there’s still something hinky going on under the covers. In these latter cases, the I7 compiler is generating I6 string constants which contain literal tab and newline characters – though not both at the same time, which is even hinkier. These characters then get ironed out into spaces by the I6 compiler. The result is valid, but the I7 compiler really should be handling it all and not passing the buck.)

I filed inform7.com/mantis/view.php?id=715 , which repeats this analysis in tedious detail.

I’ve gotten into the habit of doing things this way:

[code]When play begins:
say “The comma
[line break]belongs in this haiku, or
[line break]it doesn’t.”

When play begins:
say “There’s a paragraph about one thing.
[paragraph break]And there’s a paragraph about something else.”[/code]

I just don’t use literal line breaks inside strings at all, which is why I wasn’t up to speed on how the compiler treats them.