Testing buffer list with Vader - vim

I am writing a vim plugin and I noticed a bug where temporary buffers are not cleaned up automatically. I am using the Vader test framework plugin to test it and I would like to be able to verify the fix with a Vader test and prevent regressions.
I would use :ls command to verify the buffer list doesn't grow but I don't know how to access the output of this from Vader.
So, is it possible to use Vader to test that the buffer list doesn't grow? Essentially, I just need to verify that the buffer list that is displayed is the same after executing my command as before. I don't need fine-grained check on the buffer list.

This isn't specific to Vader, but you can capture the output of any Ex command via :redir, or more comfortably (in newer Vim versions) with :help execute().
However, for the use case as you describe it, you don't need to parse the output of :ls at all: Buffers are allocated with increasing numbers, and the highest one can be obtained via bufnr('$'). So, just by storing the original value and comparing it with a later query, you can ensure that no additional buffers are created.
If you do need more more fine-grained checks on the buffers (your question isn't very clear on that), you can use filter() over all possible buffers, e.g. to obtain all listed buffers (or loaded buffers via bufloaded()):
:echo filter(range(1, bufnr('$')), 'buflisted(v:val)')

Related

Why is it slower to print directly to console/terminal than redirecting?

Why does it take significantly more time to print multiple lines to the terminal rather than redirecting it to a file which seems to be almost instant ?
Primarily, terminals are just plain slow. For every update, they have to:
Parse and interpret any control codes.
Parse, interpret and render any escape codes.
Interpret and account for any multibyte and composed characters.
Update appropriate screen and scroll buffers.
Render this with appropriate fonts.
and possibly do all of the above over again if you use screen or tmux.
Meanwhile, for redirecting to a file, you just have to:
Dump data into RAM (for later writeback to storage).
This step is so minor that it doesn't even register on the terminal's checklist.
This is not something people optimize for, because the speed of your terminal is rarely an issue. The difference between terminals can be 50x (VGA vs fbcon back in the day), and you can time it with a simple time cat somebigfile.txt.

How to query the character under the current cursor position or anywhere on the screen in bash

I know that the following statement is a way to query the current cursor position:
echo -en '\033[6n'
Does anyone know how to query the character under the cursor or populate a array with the contents of the current screen/window? I've searched through the ANSI terminal commands however a lot of these are pretty abstract and it doesn't look like they would do this properly. I also looked into doing it with the tcup command with no luck.
Thank you for your help.
An ANSI terminal is not really required to be able to tell you what is on the screen. You're supposed to remember that yourself, if you need the information. The popular ncurses library does that, for example, although it only allows you to export the screen to a file, and the fileformat is not documented. In any event, bash doesn't use ncurses, so it really doesn't know anything about the state of the console.
Most probably, the screen you are talking about is actually an artifact of some terminal emulation program like xterm. Those programs run in userspace, and rarely (if ever) have an external query interface. However, linux does have a console (actually, a number of emulated consoles, but using the display's console mode) and it maintains the display memory for those consoles. And furthermore, it provides an interface for reading the console memory, usually available as /dev/vcsN (for values of N between 0 and the number of virtual consoles linux was compiled with). /dev/vcs0 is the "current" console (the one which is visible).
Most linux distributions restrict access to /dev/vcsN, so if you want to play around with them you'll either need special privileges or you'll need to use root privileges to change the access permissions on the device files. (Ubuntu appears to provide rw access to users in group tty; check ls -l /dev/vcs0 to see how your system does it.) (And, of course, you'll need to find the console :-) Try CtlAlt1; CtlAlt7 will probably give you back your GUI.)
Once you've worked out the access issues, you could do something like cp /dev/vcs0 console_memory to take a look at it. What you'll find is that it is just a 2D array of characters with no newlines, and no indication of what the dimensions are. (You can get the dimensions with an ioctl or by looking at the environment variables $LINES and $COLUMNS.)
You could use /dev/vcsa0 instead; it has a slightly different format using two bytes per character in order to store display attributes (foreground and background colours, mostly) as well as the character. Also, the first four bytes of /dev/vcsaN are the screen dimensions and cursor position (one byte per coordinate), which will save you the work of querying the cursor position.
Note that the console does not support a full Unicode character set. In fact, it can only display 512 different glyphs at once. In order to maximize the available glyph space, Linux may reassign some codes to needed symbols, and this mapping is not part of the console memory. So the code extracted from console memory might not have an obvious mapping to a Unicode code, but it should work fine for standard ANSI characters.

Atomic write with Vim

Can I configure Vim so it does an atomic write?
The default Vim behavior is:
move file.txt to file.txt~
write buffer contents to file.txt
But this causes some problem with compass watch for example
I would like behavior like:
write buffer contents to file.txt~
move file.txt~ to file.txt
I've looked at the backup, backupcopy and writebackup options but I can't get Vim configured as I want.
:set backupcopy=yes is probably what you want.
You could also use the `backupskip' option on the paths you are particularly worried about.
I'm not 100% sure how atomic writes are typically handled in arbitrary software. I could be wrong, but something like this is probably handled or configurable at the kernel level (and that would seem like the optimal place to handle such a notion as atomic writes for multiple reasons such as: efficiency, direct access to hardware, the DRY principle, application agnosticism, etc.). A more manual and user-space way that I can think of accomplishing this however would be to first write to some new/unique/random file inside of /tmp, then mv that file that you just wrote under /tmp into place. You can use Vim's tempname() function to help you accomplish this in a platform-agnostic manner (see :help tempname()).

Reading file in Kernel Mode

I am building a driver and i want to read some files.
Is there any way to use "ZwReadFile()" or a similar function to read the
contents of the files line by line so that i can process them in a loop.
The documentation in MSDN states that :-
ZwReadFile begins reading from the given ByteOffset or the current file position into the given Buffer. It terminates the read operation under one of the following conditions:
The buffer is full because the number of bytes specified by the Length parameter has been read. Therefore, no more data can be placed into the buffer without an overflow.
The end of file is reached during the read operation, so there is no more data in the file to be transferred into the buffer.
Thanks.
No, there is not. You'll have to create a wrapper to achieve what you want.
However, given that kernel mode code has the potential to crash the system rather than the process it runs in, you have to make sure that problems such as those known from usermode with very long lines etc will not cause issues.
If the amount of data is (and will stay) below the threshold of what registry values can hold, you should use that instead. In particular REG_MULTI_SZ which has the properties you are looking for ("line-wise" storage of data).
In this situation unless performance is a critical (like 'realtime') then I would pass the filtering to a user mode service or application. Send the file name to the application to process. A user mode application is easier to test and easier to debug. It wont blue screen or hang your box either.

Faster multi-file keyword completion in Vim?

While searching for my python completion nirvana in vim, I have come to really love <C-x> <C-i>: "keywords in the current and included files". This almost always gets me a long nasty name from another module completed, which is great.
(Omni-completion is obviously better when it works, but too often it reports it can't find any matches. Ok, Python isn't Java, I get it)
The only problem with this multi-file completion is it's very slow: on my netbook, a file with a reasonable set of imports can take up to 4 or 5 seconds to parse every time I hit <C-x> <C-i>. It seems to load every imported file every time I hit <C-x> <C-i>. Is there any way to cache the files or speed up this process? Would using tag completion be faster?
It is quite possible that this process takes some time if you're working on projects with multiple source files (vim needs to parse all included source files to find more included source files and to build the word list.) You could use tag-completion, which uses the output of ctags to do almost the same, but you'd need to run a few tests to tell the speed difference.
I personally use complete completion (<C-P> or <C-N> in insert mode.) By default, it matches all words in all buffers (even buffers that have been unloaded, i.e. files that have been closed), but is really fast. I found that the completion works quite accurately nonetheless, even if you activate it after 2-3 characters.

Resources