How to make fmpp fail if a value cannot be found for a variable? - freemarker

Is there a parameter to make FMPP fail when it is unable to find a value for a variable in the template? right now it just leaves the text intact with ${} if it cannot resolve a variable.

Something strange is going on there, because it does fail and by default even aborts the whole batch processing if you refer to an undefined variable. Also, it doesn't leave ${}-s in the output, because all the ${ and } are "parsed away" before the template could do anything. So I suspect the value of those variables is indeed the string "${}", or you have some tricky #escape in the border/footer/header settings, or something tricky like that. (If you can provide a minimalistic example to reproduce this, I can certainly spot the reason.)

Related

Bash: ensuring a variable is set without erasing any existing value

Let's say I'm running a bash script under set -u. Obviously, for any given variable, I need to ensure that it's set. Something like:
foo=
However, if I want to keep any pre-existing value that might be set by my caller, this would overwrite it. A simple solution to this problem is to do this instead:
: ${foo:=}
But I have some code that does this (more complicated) way:
foo=${foo+$foo}
Now, I know this second way works. My question is, is there any advantage to it over the first way? I am assuming there is but now can't remember what it was. Can anyone either think of an edge case (no matter how obscure) where these two constructs would behave differently, or provide a compelling explanation that they can't?
I can't think of any case where they would differ. They're just alternative logic for the same thing.
The meaning of the simple solution is: If foo is unset/empty, set it to the empty string.
The meaning of your code is: If foo is set, set it to itself, otherwise set it to an empty string.
Your code seems like more work -- why set something to itself? Just do nothing and it will keep its value. That's what the simpler version does.
You can also simplify the simple solution further by removing the : in the parameter expansion.
: ${foo=}
This makes it only test whether foo is unset. If it's set to the empty string, no default needs to be assigned.
My question is, is there any advantage to it over the first way?
Maybe this is subjective, but one advantage is that it clearly looks like a variable assignment. Anyone who sees the command foo=${foo+$foo} will immediately understand that it sets the variable foo (even if they need to look up the ${parameter+word} notation to figure out what it sets it to); but someone who sees the command : ${foo:=} is likely to completely miss that it has the side-effect of modifying foo. (The use of : is definitely a hint that something might be happening, since : itself does nothing; but it's not as blatant.)
And of course, someone searching the script for foo= will find the former but not the latter.
That said, I would personally write this as either foo="${foo-}" or foo="${foo:-}", which still makes clear that it sets foo, but is a bit simpler than foo=${foo+$foo}. I also think that readers are more likely to be familiar with ${parameter-word} than ${parameter+word}, but I haven't asked around to check.

How do I debug vim indentexpr script?

I have downloaded a verilog/systemverilog indent file which looks really comprehensive. However, there is a problem: it doesn't work. I'm looking at the vimscript code and want to both fix it (I'm on vim 8.2, maybe there's a version mismatch) as well as enhance it. However, I'm running into issues debugging. Specifically, indentexpr scripts have a variable v:lnum which is set when indentkey is pressed and the indentexpr is evaluated.
BUT, I don't know of a way to enter debug mode on just the indentexpr call. I tried manually calling the function inside the vimscript but that leaves v:lnum as some garbage number (well, the last line to invoke indentexpr). Is there a way to enter debug mode when I actually hit a key that invokes indentexpr?
The best way for v:lnum to be used is as an argument to the function. Here's an example: vim-ruby's indentexpr setting used to look like this:
setlocal indentexpr=GetRubyIndent()
Inside the function, the variable v:lnum was used to get the line number that it was called on. This, as you've discovered, is pretty inconvenient. So, the better way is:
setlocal indentexpr=GetRubyIndent(v:lnum)
So, find the place in the script where the indentexpr is set and change it to take the magic v:lnum variable as an argument. You could then rewrite the function itself to take a single argument:
function! GetRubyIndent(lnum)
Now, in that function, the a:lnum variable will be the line number, and you can call the function with that argument. Search-and-replace v:lnum with a:lnum everywhere in the function. The indent script should now work as it did before, and you'll be able to call the function manually with a line number.
Here's the specific commit that does this in the vim-ruby repository, as an example
Additionally, echomsg "foo" will print a message that you can read afterwards by running the :messages command. And I can recommend the Decho plugin for easy-to-read debug messages.

What benefit does discriminating between local and global variables provide?

I'm wondering what benefit discriminating between local and global variables provides. It seems to me that if everything were made a global variable, there would be a lot less confusion.
Wouldn't declaring everything a global variable result in fewer errors because one wouldn't mistakenly call a local variable in a global instance, thereby encountering fewer errors?
Where is my logic wrong on this?
Some of this boils down to good coding practices. Keeping variables local also means it becomes simpler to share code from one application to another without having to worry about code conflicts. While its simpler to make everything global, getting into the habit of only using global variables when you actually have to will force you to code more efficiently and will make your code more structured.
I think your key oversight is thinking that an error telling you a local variable doesn't exist is a bad thing - it isn't. You've made a mistake and ruby is telling you so. This type of mistake is usually easy to fix: you've misspelled something or you're using something that you forgot to create.
Global variables everywhere might remove those errors but they would replace them with a far harder set of errors to reason about: accidentally using a variable that another bit of code is using. Imagine if every time you called a function (one of your own or a standard library one or one from a gem) you had to check which global variables it might change (and which functions it called, since it might also change global variables) If you make a mistake then you might get an error message (if the class of the object in the variable changes enough) but often you would just silently get incorrect results (if the value of a variable you were using changes unexpectedly).
In general global variables are much harder to work with and people avoid them when possible.
If all variables are global, every line of code in every program (including those which haven't been written yet) written by every programmer on the planet (including those who haven't been born yet or are already dead) must universally, uniquely agree on the names of variables. If you use a variable name that someone else on a different continent two years from now will also use, both of your programs will break, when used together.

How ought I run the annotate function in gui-debugger/annotator on a datum?

I am trying to learn how to use the DrRacket debugger's annotate function. My ultimate aim is to build a REPL that you can execute from within a closure and have access to everything that's in scope. (see my previous question on that topic and Greg Hendershott's well-researched answer) For the time being, I'm just trying to explore how the annotate function works. You can see my first exploratory attempt at using it, and the results, here.
The error, which is happing inside of the annotator, seems to arise when it tries to match he application of string-append. The matcher is looking for a #%plain-app and the expanded syntax I'm presenting to it contains an #%app. I'm unsure if I should be expanding the syntax differently so it comes out as a #%plain-app or if there's something else I'm doing wrong to produce the syntax I'm feeding into the annotator. Does anybody see where my error is?
This revision to my previous pasterack post is swallowed without complaint. It seems that the syntax match must take place on a top-level syntax object (ruling out anything that could happen in an expansion phase, like a macro), and expansion must take place with a current namespace attached. There are some more subtleties in the syntax match, particularly around the fact that the syntax object needs to be free-identifier=? to #%plain-app. For all the gory details, refer to the mailing list thread I started.

Is it possible to undefine a variable in freemarker?

In the freemarker template language, I can test whether a variable exists by using constructs like variable?exists or variable??. I can also cause a previously non-existent variable to exist by assigning to it, e.g., <#assign variable = "hi" />. But how can I cause a previously existing variable to no longer exist?
I have some other dude's freemarker template, with logic at various points that tests for the (non-)existence of certain variables. In my use case, it would be simplest if I could have a variable that exists at one point, then becomes undefined when including his template, then gets assigned to again later on. The alternative is to restructure things more significantly.
No, there's no directive fort that. Maybe it can be achieved with a custom directive (TemplateDirectiveModel) that can then write null into the variable through the Environment. (Unless the Environment API checks for null-s...)

Resources