How can I read a line of input in Inform 7? - inform7

I just want to prompt the user for a line of text in the middle of an action. The effect should be like this:
> north
The robot steps in front of you as you approach the gate.
"PAASSWAAAAWRD!!" it bellows.
Enter the password: _
At this point the game should pause and let the player try to guess the password. For example, suppose I guess “fribble”, which is not the password:
Enter the password: fribble
"WRONG PASSWAAARD!" roars the robot. "CHECK CAPS LAAAWWWWK!"
>
The behavior I want is similar to if the player consents, but I want the whole line of input, not just a yes or no.

Inform offers no easy way to do this, though you might be able to get to the keyboard primitives by dropping to Inform 6.
However it is possible to achieve the desired effect:
The Loading Zone is a room. "Concrete with yellow stripes. The Hold is north."
The robot is an animal in the Loading Zone. "However, a robot the size of an Arcturan megaladon guards the way."
North of the Loading Zone is the Hold.
Instead of going north from the Loading Zone:
say "The robot steps in front of you as you approach the gate. 'PAASSWAAAAWRD!!' it bellows.";
now the command prompt is "Enter password: ".
After reading a command when the command prompt is "Enter password: ":
if the player's command matches "xyzzy":
say "The robot folds itself up into a cube to let you pass.";
move the player to the Hold;
otherwise:
say "'WRONG PASSWAAARD!' roars the robot. 'CHECK CAPS LAAAWWWWK!'";
now the command prompt is ">";
reject the player's command.
I think this sort of thing is considered poor gameplay: it forces the player to guess, which damages the player's illusion of control and choice. The more conventional way would be to require the player to say the password:
The Loading Zone is a room. "Concrete with yellow stripes. The Hold is north."
The robot is an animal in the Loading Zone. The robot is either awake or asleep. The robot is awake. "[if awake]However, a robot the size of an Arcturan megaladon guards the way.[otherwise]A cube of metal the size of an Arctural megaladon snores loudly.[end if]".
North of the Loading Zone is the Hold.
Instead of going north from the Loading Zone when the robot is awake:
say "The robot steps in front of you as you approach the gate. 'PAASSWAAAAWRD!!' it bellows."
Instead of answering the robot that some text:
if the topic understood matches "xyzzy":
say "The robot folds itself up into a cube to let you pass.";
now the robot is asleep;
otherwise:
say "'WRONG PASSWAAARD!' roars the robot. 'CHECK CAPS LAAAWWWWK!'"
The commands say xyzzy and answer xyzzy and robot, xyzzy and say xyzzy to robot will all work.

The extension Questions by Michael Callaghan will help with this. Note that you might not be able to reliably test input case sensitively.

Dropping to I6 like this works in Inform 7.9.3. This is probably a bad idea.
Section 1 - Line input
Include (- Global user_input = 100; -) after "Parser.i6t".
The user input is a snippet that varies. The user input variable translates into I6 as "user_input".
To get a line of input: (-
KeyboardPrimitive(buffer, parse);
user_input = 100 + WordCount();
-).
You can then use the phrase "get a line of input" to read a line, and the phrase "the user's input" gives the line they entered. (A snippet is a kind of text.)
The example then looks like this:
Section 2 - Example
The Loading Zone is a room. "Concrete with yellow stripes. The Hold is north."
The robot is an animal in the Loading Zone. "However, a robot the size of an Arcturan megaladon guards the way."
North of the Loading Zone is the Hold.
Instead of going north from the Loading Zone:
say "The robot steps in front of you as you approach the gate. 'PAASSWAAAAWRD!!' it bellows.[paragraph break]";
say "Enter password: ";
get a line of input;
if the user input matches "xyzzy":
say "The robot folds itself up into a cube to let you pass.";
move the player to the Hold;
otherwise:
say "'WRONG PASSWAAARD!' roars the robot. 'CHECK CAPS LAAAWWWWK!'".
Test me with "n / password / n / xyzzy".

Related

In a UNIX pipeline how to get the user-tool interaction of the first stage piped into the next stage?

Page 32 of the book "The UNIX Programming Environment" makes this profound statement about UNIX pipes:
The programs in a pipeline actually run at the same time, not one
after another. This means that the programs in a pipeline can be
interactive; the kernel looks after whatever scheduling and
synchronization is need to make it all work.
Wow! By using pipes I can get parallel processing for free!
"I've got to illustrate this awesome capability to my colleagues" I thought. I will implement a demo: create a simple interactive tool that mimics what I type in at the command window. I'll name that tool mimic. Use a pipe to connect it to another tool which counts the number of lines and characters. I'll name that tool wc (sadly, I am working on Windows, which doesn't have the UNIX wc program so I must implement my own). The two tools will run on a command line like this:
mimic | wc
The output of mimic is piped into wc.
Well, that's the idea.
I implemented the mimic tool with a very simple Flex lexer, which I show below. Compiling it generated mimic.exe
When I run mimic.exe from the command line it does indeed mimic what I type:
> mimic
hello world
hello world
greetings
greetings
ctrl-c
I implemented wc using AWK. The AWK program (wc.awk) is shown below. When I run wc from the command line it does indeed count the lines and characters:
> echo Hello World | awk -f wc.awk
lines 1 chars 13
However, when I put them together with a pipe, they don't work as I imagined they would. Here's a sample run:
> mimic | awk -f wc.awk
hello world
greetings
ctrl-c
Hmm, nothing. No mimicking. No line counts. No char counts.
How come it's not working? What am I doing wrong, please?
What can I do to make it work as I expected? I expected it to work like this: I type something in at the command line. mimic repeats it, sending it to the pipe which sends it to wc which reports the number of lines and characters. I type in the next thing at the command line. mimic repeats it, sending it to the pipe which sends it to wc which reports the number of lines and characters. And so forth. That's the behavior I thought I was implementing.
Here is my simple Flex lexer (mimic):
%option noyywrap
%option always-interactive
%%
%%
int main(int argc, char *argv[])
{
yyin = stdin;
yylex();
return 0;
}
Here is my simple AWK program (wc):
{ nchars = nchars + length($0) + 1 }
END { printf("lines %-10d chars %d\n", NR, nchars) }
This question has little or nothing to do with Flex, Bison, Awk, and really not so much about Unix, either (since you're experimenting with Windows).
I don't have Windows handy, but the underlying issue is basically about stdio buffering, so it's reproducible on Unix as well.
To simplify, I only implemented mimic, which I did directly rather than using Flex (which is clearly overkill):
#include <stdio.h>
int main(void) {
for (int ch; (ch = getchar()) != EOF; ) putchar(ch);
return 0;
}
Since you use %always-interactive, which forces Flex to always read one character at a time with fgetc(), that has basically the same sequence of standard library calls as your program, except for simplifying fwrite of one byte to the equivalent putchar.
It certainly has the same execution characteristic:
$ ./mimic
Here we go round the mulberry busy,
Here we go round the mulberry busy,
the mulberry bush, the mulberry bush.
the mulberry bush, the mulberry bush.
In the above, I signalled end-of-input by typing Ctrl-D for the third line. On Windows, I would have had to have typed Ctrl-Z followed by Enter to get the same effect. If I kill the execution by typing Ctrl-C instead, I get roughly the same result (other than the fact that Ctrl-C shows up in the console):
$ ./mimic
Here we go round the mulberry bush,
Here we go round the mulberry bush,
the mulberry bush, the mulberry bush.
the mulberry bush, the mulberry bush.
^C
Now, since mimic just copies stdin to stdout, I might expect to be able to pipe it into itself and get the same result. But the output is a little different:
$ ./mimic | ./mimic
Here we go round the mulberry bush,
the mulberry bush, the mulberry bush.
Here we go round the mulberry bush,
the mulberry bush, the mulberry bush.
Again, I signaled end of input by typing Ctrl-D. And it was only after I typed the Ctrl-D that any output appeared; at that point, both lines were echoed. And if I terminate the program abruptly with Ctrl-C, I don't get any output at all:
$ ./mimic | ./mimic
Here we go round the mulberry bush,
the mulberry bush, the mulberry bush.
^C
OK, that's the data. Now, we need an explanation. And the explanation has to do with the way C standard library streams are buffered, which you can read about in the setvbuf manpage (and in many places on the web). I'll summarise:
The C standard specifies that all input functions execute "as if" implemented by repeated calls to fgetc, and all output functions "as if" implemented by repeated calls to fputc. Note that this means that there is nothing special about the chunk of bytes written by a single printf or fwrite. The library does not do anything to ensure that the sequence of calls is atomic. If you have two processes both writing to stdout, the messages can get interleaved, and that will happen from time to time.
The data written by fputc (and, consequently, all stdio output functions) is actually placed into an output buffer. This buffer is not part of the Operating System (which may add another layer of buffering). It's strictly part of the stdio library functions, which are ordinary userland functions. You could write them yourself (and it's a pretty good exercise to do so). From time to time, the contents of this buffer are sent to the appropriate operating system interface in order to be transferred to the output device.
"From time to time" is deliberately unspecific. There are three standard buffering modes, although the standard doesn't require them all to be used by a particular library implementation, and it also doesn't restrict the library implementation from using different buffering modes (although the three specified modes do basically cover the useful possibilities). However, most C library implementations you're likely to use do implement all three, pretty well as described in the standard. So take the following as a description of a common implementation technique, but be aware that on certain idiosyncratic platforms, it might not be accurate.
The three buffering modes are:
Unbuffered. In this mode, each byte written is transferred to the operating system (and, it is hoped, to the actual output device) as soon as possible.
Fully buffered. In this mode, there is a buffer of a predetermined size (often 8 kilobytes, but different library implementations have different defaults for different platforms). If you want to, you can supply your own buffer (of an arbitrary size) for a particular output stream, using the setvbuf standard library function (q.v.). Fully-buffered output might stay in the output buffer until it is full (although a given implementation may release output earlier). The buffer will, however, be sent to the operating system if you call fflush or fclose on the stream, or if fclose is called automatically when main returns. (It's not sent if the process dies, though.)
Line-buffered. In this mode, the stream again has an output buffer of a predetermined size, which is usually exactly the same as the buffer used in "fully-buffered" mode. The difference is that the buffer is also sent to the operating system when a new line character ('\n') is written. (If the buffer gets full before an end-of-line character is written, then it is sent to the operating system, just as in Fully-Buffered mode. But most of the time, lines will be fairly short, so the buffer will be sent to the OS at the end of each line.)
Finally, you need to know that stdout is fully-buffered by default unless the standard library can determine that stdout is connected to some kind of console device, in which case it is not fully-buffered. (On Unix, it is typically line-buffered.) By contrast, stderr is not fully-buffered. (On Unix, it is typically unbuffered.) You can change the buffering mode, and the buffer size if relevant, calling setvbuf before the first write operation to the stream.
The above-mentioned defaults are one of the reasons you are encouraged to write error messages to stderr rather than stdout: since stderr is unbuffered, the error message will appear as soon as possible. Also, you should normally put \n at the end of output line; if standard output is a terminal and therefore line buffered, the \n will ensure that the line is actually output, rather than languishing in the output buffer.
You can see all of this in action in the above examples. When I just ran ./mimic, leaving stdout mapped to the terminal, the output showed up each time I entered a line. (That also has to do with the way terminal input is handled by the terminal driver, which is another kettle of fish.)
But when I piped mimic into itself, the first mimics standard output is redirected to a pipe. A pipe is not a terminal, so that mimic's stdout is fully-buffered by default. Since the buffer is longer than the total input, the entire program runs without sending anything to stdout, until the buffer is flushed when stdout is implicitly closed by main returning.
Moreover, if I kill the process (by typing Ctrl-C, for example, or by sending it a SIGKILL signal), then the output buffer is never sent to the operating system, and nothing appears on the console.
If you're writing console apps using standard C library calls, it's very important to understand how stdio output buffering affects the sequence of outputs you see. That's just as true on Windows as on Unix. (Of course, it doesn't apply if you use native Windows or Posix I/O interfaces.)

Mint preproduced tokenurl(file size in range 42:50 Kb) , using svg to store full metadata on chain , Erc-721 , polygon (test & main network)

1- i will start by writing the general configurations(system, version, smart contract overall idea).
2- then i will show the main problem(with small code line, that i think it need edit).
3- third part i will show what i try until now and the results
4- at the end of i will add the github link for my full code.
note: the full original code produced by mr. PatrickAlphaC.
a- general configurations(system, version, smart contract overall idea):
a1- operation system: opensuse leap 15.3
a2- hardhat version: 2.8.3
a3- node version: v14.18.3
a4- npm version: 8.3.0
a5- metamask wallet addone to firefox
a6- target block chain: polygon(main net, test net)
a7- smart contract overall idea: use svg to create erc-721 nft, where it's metadata totally stored on chain(the smart contract mint tokenurl to polygon chain).
b- the main problem:
every thing work good as the size of minted file (tokenurl) less than 23.8kb(small than 23.8 kb). where i target mint file that twice this size (every tokenurl equal 50kb). so when try mint tokenurl with size (23.8 Kb < size < 50 Kb) i recive next error message.
An unexpected error occurred:
Error: ERROR processing /home/naive/demos/secondtry/deploy/01_Deploy_SVGNFT.js:
Error: cannot estimate gas; transaction may fail or may require manual gas limit (error={"name":"ProviderError","code":-
32000,"_isProviderError":true}, method="estimateGas", transaction={"from":"metamask wallet address","to":"contract address",
c- what i try until now and the results:
c1- try set the gas limit in "hardhat.config" but did not make any effect(it was during search so i do not remmber the form or values).
c2- in "01_Deploy_SVGNFT" add gaslimit to tx, so the code line look like next.
c2-0 origonal code line before edit it: tx = await svgNFT.create(svg)
c2-1 code line after edit it: tx = await svgNFT.create(svg, {gasLimit: 3000000 })
c2-2 the result: give me some error message about wrong syntic (forum, typing)
c3- in "01_Deploy_SVGNFT" add gaslimit to tx, so the code line look like next.
c3-0 origonal code line before edit it: tx = await svgNFT.create(svg)
c3-1 code line after edit it: tx = await svgNFT.create({svg}, {gasLimit: 3000000 })
c3-2 the results:
3-2-0 contract deploying, svg uploading, contract verifying, the matic value decrease in metamask wallet(gas value transfer succeed) all thing look good.
3-2-1 when go to opensea there's no image appears.
3-2-2 when go to polygonscan or etherscan and use token id to see the token uri it return nothing (ther's no metadata string appears, nothing appears).
d- the next github link for full code(contracts, deploy, hardhat.config.js, helper-hardhat-config.js and img folder that contains (preproduced tokenurl)
https://github.com/naive2022/onchainfork
hope help me find how can mint preproduced tokenurl(every file size is 50kb) without face this problem when use polygon test or polygon main network.
the final results rinkeby network can not accept(mint token url) with size above 23 kb approximately

How to terminate outgoing CSD call?

I have a gsm modem called iRZ. I use it for CSD call(getting meterage from meter). I call to meter like this: ATDpho0ne_number
Then I exchange data.
And finally I need to terminate this call, but how?
I tried: "+++" next "ATH", and "ATH0". But it doesn't work...
Help, please...
You did not specify the exact modem type so I tell you two options.
Option 1:
The +++ character sequence must be preceded and
followed by a pause of at least 1000 ms. The +++ characters must be entered in quick succession, all within 1000 ms.
Option 2:
You have to set up a "code word" by ATM Control utility and that code word will switch back the modem to AT mode and then you can issue the ATH command.

Who know the history of unix fork?

Fork is a great tool in unix.We can use it to generate our copy and change its behaviour.But I don't know the history of fork.
Does someone can tell me the story?
Actually, unlike many of the basic UNIX features, fork was a relative latecomer (a).
The earliest existence of multiple processes within UNIX consisted of a few (fixed number of) processes, one per terminal that was attached to the PDP-7 machine (b).
The basic idea was that the shell process for a given terminal would accept a command from the user, locate the program file, load a small bootstrap program into high memory and jump to it, passing enough details for the bootstrap code to load the program file.
The bootstrap code, after loading the program into low memory (overwriting the shell), would then jump to it.
When the program was finished, it would call exit but it wasn't like the exit we know and love today. This exit would simply reload the shell and run it using pretty much the same method used to load the program in the first place.
So it was really more like a rudimentary exec command, the one that replaces your current program with another, in the same process space.
The shell would exec your program then, when your program was done, it would again exec the shell by calling exit.
This method was similar to that found in many other interactive systems at the time, including the Multics from whence UNIX got its name.
From the two-way exec, it was actually not that big a leap to adding fork as a process duplicator to work in conjunction. While many systems run another program directly, it's this "just add what's needed" method which is responsible for the separation of duties between fork and exec in UNIX. It also resulted in a very simple fork function.
If you're interested in the early history of various features(c) of Unix, you cannot go past the article The Evolution of the Unix Time-Sharing System by Dennis Ritchie, presented at a 1979 conference in Australia, and subsequently published by AT&T.
(a) Though I mean latecomer in the sense that the separation of the four fundamental forces in the universe was "late", happening some 0.00000000001 seconds after the big bang.</humour>.
(b) Since a question was raised in a comment as to how the shells were originally started off, there's a great resource holding very early source code for Unix over at The Unix Heritage Society, specifically the source code archives and, in particular, the first edition.
The init.s file from the first edition shows how the fixed number of shell processes were created (slightly reformatted):
...
mov $itab, r1 / address of table to r1
1:
mov (r1)+, r0 / 'x, x=0, 1... to r0
beq 1f / branch if table end
movb r0, ttyx+8 / put symbol in ttyx
jsr pc, dfork / go to make new init for this ttyx
mov r0, (r1)+ / save child id in word offer '0, '1, etc
br 1b / set up next child
1:
...
itab:
'0; ..
'1; ..
'2; ..
'3; ..
'4; ..
'5; ..
'6; ..
'7; ..
0
Here you can see the snippet which creates the processes for each connected terminal. These are the days of hard-coded values, no auto detection of terminal quantity involved. The zero-terminated table at itab is used to create a number of processes and hopefully the comments from the code explain how (the only possibly tricky bit is the labels - though there are multiple 1 labels, you branch to the nearest one in a given direction, hence 1b means the closest 1 label in the backwards direction).
The code shown simply processes the table, calling dfork to create a process for each terminal and start getty, the login prompt. The getty program, in turn, eventually started the shell. From that point, it's as I described in the main part of this answer.
(c) No paths (and use of temporary links to get around this limitation), limited processes, why there's a GECOS field in the password file, and all sorts of other trivia, generally interesting only to uber-geeks, of course.

What are the dark corners of Vim your mom never told you about? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
There are a plethora of questions where people talk about common tricks, notably "Vim+ctags tips and tricks".
However, I don't refer to commonly used shortcuts that someone new to Vim would find cool. I am talking about a seasoned Unix user (be they a developer, administrator, both, etc.), who thinks they know something 99% of us never heard or dreamed about. Something that not only makes their work easier, but also is COOL and hackish. After all, Vim resides in the most dark-corner-rich OS in the world, thus it should have intricacies that only a few privileged know about and want to share with us.
Might not be one that 99% of Vim users don't know about, but it's something I use daily and that any Linux+Vim poweruser must know.
Basic command, yet extremely useful.
:w !sudo tee %
I often forget to sudo before editing a file I don't have write permissions on. When I come to save that file and get a permission error, I just issue that vim command in order to save the file without the need to save it to a temp file and then copy it back again.
You obviously have to be on a system with sudo installed and have sudo rights.
Something I just discovered recently that I thought was very cool:
:earlier 15m
Reverts the document back to how it was 15 minutes ago. Can take various arguments for the amount of time you want to roll back, and is dependent on undolevels. Can be reversed with the opposite command :later
:! [command] executes an external command while you're in Vim.
But add a dot after the colon, :.! [command], and it'll dump the output of the command into your current window. That's : . !
For example:
:.! ls
I use this a lot for things like adding the current date into a document I'm typing:
:.! date
Not exactly obscure, but there are several "delete in" commands which are extremely useful, like..
diw to delete the current word
di( to delete within the current parens
di" to delete the text between the quotes
Others can be found on :help text-objects
de Delete everything till the end of the word by pressing . at your heart's desire.
ci(xyz[Esc] -- This is a weird one. Here, the 'i' does not mean insert mode. Instead it means inside the parenthesis. So this sequence cuts the text inside parenthesis you're standing in and replaces it with "xyz". It also works inside square and figure brackets -- just do ci[ or ci{ correspondingly. Naturally, you can do di (if you just want to delete all text without typing anything. You can also do a instead of i if you want to delete the parentheses as well and not just text inside them.
ci" - cuts the text in current quotes
ciw - cuts the current word. This works just like the previous one except that ( is replaced with w.
C - cut the rest of the line and switch to insert mode.
ZZ -- save and close current file (WAY faster than Ctrl-F4 to close the current tab!)
ddp - move current line one row down
xp -- move current character one position to the right
U - uppercase, so viwU upercases the word
~ - switches case, so viw~ will reverse casing of entire word
Ctrl+u / Ctrl+d scroll the page half-a-screen up or down. This seems to be more useful than the usual full-screen paging as it makes it easier to see how the two screens relate. For those who still want to scroll entire screen at a time there's Ctrl+f for Forward and Ctrl+b for Backward. Ctrl+Y and Ctrl+E scroll down or up one line at a time.
Crazy but very useful command is zz -- it scrolls the screen to make this line appear in the middle. This is excellent for putting the piece of code you're working on in the center of your attention. Sibling commands -- zt and zb -- make this line the top or the bottom one on the sreen which is not quite as useful.
% finds and jumps to the matching parenthesis.
de -- delete from cursor to the end of the word (you can also do dE to delete until the next space)
bde -- delete the current word, from left to right delimiter
df[space] -- delete up until and including the next space
dt. -- delete until next dot
dd -- delete this entire line
ye (or yE) -- yanks text from here to the end of the word
ce - cuts through the end of the word
bye -- copies current word (makes me wonder what "hi" does!)
yy -- copies the current line
cc -- cuts the current line, you can also do S instead. There's also lower cap s which cuts current character and switches to insert mode.
viwy or viwc. Yank or change current word. Hit w multiple times to keep selecting each subsequent word, use b to move backwards
vi{ - select all text in figure brackets. va{ - select all text including {}s
vi(p - highlight everything inside the ()s and replace with the pasted text
b and e move the cursor word-by-word, similarly to how Ctrl+Arrows normally do. The definition of word is a little different though, as several consecutive delmiters are treated as one word. If you start at the middle of a word, pressing b will always get you to the beginning of the current word, and each consecutive b will jump to the beginning of the next word. Similarly, and easy to remember, e gets the cursor to the end of the current, and each subsequent, word.
similar to b/e, capital B and E move the cursor word-by-word using only whitespaces as delimiters.
capital D (take a deep breath) Deletes the rest of the line to the right of the cursor, same as Shift+End/Del in normal editors (notice 2 keypresses -- Shift+D -- instead of 3)
One that I rarely find in most Vim tutorials, but it's INCREDIBLY useful (at least to me), is the
g; and g,
to move (forward, backward) through the changelist.
Let me show how I use it. Sometimes I need to copy and paste a piece of code or string, say a hex color code in a CSS file, so I search, jump (not caring where the match is), copy it and then jump back (g;) to where I was editing the code to finally paste it. No need to create marks. Simpler.
Just my 2cents.
:%!xxd
Make vim into a hex editor.
:%!xxd -r
Revert.
Warning: If you don't edit with binary (-b), you might damage the file. – Josh Lee in the comments.
gv
Reselects last visual selection.
Sometimes a setting in your .vimrc will get overridden by a plugin or autocommand. To debug this a useful trick is to use the :verbose command in conjunction with :set. For example, to figure out where cindent got set/unset:
:verbose set cindent?
This will output something like:
cindent
Last set from /usr/share/vim/vim71/indent/c.vim
This also works with maps and highlights. (Thanks joeytwiddle for pointing this out.) For example:
:verbose nmap U
n U <C-R>
Last set from ~/.vimrc
:verbose highlight Normal
Normal xxx guifg=#dddddd guibg=#111111 font=Inconsolata Medium 14
Last set from ~/src/vim-holodark/colors/holodark.vim
:%TOhtml
Creates an html rendering of the current file.
Not sure if this counts as dark-corner-ish at all, but I've only just learnt it...
:g/match/y A
will yank (copy) all lines containing "match" into the "a/#a register. (The capitalization as A makes vim append yankings instead of replacing the previous register contents.) I used it a lot recently when making Internet Explorer stylesheets.
Want to look at your :command history?
q:
Then browse, edit and finally to execute the command.
Ever make similar changes to two files and switch back and forth between them? (Say, source and header files?)
:set hidden
:map <TAB> :e#<CR>
Then tab back and forth between those files.
Vim will open a URL, for example
vim http://stackoverflow.com/
Nice when you need to pull up the source of a page for reference.
Macros can call other macros, and can also call itself.
eg:
qq0dwj#qq#q
...will delete the first word from every line until the end of the file.
This is quite a simple example but it demonstrates a very powerful feature of vim
Assuming you have Perl and/or Ruby support compiled in, :rubydo and :perldo will run a Ruby or Perl one-liner on every line in a range (defaults to entire buffer), with $_ bound to the text of the current line (minus the newline). Manipulating $_ will change the text of that line.
You can use this to do certain things that are easy to do in a scripting language but not so obvious using Vim builtins. For example to reverse the order of the words in a line:
:perldo $_ = join ' ', reverse split
To insert a random string of 8 characters (A-Z) at the end of every line:
:rubydo $_ += ' ' + (1..8).collect{('A'..'Z').to_a[rand 26]}.join
You are limited to acting on one line at a time and you can't add newlines.
^O and ^I
Go to older/newer position.
When you are moving through the file (by searching, moving commands etc.) vim rember these "jumps", so you can repeat these jumps backward (^O - O for old) and forward (^I - just next to I on keyboard). I find it very useful when writing code and performing a lot of searches.
gi
Go to position where Insert mode was stopped last.
I find myself often editing and then searching for something. To return to editing place press gi.
gf
put cursor on file name (e.g. include header file), press gf and the file is opened
gF
similar to gf but recognizes format "[file name]:[line number]". Pressing gF will open [file name] and set cursor to [line number].
^P and ^N
Auto complete text while editing (^P - previous match and ^N next match)
^X^L
While editing completes to the same line (useful for programming).
You write code and then you recall that you have the same code somewhere in file. Just press ^X^L and the full line completed
^X^F
Complete file names.
You write "/etc/pass" Hmm. You forgot the file name. Just press ^X^F and the filename is completed
^Z or :sh
Move temporary to the shell. If you need a quick bashing:
press ^Z (to put vi in background) to return to original shell and press fg to return to vim back
press :sh to go to sub shell and press ^D/exit to return to vi back
Typing == will correct the indentation of the current line based on the line above.
Actually, you can do one = sign followed by any movement command. ={movement}
For example, you can use the % movement which moves between matching braces. Position the cursor on the { in the following code:
if (thisA == that) {
//not indented
if (some == other) {
x = y;
}
}
And press =% to instantly get this:
if (thisA == that) {
//not indented
if (some == other) {
x = y;
}
}
Alternately, you could do =a{ within the code block, rather than positioning yourself right on the { character.
" insert range ip's
"
" ( O O )
" =======oOO=(_)==OOo======
:for i in range(1,255) | .put='10.0.0.'.i | endfor
This is a nice trick to reopen the current file with a different encoding:
:e ++enc=cp1250 %:p
Useful when you have to work with legacy encodings. The supported encodings are listed in a table under encoding-values (see help encoding-values). Similar thing also works for ++ff, so that you can reopen file with Windows/Unix line ends if you get it wrong for the first time (see help ff).
imap jj <esc>
Let's see some pretty little IDE editor do column transposition.
:%s/\(.*\)^I\(.*\)/\2^I\1/
Explanation
\( and \) is how to remember stuff in regex-land. And \1, \2 etc is how to retrieve the remembered stuff.
>>> \(.*\)^I\(.*\)
Remember everything followed by ^I (tab) followed by everything.
>>> \2^I\1
Replace the above stuff with "2nd stuff you remembered" followed by "1st stuff you remembered" - essentially doing a transpose.
Not exactly a dark secret, but I like to put the following mapping into my .vimrc file, so I can hit "-" (minus) anytime to open the file explorer to show files adjacent to the one I just edit. In the file explorer, I can hit another "-" to move up one directory, providing seamless browsing of a complex directory structures (like the ones used by the MVC frameworks nowadays):
map - :Explore<cr>
These may be also useful for somebody. I like to scroll the screen and advance the cursor at the same time:
map <c-j> j<c-e>
map <c-k> k<c-y>
Tab navigation - I love tabs and I need to move easily between them:
map <c-l> :tabnext<enter>
map <c-h> :tabprevious<enter>
Only on Mac OS X: Safari-like tab navigation:
map <S-D-Right> :tabnext<cr>
map <S-D-Left> :tabprevious<cr>
Often, I like changing current directories while editing - so I have to specify paths less.
cd %:h
I like to use 'sudo bash', and my sysadmin hates this. He locked down 'sudo' so it could only be used with a handful of commands (ls, chmod, chown, vi, etc), but I was able to use vim to get a root shell anyway:
bash$ sudo vi +'silent !bash' +q
Password: ******
root#
I often use many windows when I work on a project and sometimes I need to resize them. Here's what I use:
map + <C-W>+
map - <C-W>-
These mappings allow to increase and decrease the size of the current window. It's quite simple but it's fast.
:r! <command>
pastes the output of an external command into the buffer.
Do some math and get the result directly in the text:
:r! echo $((3 + 5 + 8))
Get the list of files to compile when writing a Makefile:
:r! ls *.c
Don't look up that fact you read on wikipedia, have it directly pasted into the document you are writing:
:r! lynx -dump http://en.wikipedia.org/wiki/Whatever
Not an obscure feature, but very useful and time saving.
If you want to save a session of your open buffers, tabs, markers and other settings, you can issue the following:
mksession session.vim
You can open your session using:
vim -S session.vim
Map F5 to quickly ROT13 your buffer:
map <F5> ggg?G``
You can use it as a boss key :).
I use vim for just about any text editing I do, so I often times use copy and paste. The problem is that vim by default will often times distort imported text via paste. The way to stop this is to use
:set paste
before pasting in your data. This will keep it from messing up.
Note that you will have to issue :set nopaste to recover auto-indentation. Alternative ways of pasting pre-formatted text are the clipboard registers (* and +), and :r!cat (you will have to end the pasted fragment with ^D).
It is also sometimes helpful to turn on a high contrast color scheme. This can be done with
:color blue
I've noticed that it does not work on all the versions of vim I use but it does on most.
I just found this one today via NSFAQ:
Comment blocks of code.
Enter Blockwise Visual mode by hitting CTRL-V.
Mark the block you wish to comment.
Hit I (capital I) and enter your comment string at the beginning of the line. (// for C++)
Hit ESC and all lines selected will have // prepended to the front of the line.

Resources