Wandering Thoughts archives

2021-10-26

Vim visual mode and an unfortunate restriction on the filter operation

Since discovering Vim's visual (selection) mode I've found myself using it periodically for various things (which I may write up some other day, as there are a couple of common cases where it comes in handy). However, I recently re-discovered an unfortunate restriction on operators on the visual area, specifically filtering. This is that no matter what (as far as I know), they apply on a line-wise basis even if you made a visual block selection.

Suppose, hypothetically, that you have a shell script or a program with a block of comments:

# This is a comment that
# I am in the process of editing and
# shuffling words around. And
# sentences too. It's wound up
# all ragged.

What I often want to do is reflow this paragraph of comments. If you're an innocent or forgetful person, one way to do this in Vim is to use Ctrl-V to make a block selection of the actual comment text, excluding the '# ' that starts them all, and then reflow it with !fmt (my normal choice). Unfortunately, as explicitly documented, filtering operates in line mode even if you made a visual selection, which means that if you do this fmt will reflow your leading '# ' comment markers with the text and suddenly you won't have a comment block.

(Fortunately you can undo this, which is what I immediately did when I noticed that my reflow seemed to have gone very wrong. Then I remembered the special 'always line based' operation of filtering.)

The Vim documentation for the visual gq command and comment formatting suggests that under the right circumstances, Vim will magically recognize comments and do the right thing. However, processing a block of text through fmt is more general (it works in any context where you have a captive block of text that you want to reflow, not just comments), and I'm a person of fixed Vim habits.

I kind of wish that Vim always did filtering with only the selection regardless of what sort of visual selection it was, but I sort of see why Vim does it the current way. For block mode specifically, Vim would definitely need a rule to describe when it introduced newlines (you'd normally want them at the end of each line of the block selection).

(For my own use I have a more general replacement for fmt (also), but this doesn't help when I'm editing a configuration file or script as root or I'm on a system where I haven't dragged over my usual set of tools.)

unix/VimVisualModeFilterLimit written at 23:29:41;

Go 1.18 will embed source version information into binaries

Since Go 1.13, Go has embedded information about the modules used to build a program into its binary, and has reported them if you used 'go version -m ...' (release notes). This information has historically included a variety of things, including the path and module that the program was built from, an indication of any module replacements being used, and a marker that the program was being built from a source tree instead of with 'go install ...@...'. However, it hasn't historically included any information about the state of the source tree when you built from source.

In Go 1.18, this is changing due to issue 37475 and issue 35667. To quote from the draft release notes:

The go command now embeds version control information in binaries including the currently checked-out revision and a flag indicating whether edited or untracked files are present. Version control information is embedded if the go command is invoked in a directory within a Git or Mercurial repository, and the main package and its containing main module are in the same repository. This information may be omitted using the flag -buildvcs=false.

Additionally, the go command embeds information about the build including build and tool tags (set with -tags), compiler, assembler, and linker flags (like -gcflags), whether cgo was enabled, and if it was, the values of the cgo environment variables (like CGO_CFLAGS). This information may be omitted using the flag -buildinfo=false. [...]

(I don't know if the module and other information that will be embedded also includes information about the Go workspace you're in, if you're in one.)

At the moment this information is recorded in Go binaries in a form that can be read by Go 1.17's 'go version -m', and probably this also works for earlier versions (as I believe much of this information is actually in the binary as text).

The current information is pretty verbose by default since cgo is generally enabled, and this adds five lines of output, even if the code being compiled didn't actually use it and you have no special environment variables set. I suspect that this won't get reduced before release; the Go team seems to like being comprehensive here.

If nothing else, having this information embedded into binaries will make it harder to lose track of what exactly you're running. Now you have a better chance of figuring out the provenance of some old Go binary that's been running in the corner for who knows how long. People who distribute binaries widely and build them doing funny things may now have more of those funny things be somewhat visible, though. Well, until they turn these features off with those documented flags.

(As threatened, Go 1.18 will only support building programs in module mode, so this information only coming from 'go version -m' doesn't matter any more.)

Sidebar: What this extra information looks like today

Here is the additional output added by this, as reported by 'go version -m' from the current development version:

       build   compiler        gc
       build   tags    goexperiment.regabiwrappers,goexperiment.regabireflect,goexperiment.regabiargs
       build   CGO_ENABLED     true
       build   CGO_CPPFLAGS
       build   CGO_CFLAGS
       build   CGO_CXXFLAGS
       build   CGO_LDFLAGS
       build   gitrevision     4f8a1b5f197fc69bc1252b32b5a8ed670ff557b6
       build   gituncommitted  false

I wouldn't be surprised if some of the current build tags go away in the released version of Go 1.18, as some experiments are promoted out of that state.

Documentation on the current experiments is in the source code in internal/goexperiment/flags.go, and can be gotten for your particular version of Go with 'go doc goexperiment.Flags'. I'm not sure how you can find out the default set of experiments enabled in your version of Go, but in the source code this seems to be in the 'baseline' variable set in ParseGOEXPERIMENT() function in internal/buildcfg/exp.go. The current Go 1.18 build tags reported above appear to be this baseline state on amd64.

programming/GoVersionOfYourSource written at 00:09:30;


Page tools: See As Normal.
Search:
Login: Password:

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.