Subtitles section Play video Print subtitles BRAM MOOLENAAR: Wow. Is it working? OK. It's amazing to see so many people show up for this talk. I've done a few talks before, and conferences, and mostly people have to choose between two rooms and they never choose mine. So this is very good. I hope you enjoyed some of the food. I'm afraid it's not enough. We didn't really expect so many people to show up. So let me try to make it up by giving you a good presentation. It's called 2.0 because I did this presentation in a different form some years ago in Holland. And I think none of you were there, so it's all new to you. But I did update it with some new stuff, so hopefully it will be interesting. There's a big crowd now, so I'll try to answer questions near the end. But if there's something that you don't understand on the slides or something like that, just shout. OK, let's get started. So text editing, that's what we're talking about. I think we all know the problem that we're working with text the whole day, with email, or whatever you're working on with log files, HTML, documentation, et cetera, et cetera. If I look at myself, I spend most of my day editing text, if I'm not working on Vim, then it's email or something else, and it takes an awful lot of time. So if we can improve our text editing skills a little bit, that helps a lot. We can get more work done. Mostly when I'm not working on text editing, then mostly I'm doing meetings or stuff like that. So maybe somebody can do a presentation on how to do effective meetings. That would help. So I'm going to try to explain to you how to get more work done in less time. So if you're paid by the hour, you can leave now. Of course, I'm using Vim for all the examples. That doesn't mean that I think that Vim is the only text editor that you can use or should use. As a basic rule, if you have a text editor that's good, that can do everything you need, has enough features, it does the work, and you can still expound it to do the work you expect it to do, than just stick to it. I mean why learn another editor when you already have all the skills in the one you're using? So if you're using index, you're happy with it, I'm not going to tell you to leave it alone, unless, maybe, you think it's not good. Also, I sometimes see people, even software developers, using Notepad or a similar editor. I mean, that's terrible. I mean, you're wasting a lot of time. So basically, you either use the editor that you have, that you're happy with, or you switched to Vim. There's no other rule. So otherwise, I'm not going to discuss which editor is best. That's another discussion, and not very interesting. I think most of the people here are using Vim, anyway. Oh, let me ask that. How many people of you are actually mostly using Emacs? OK, OK. We'll try to convert some people today. I won't ask how many people are using Vim, because then it's all hands up, so let's don't do this. OK, how are we going to explain these habits that I was talking about in the title? The first step, a very important step-- well, all three are important, so. The first step is how to know that you're doing something inefficiently. Mostly, that's when you are repeating the same thing over, and over, and over again, and you think, well, there must be a quicker way to do this. Must be a smarter way to do this. For example, what I do myself quite often is you have a function name, somebody refuse your change says, this is a terrible function name. Use another name. So you have to go all over your code and change one name into another. Well obviously, if you're going to find the name, type the same name over and over again, then not only is it not efficient, you're also going to make mistakes that you have to fix later. And it's even getting more complicated, like if you have five names that you have to change into five different names. And there's a pattern in how you change them, and obviously, you don't want to type that. You want to find some way to do it quickly. The trick here is that you have to do this while you are working. So every time you're working on something, you have to kind of look back, like what did I do the last five minutes? Did I repeat myself? Can I do this in a quicker way? So you have to detect your inefficiency. That's actually quite tricky, but I'm going to give examples, of course. Well, find a quicker way. Well, every good editor has ways to do things quickly. The trick is, how do you find them? You don't want to spend the whole day to find a better solution. You want to find it in five minutes. So I'm going to give you some ideas of how to find better ways, quicker ways. And the last, and also important, is how to make it a habit? You can read the whole reference manual of Vim, but that doesn't mean you know the commands. You don't really use them. So you have to make it a habit to actually use them, otherwise you'll have to think about every key that you type. You really want to get the commands in your fingers, done automatically. So it must be a habit. So basically, what you need to do is you have to see the problem, you have to find a solution, and make it a habit. That's quite simple, isn't it? Let's go on. About the title, I mean, why seven habits? Why not three, or why not 42? Well actually, 42 will be a different book. I saw this book and I read it, and I think it's quite an interesting book and gives you a lot of tips about work, and life, and family, and all kinds of things, and I can recommend it for normal reading, and I also liked the title. So I made the title for this presentation a variant on this title. Of course, there's also another variant on this title: seven years of highly defective people. I just love Dilbert. This is really a great book that explains a bit about the characters around Dilbert, and why they are drawn the way they are drawn, and how they developed over the first seven years. It's really a nice book, especially if you like Dilbert, of course. OK, let's get on with the first habit. This is something simple to start with. So you have these codes, and you're wondering, where is this variable used? I used rsc, for example. So what do you do? You search for the name. And you keep pressing n, n, n, n, to find all occurrences of that variable. And then you search for another variable, and do the same thing again, you browse through the whole code. And then you type a long n. But if you look closely, you can see there's a typo in there, so you don't find anything. Well, this is what happens a lot if you don't know the commands of your editor. So you keep typing a lot of text, typing a lot of commands, and wasting a lot of time, obviously. So what's a quicker way? Well, what's important here, how do you find a quicker way? In this example, I will say that you just search in the Help for Vim, and you find something about Search Highlighting. And you think, well, I'm searching, I want to see what's going on, so highlighting will help. And so you turn on the Highlight Search option. Of course, you need to search a little bit in Help to find this. And especially the Star command. Well, I think most people that actually use Vim know about the Star command, especially if you looked on the website. I think it's actually the first step, one of the first steps. Well obviously, what you then get is that you get all the things you were looking for highlighted, and it gives you a great overview of where a variable's used. Of course, this is just a small screen. If you have one of the bigger screens, you have a much bigger overview, and that works really great. Of course, the Star command you use when the cursor is on a word. So you type Star, and it looks for other occurrences of that word. So how do you make this a habit? Well, the easiest is to switch on Highlight Search in your Vim RC, file, in your start-up file, so it's always on. I do that. I always have the Highlight Search option on. That does mean that for every search you do, you see all the matches. That sometimes means you have a whole yellow screen. That happens. And so I added the hint here that you can switch it off for a moment, and then it's switched on automatically again when you search for something. Again, you have to to make it a habit, so just repeat that Star command. You have the option switched on, so that works. You have to use it again and again. And after a little while, you don't even think of it. You just look at a variable, you automatically press Star. There's, of course, many other ways to move around quickly. Just to mention one, folding was added in Vim 6. Some people like it, some people don't. So you'll have to find out yourself if you like it or not. Maybe I can switch and give a life-- oh, that's working. So what I have here is just a source file. How does this work? Here you see a marker in the source file with three brackets, and that actually marks an area in the code that can be folded away. So I can just click on the Minus sign. If I click right. OK, then it's closed. Now if we just move around to some of the other folds, I can move in just by moving the cursor, and it opens so you can see the code. It's quite convenient. So there's a few commands that you can use with folds to move around, so you have a nice overview of the functions in your file. And you can move around, and then move the cursor, and it's open, so you can then see the code. Just one of the many ways to quickly move around. OK, second example. You know, if you're working with XWindows, you have these terrible function names that you have to use all the time. I mean, it's just impossible to type right in at once unless you are perfect, but nobody's perfect. And there is small print, there is capital print, and there's everything. You type it wrong all the time. But one solution that people I have seen using is to Copy, Paste the name. So you have a list of names, you Copy, Paste them. That's a little bit quicker, but still, it's a bit slow. There's a much quicker way. So how do you find this method? Well, what I often recommend is just ask around. Ask somebody, a colleague or a friend, how do you do this? And that's actually one of the best ways to find a better way. Of course, you have to do it. Don't be shy. Ask a question. This colleague of yours that, of course, is much better in Vim, then tells you to use the Control N command, or the Next Insert Mode Completion command. And what that does is you type some of the letters. So what happens here is you type like five letters, which is the start of one of the function names. Then you'll hit Control N, and Vim will complete the whole word for you. Well, if you're lucky. I mean, if you look closely you see here there's like 16 function names that start with the same five letters, so you might have to hit Control N a few times to get to the right one. But at least that's a lot less typing and a lot less mistakes than when you would try to type it directly. This doesn't only work for strange function names. It also works for the name of people you're replying to in an email. I mean, if you reply to somebody and you type his name wrong, that's also not very good. That's not very nice. So I use Completion a lot, especially for people from strange countries that have these names that are really hard to type sometimes. I mean, no offense, but not everybody has English name or Dutch names, so it looks very strange. In Vim 7, I discovered that often, you want an overview of all the matches that exist. So I made this fantastic, high-tech menu. And I mean, doesn't it look great? And you can actually get an overview of all the matches that have been found. And you can use the cursor keys to scroll through them. So that's also for dummies who don't know exactly how Vim does this. And also, what this shows is it's actually omni-completion, and omni is a term that we invented to avoid a very long name. What this does is actually, it looks at the context. So it doesn't just look at the words before the cursor. It looks for a bit further back, and in this case, it finds this pointer. It looks up the type of the pointer, finds out that it's a structure and the structure has members, and then the members are obtained, and these are the alternatives that you get. So you don't even have to type anything here. The cursor could have pointed the silver arrow there, and you just type Control N, and you get all the possible names that can be valid there, hopefully. But omni-completion is a complicated thing. It currently has been implemented for a few languages like C, Python, I don't think Java really works. But it's still under development, and we could use some help. So if you know a language very well, maybe you can help developing it. It's all written in Vim script. You don't have to program C or anything, but I have to admit, it's not really easy. But with a little bit of effort, we can get it done. And sorry about the ugly menu. OK, next habit. I'm not a native English speaker. I do know English quite well, I think. but I still make lots of mistakes, especially when typing. Vim now has a spell checker, which is very nice. Actually, I think the next slide shows that. The spell checker, you can switch it on, and it will highlight. In this case I was using the GUI version, G Vim. So it will just underline the mistakes with a nice, wobbly line, and then you can go there and either use the mouse or use keyboard commands to see the alternatives for fixing that. So in this case, it's just that the first letter was wrong. This works. It works quite well, especially if you have only a few mistakes in your text. And if you don't know the language very well so you don't know the correction, this works really well. It's supported for about 30 languages, so that's quite good. But still, if you have common typing mistakes, you have to fix every one of them in this way, that's still taking a lot of time. So you think, there must be a better way, and there is. This example I'm using a way to find the solution using the maillist archives. You know, the Vim maillist archive is really a treasure of all kinds of tips and suggestions, and answers to questions. So if you use the right keywords, just search in the archives, and mostly you will find a solution. Actually, this one is somewhere in the archives, if you can find it. But of course, now it's on the screen, so that's a lot easier. What does this do? You basically take the words that you misspell-- so you wanted to type the, but you typed teh-- and you make an abbreviation for it, and insert that abbreviation. So that's really simple. That's one of the basic things in Vim. You just have to think about actually doing it. And then you can also, as an extra, highlight the typing mistakes. So when the correction doesn't happen for some reason, because abbreviations don't always kick in, you can also highlight them so you can have an overview. So then you get this. So you have some text, and this is something I typed and typed wrong. Actually, I had a hard time typing this, because the corrections kept kicking him and correcting me, so I had to switch that off. So these are just a few examples of common typos. So you type lonux instead of Linux, and you type an extra c in. Of course, these are words that are really wrong. You would never have them in your text, so then you can make an abbreviation. Some words are just-- you still type them wrong, but they're also valid words, so then you'll have to decide yourself if you want to correct them or not. The nice thing about this is it's really fast. I mean, you can just continue typing all your mistakes, and it corrects them for you automatically. The only thing is you have to make a list. I have made a list for myself because I always make the same mistakes over and over again, and you probably make different mistakes depending on your keyboard and what you're used to. So you have to make your own list. And if you want to make this a habit, one thing you need to do is if you've noticed you make certain typing mistakes, you have to add that word to the list and find a correction. And of course for more advanced users, you could make a mapping to actually do that, so you don't have to manually edit that list but you can do it automatically. OK, well when I started working for Google, I found this whole pack of codes that's fantastic, but quite difficult to understand. So you have to somehow find a way to maneuver between all the files, find out how it works, and that's quite difficult if it's a lot of codes. Of course, this inefficiency is very easy to detect. You just can't find your way. The solution is a bit more difficult. In this case, I give the example of you looking in Vim quick reference. Of course, there's also the user manual, which is very useful. You just search around in some of the pages on Vim help. And the quick reference is very good because it's compact. You just have some keywords, so if you look for the right keywords, you can find a hint about what you're looking for. So for moving around in files, I have two examples here. One of them is using the Ctags program. I'm wondering how many of you know Ctags? OK, quite a few, but not everybody. Of course, Ctags generate a Tags file. What I mostly do is if I find new code, I generate a Tags file, and I do it like this, with the Dash R, which means recursive, and with the dots, which means the current directory. So basically, you have to move to the right directory and say, generate a Tags file for everything below this, the whole directory tree. Don't do that for a big tree, because it will take too long, but normally, for libraries and stuff like that, it works just fine. Then you can use the Tag command to jump to a tag, and you use T Next if you [UNINTELLIGIBLE] multiple matches, which especially happens in C Plus Plus code. There must be lots of matches for the same word. You can move around, or use T Select, which is another tags one. There's lots of Tags commands. You can just look it up in the Help file. The important thing is that Tags only finds where things are defined. So where a variable is defined, or where a function is defined, or a few other things, but it doesn't find where they are used. So if you have like a function, and you want to know, where is this function invoked from, you have to do something else. There is C Scope. That's not a very well-known tool. Within Google, we have other things that know where matches are to be found. But a very common way is to use Grip. And if you look closely, you can see there's no exclamation mark here. So this is not the external Grip, this is the internal Grip. It was added in Vim 7. The trick here is that Vim knows about compressed files. It accepts this wild card, which means searching a whole directory tree. So there's a few tricks that it can do better than the normal Grip command, but it's slower. So if you have a lot of files, you might still want to use the original Grip, and like [UNINTELLIGIBLE], it will just invoke it, get the lists, and then use that. So that's up to you. Anyway, you got a long list of matches, and then you have to move through the matches. If there's few matches, you can just use C Next, and C List, and other C commands to manipulate the list. And there's one nice thing, though, that if you have a lot of matches, or you want to get an overview, you have the Quick Fix window. So you use the Colon C Open Command, you get the Quick Fix window. And there you can actually search around. It's just a normal text window, except that when you hit Enter, you jump to the position that's mentioned there. Well, of course there's many other ways to move around, and since it's quite important, I thought I'd make another slide about it. Well, Goto File, GF. You can just type that on any file name and it will jump to that file if it can find it, of course. The nice thing, it even works on hypertext links. We have the net R [UNINTELLIGIBLE] RW plug-in that does that for you. And most people don't know that, but it actually works. Of course, you'd see the HTML SHTML. You don't see it rendered, but still it's very nice. An important thing is that the Path option should be set correctly, because that's how Vim knows where to find your files. And they could be anywhere, so you have to make sure it's set OK. There's a few more commands. Actually the square brackets I-- that's a capital I-- searches in Include files. So that's very useful if you have a lot of library functions that you're using and you don't know exactly how they're defined, or you can't find the documentation. You can search in the Header files, the Include files, and again, if the path is set correctly. I quite often just use the square brackets tab, and just jump to the first match, basically, and hopefully that's the right one. And that's very quick, unless you have a lot of Include files, then it's slow. I think I forgot making that into a habit. Anyway, you can do that yourself. Let's work together. There's a lot of programs, especially about layout, email, lots of stuff, that basically you work with text but add something to it, like layout, or some format like in a spreadsheet. The problem is that those editors are OK, but it's sometimes so difficult do type a lot of text, and the WQ appearing in your text is not very nice. So that's one of the inefficient things, and sometimes when I have to write a document with mark-up and it has to look nice, than what I mostly do is something that you have to find out about. Of course, the trick is, how do you find out how to do this? Well in this case, I give the example, ask on the Vim maillist. There's lots of people on the Vim maillist that are excellent in giving very nice answers to your questions, and very patiently and understanding that you don't know everything. And it's actually amazing that there's a few people that seem to be doing nothing the whole day but answering questions on the Vim maillist. And I'm so glad, because otherwise I would have to do that, and I just simply don't have the time. So let me thank all the people on the Vim maillist that answer the questions there. That's just great. So you ask a question, and then somebody says, oh just type your text in Vim as you like it, move it with just a trick. You switch off automatic text wrapping-- if it was on anyway-- you switch on the wrap, so the lines wrap, and you switch on Line Break. This is, of course, the essential part of it. That means that the lines are wrapped at blank spaces or special characters, so the words are not broken halfway, so it's much more easy to read. It's just a simple trick, but actually if you do this, you can have paragraphs of one line that you can Copy, Paste between your Word or Open Office or whatever, and Vim. So you can edit them in Vim, and copy them back, and that works quite well. Of course, it's still work to do the copying back and forth, but it's at least a lot better than trying to type your text in Word. Of course, there's one catch. You can't Copy, Paste the formatting. So if you have Bold stuff, and underlining, that will be gone. It's not perfect. Yeah, there's other ways to do this like removing the-- it doesn't say that. There's another way is that when you Copy and Paste text, you can actually insert line breaks and remove them again, but I'll leave that to you to find out how to do that. Yeah, that's a problem that still exists. Actually have to scan documents that I write if I don't leave something in there. OK, just one more example that I was thinking of. This is actually something I do when I release a new version of Vim or make a few patches, is I have to check if there's nothing wrong on some kind of system, and the compiler does one for every arrow. So what I do is I run the Vim source code through Lint, it still exists. And I do that actually with like 20 different combinations of features. What I get is an awfully long list with all kinds of warnings. And most of these warnings are for Header files, so I can't fix them. i mean, well, I could perhaps edit the Header file to fix the problem there, but that's a lot of work. And then if you go from GTK 2.1.3 to the next version, then it's all gone again. They're mostly GTK warnings, I'm afraid. So you have this long list of warnings, and it's very difficult to find arrows that you were actually looking for. So how do you do that? Well, quite simple, actually. This time, you just think, OK, I can do it myself. So you don't ask anyone. You don't look on the maillist. You just do it. And you write this simple function, which is nothing but a global command that searches for the things you don't want to see and deletes them. Of course, the trick is to make the pattern match the lines you want to delete and not match any lines you want to keep. So you have to think about that yourself. In this case, I do things like look for GTK, and [UNINTELLIGIBLE] something, and then I don't have that in my code, so it must be in a Header file. And the Perl stuff gives errors that match this, so they're all gone, and it cleans up. Then I'll make a mapping for this Underscore, C L. I have a lot of mappings that start with an underscore, because underscore actually is an original VI command. It's not properly documented, but it is a command, but don't ever use it. So you can actually use it for mappings without interfering with blocking one of the Vim commands. So that's a very good thing for more advanced mappings. So you call your function. Of course, this is to signal the answering the function call, and this part you put in your Vim RC file or somewhere else, just so that it gets sourced when you start up. And so you run Lint, you get the output, you clean up the output, and then you use the C File command to load the file as a list of errors so you can actually jump to the errors very quickly. And this is what I use. It's not much more-- well actually, of course the patterns, I have a lot more of them. I can probably show that. Let's see. Ah, there we are. So there's a few more of them if you really want to do it properly. And I keep updating this list. For example, if you upgrade GTK, then it will produce different errors. And it's quite a long list as you can see. But this is real. This is what I use. And again, you have to make this a habit, so just do it. Well, I do it quite regularly. The only thing is that Lint runs a bit slow, so I don't do it every day. Of course, what I said, you have to keep updating those patterns. That's very important, and especially watch out for things that you remove that should not be removed. OK, Habit Seven is actually a different kind of habit. It's not really an example by itself. It's a meta example, a meta habit, which is a habit to do these things. I mean, I talked about the three steps, and the seven habits, and you know explained how you do it, and now you have to do it. Somehow, when you're using the editor, you have to look back, what did I do in the last five minutes, or even longer? Is there something I can improve? It's very important that every day, you take a few minutes to think about that and not just keep typing, because it's so easy to just forget about, just keep going, and then you'll never learn. I like to compare that with driving a car. When you are first in a car, and your driving instructor tells you what to do, and move the wheel, you know how it works, but still actually doing it without hitting anything is quite difficult. So you learn one thing at the time. You learn to use the driving wheel. You learn to use the gears. Well, you use automatic here. Well, you learn all the parts that you need to know, even the wipers and indicators, and all the other knobs, and turn on the lights, and everything. It goes one step at a time. The same for an editor. You have to learn one thing at a time and keep learning. The difference between a car and an editor is, a car has only so many features. An editor has like 100 times as many features, so there's a lot more to learn. So once you have learned to drive a car, you can learn to drive your editor. I can skip that. OK, how does Vim help you with this? Of course, lots and lots of features. I think by now in Vim 7, we have most of the things that people use actually in there. I can't think of really big things to add that people would use daily. Of course, there's still a long list of feature requests, but most of the things are just for a few people that would use them, or they're very difficult to implement. I'm not going to go through the list, you probably know about that. Well, I want to say one thing about automatic indenting. I don't know if you're using it. If you don't using it, you're probably missing out a lot. It's just a matter of switching it on, and mostly it works, especially for Seagull and a few other languages that are structured enough, it's easy to figure out indenting. Python, of course, is an exception, because there, the indention defines what it means and not the other way around, so that's a bit tricky. But otherwise, it's a really good feature and saves you a lot of time. And why is my [UNINTELLIGIBLE]? Oh well. Doesn't work. Just doesn't work. OK, so a summary of the three steps. And somehow it sounds so simple, and it is simple. You just have to do it. So you have to detect what you're doing inefficiently. As I said, look back at the five minutes that you've been working and think of, what could you improve in those commands that you've done? Find a quicker way. Well, there's many ways to find out the commands that you need to do it quicker. Read online help, ask the maillist, ask friends, search on the internet. And you can even do it yourself. Write your own scripts. I know the Vim scripting language is very specific. It's not like any other language. But if you use examples, for example-- most importantly, if you go to the Vim website, there's lots and lots of useful scripts. And if you look in there, you will probably find some examples that you can use, and Copy, Paste, change a little bit, and that will do what you want. And of course, the third step, make it a habit. Make sure that you actually use it, and get it in the top of your finger so it's almost automatic. And I think one important thing to add here is that you have to do one thing at the time. I don't think you can just sit down one day and in that one day, do all of this for everything you do, and then the next day you're going to use them. No. It's more like you do a little bit of it every day. That works much better. A few counter examples, how not to be effective. One of the major problems is that your boss tells you that it has to be done today, or yesterday, you just don't have the time to look into the Help files or how somebody how to do something quicker, and it's an obvious mistake that a lot of people make. So just take your time to do it right, and in the end you will be more effective and more efficient, and then your boss will be happy, too. The counter example-- I know a lot of people that just start reading reference manual and want to learn every single command. You can imagine, not only to they take an awful lot of time to learn everything, but they're also wasting time, because most of it, they're never going to use. And especially, it's not going to be a habit. So every time they want to do something, they have to think, how did I do it? And carefully type their commands, and they end up being very slow, actually. So don't try to learn everything. Just learn the things that you need. OK, a few more tips. Read the user manual. Since Vim 7, I've added quite a bit of text that was based on the book by Steve Oualline. He wrote a very nice book for beginners, basically, how to learn Vim. And especially the first 20 chapters or so are quite good. So I took that text, and fortunately, they allowed me to do that, to copy the text. And then I fixed some mistakes. I had to take out the pictures, unfortunately. And I added all the new things from Vim 6 and Vim 7, so it's quite big. And it's really set up so you can read it from start to end. And you'll have some idea, at least, about all the commands, and from there, you can actually jump to more detailed help, so that's very good. As I said, the Vim user maillist works really well. Don't be afraid to ask a question there. Just try to formulate your question properly. If you ask something like, this doesn't work. How do I do that? Then nobody can actually answer your question. They'll just come back with more questions, because they don't understand you. But if you formulate it properly, then I'm quite sure that within a few hours, you'll get like a dozen answers, hopefully. And as I said, thanks to a lot of people that actually answer those questions. That's really great. OK, that's the end of the slides, so let's have a few questions. Let's start with questions about what I was talking about, about the habits. Anybody, question about the habits at all? Nobody? Was it so clear? OK, there's a hand. AUDIENCE: I have a question about the [INAUDIBLE] BRAM MOOLENAAR: Yes? AUDIENCE: [INAUDIBLE] two ways of doing it? [INAUDIBLE] BRAM MOOLENAAR: I can scroll back to that, hopefully. This one. OK? AUDIENCE: [INAUDIBLE] like a pointer tool [INAUDIBLE] basically remember who all the members are. [INAUDIBLE] break this up [INAUDIBLE] BRAM MOOLENAAR: Yeah. AUDIENCE: Oh, can it also, if you have a, say within that structure, you have, say, a pointer to another structure. Can you follow it? BRAM MOOLENAAR: Yes, actually if you look closely at what's shown here. So for the people watching the video, this is a question about omni-completion and how it works. So what happens is Vim takes the first word, so it basically looks back for the start of something, and mostly that ends by white space, or a parent, or something like that. So in this case, it will find this variable, this name, it doesn't really know what it is. So the first thing what it does is actually looks back in the code if it can find out something about its type. You can't see it here, but this is actually a variable local to the function. So it looks at the declaration to the variable, finds out it's a pointer to a structure, and then that matches with the arrow that's there. So if you complete that, than it knows it's a pointer to a structure. It fetches the information about the structure-- which are these fields-- and then completes that for you. So suppose you take one of the fields of the structure, you can actually already see here that this field has another arrow after it. So that means Vim knows that this is another pointer. And actually, you can see it's a pointer to this type. So if you would accept this one, and then type Control N again to do more completion, it will actually find the contents of this pref type and then continue. And it actually goes down as far as you like. And it also knows about Erase, so that's why the square bracket is there. But of course, if you have an int, or a character, then it stops there, because you can't do any further completion on that. Does that answer your question? AUDIENCE: Yes it does. BRAM MOOLENAAR: OK. AUDIENCE: [INAUDIBLE] BRAM MOOLENAAR: That's exactly what this is for. So you don't really have to know what this type is or what it points to, the omni-completion will find out for you. And it's quite nice that it's mostly correct. I cannot guarantee it's always correct, because it's based on some guessing. It especially gets confused by prepossessors, like if you have a Hash If structure there, then of course it gets lost because it doesn't understand that. AUDIENCE: [INAUDIBLE] BRAM MOOLENAAR: Yes. AUDIENCE: Help Omni? BRAM MOOLENAAR: Yeah, I think if you just do Help Omni-- actually, you can try that. There you are. Well, from there, of course you have to look further down. Let's see. Control brackets. OK, there's actually a lot of help about this. So we can close it again. OK. AUDIENCE: [INAUDIBLE] you need tags for that to work, [INAUDIBLE]? BRAM MOOLENAAR: Sorry, can you repeat the question? AUDIENCE: So if you're completing structures [INAUDIBLE] Header file, will Vim actually look at the Header file, [INAUDIBLE] tags set up? BRAM MOOLENAAR: For C code, what omni-completion does, it uses Tag files mostly. You could use the header files. The problem is, there's so many of them, so that would be very slow. And also you need to parse them, and parsing the Header files is quite complicated, especially for C, because you have the three-processor stuff, and the syntax is not that easy. And C Plus Plus is terrible. I mean, who can parse C Plus Plus without knowing the context? So the C Tags program actually does that beforehand, creates a big list, the Tags file, with some extra information about what is a class, what is a member, what is it a member of? And the result of that is stored in a Tags file in a sorted order, so you can do a binary search on that. Except that if you are searching for all the members of a certain structure, it has to scan through the whole file, because there's currently no way to cache them. So that can be a bit slow, especially if you have a big Tags file. And like the example of the Linux kernel, with lots of lots of structures, you could put them all in the Tags file. That will work. But then scanning that Tags file will be slow, so I'm not sure how well that will work out. I haven't tried. AUDIENCE: [INAUDIBLE] BRAM MOOLENAAR: Yeah. The Tags program is actually quite fast. It has been optimized to do that. But it may generate really big Tags files. AUDIENCE: Yes it does. BRAM MOOLENAAR: It does, OK. AUDIENCE: [INAUDIBLE] BRAM MOOLENAAR: Yeah, and of course of the binary search, if you're just looking for a specific identifier, it's still quite fast. But if you have to scan it from start to end to find all the members of a certain structure, and then, since they're sorted on the name of the member, and not on the name of the structure, that can be a bit difficult. There's, of course, way to improve this. And also, if you use C Scope, then I think it would be a lot quicker, because C Scope also stores the back references. OK, so we're back online, and we're ready for another question. OK? AUDIENCE: Is your vimrc online? BRAM MOOLENAAR: No. It's a big secret. My vimrc is a big mess, I have to confess. What I mostly do is people send me bug reports, and then I have to try out to reproduce it, and I end up with all kinds of mess in my vimrc because somebody reports a bug. I try it out, think, OK, this is the way to reproduce it. So I make a remark in my to do list to look into it. So I leave the stuff in my dot vimrc file, because I need it later. But then, of course, I forget to delete it. And I have stuff in there for all the versions of Vim, that sometimes I have to look into. Well, actually I never do in practice, but it's a big mess. So I'm not going to publish it. I think Sven Guckes has actually published his vimrc, so if you want a good example maybe you can use that one. I'm not sure if there's other ones. You should be able to look for that with some search engine that you might have heard of, and I'm not sure if it understands the dots, but vimrc it should understand. No, but I'm not giving you my vimrc, sorry. AUDIENCE: Vim makes me happy, and the fact that it's charity work makes me even happier every time I use it. BRAM MOOLENAAR: Very good. AUDIENCE: But I have a somewhat political question. I noticed that you use a Mac, and [UNINTELLIGIBLE] uses a Mac, but Vim is open source. And like for nutcases like me, I wondered if you could talk about open source, but sometimes using closed source stuff, and just your thoughts. BRAM MOOLENAAR: So your question is, what do I think about closed source versus open source? Is that correct? AUDIENCE: Yeah. BRAM MOOLENAAR: Well of course, I very much enjoy using open source. I very much enjoy writing open source. It's just a lot of fun. I think Linus used as his main remark on what he thinks about Linux, it's a lot of fun. And I think most people agree that open source is a lot of fun for everybody. The problem is, people have to make money. If you make something open source, then making money from it is difficult. It's not impossible, it's just difficult. I actually had another presentation on that a couple of years ago, how to make money with open source software. And if you see the overview, you realize that there's just small parts of open source that you can make money with. So the result is, yes, we have closed source because people want to make money with software. And I think the Mac is another example of where Apple thought, well, we'd like to give it away, but we also have to make money somehow. So they have to close some parts, but they actually have given away a lot of their stuff. But there's a gray area somewhere about what you can give away and what you can't give away. Google has the same problem. I mean, most people in Google think, let's just give it away. I mean, we make such great software. Let's just give it to everybody. But our shareholders don't agree. And we have a whole open source team within Google who are actively looking into all the parts of software that we have, and find out, can we publish this, can we give this away, or do we need to keep it a secret, because that's the choice that we have to make. That's tough. For me, I think it's OK to use closed source software, but I keep promoting open source. I think that's the best way to approach this. OK? Another question? AUDIENCE: How is the integration with various [INAUDIBLE] BRAM MOOLENAAR: Yes. Plug-ins for GUI editors kind of things? AUDIENCE: Yes. [INAUDIBLE] use Vim instead of [INAUDIBLE] BRAM MOOLENAAR: Yeah. As I said in one of the examples is Copy, Paste works, but it's not very nice. Eclipse is, I think, the application where it's asked most often. Eclipse has its own editor, and it's quite good, but it's not Vim. So people that are used to all the Vim commands have their bit set of all the functions and scripts that are written, they can't use them inside Eclipse, so that's a problem. The main problem with Eclipse is that it defines an editor interface, so you can actually plug in another editor. But that interface is so complicated, it's actually just made for their own editor, that nobody so far has actually made a good editor to plug in to that. There are a few solutions. Somebody has made an Eclipse editor plug-in. I've never tried it. I don't know-- you're raising your hand. You know how good it this? AUDIENCE: It was actually about the plug-in issue. Hopefully people here know about Mozex, something that use Gmail, with Firefox [INAUDIBLE]. But has anyone made some kind of window layering program that will hijack an editor window in Windows or MacOS, and plug in [INAUDIBLE] something else, Mozex on Firefox. BRAM MOOLENAAR: Yes, you were talking about Mozex for the [UNINTELLIGIBLE]? I don't know how it works exactly. I do know that the KDE people have worked on this, so that you could use the G Vim with the QT stuff, and plug it in into basically any KDE application. But it had issues, mostly with the keyboard focus and stuff like that, and somehow they have given up on that and started their own editor, so nobody is working on using Vim as a plug-in. They're making a Vim-alike editor for KDE. So unfortunately, that was a dead end unless somebody picks it up. Yeah, it would be really nice if we have a universal solution to that problem, like ideally, you would have an editor interface that all applications use. But it doesn't exist, and I think it will be really, really difficult to convince everybody to use it. So yeah, hijacking a window, you can do that. But then, how are you going synchronize the text, how are you going to handle keyboard focus, and stuff like that? AUDIENCE: Actually, what Mozex does, it doesn't try to go into Firefox, it just [UNINTELLIGIBLE] beside. And when you save it, it just pushes everything [UNINTELLIGIBLE]. BRAM MOOLENAAR: OK, yeah, that's that out-of-window solution. AUDIENCE: [INAUDIBLE] BRAM MOOLENAAR: Actually, I've tried using it, but somehow I didn't set it up correctly to use Vim. Maybe that's the problem. But yeah, it's actually a variant of the Copy, Paste solution, where you copy the text that's there into Vim, you edit it, and a moment you save it, it's automatically put back into the original text. AUDIENCE: Can it work both ways? BRAM MOOLENAAR: It sounds very simple. I don't know why nobody has made it yet. Maybe an idea for someone? 20% project? AUDIENCE: [INAUDIBLE] BRAM MOOLENAAR: I'm sorry, I didn't hear the first word. AUDIENCE: [INAUDIBLE] BRAM MOOLENAAR: Yes. Microsoft's Visual Studio, the older version actually had a possibility that you could add a few buttons inside, and if you click on them, then the text would appear in Vim, and you could send it back to Visual Studio. As far as I know, it doesn't work with the later version of Visual Studio. And also, I don't know if somebody's working on it, but I've not heard of a solution. I think it must be possible, because I know some other companies, mostly commercial companies, actually do something like that. So I think it's possible. And again, you must have somebody who actually into the problem and solves it. At this moment, I'm mostly busy just with fixing the bugs in the existing features. I don't really have time to work on new features, unless they are really small, or quick to do. So I'm afraid that most of the feature requests are currently on hold until I find some more time, or somebody bright steps up and says, oh, I know how to do that. Actually, [UNINTELLIGIBLE] was here. I can't pronounce his name properly. [UNINTELLIGIBLE]? Did I say that right? OK, and he's actually helping me now with some of the features that are on the to-do list. So that's really good. I really appreciate it. So I wish we had more people like that. OK, one more question? AUDIENCE: In regards to text editor productivity, would you consider using the mouse a productivity [UNINTELLIGIBLE]? BRAM MOOLENAAR: That depends. The mouse can be very productive. For example if you take scrolling-- oh, we have a scroll bar there. Suppose I would like to move this scroll bar without using the mouse. Then I have to use Control E or Control D, something like that. How do you say that? The connection between typing that and what you're seeing in the scrolling is not very direct and it can be very slow. Well, if I just pick up the bubble of the scroll bar, that's so much more convenient. Of course, the problem is you have to pick up, so you can also use the Scroll button. You can't see that, but I have a Scroll button on this mouse. And quite often, that's very convenient for scrolling through. And I am showing my vimrc. I wasn't supposed to do that. So yes, sometimes the mouse is very convenient, so I think it's up to you. It's just that, if you're using the mouse a lot, you have to think, isn't there a keyboard shortcut that's faster to do this? In Vim, of course there is. In other applications, you often end up using the mouse. I mean, graphical applications are meant to be used with the mouse. That's very difficult to use keyboard shortcuts to move between fields in a forum, for example, than just to click and it's so much easier. AUDIENCE: I've never used gVim proper, but I'm assuming that all functionality has a correct command. There's no mouse holding. BRAM MOOLENAAR: Yeah, gVim is basically a graphical layer around the console Vim. It's more like a very special kind of terminal. There's a few more connections to make it work better, but if I look at myself, I always use Vim in xterm. The xterm supports the mouse, it supports coloring, it supports everything that I want to use. And it's so much more quick in doing things than starting gVim, and then you have to grab the mouse to point to the right window, and things like that. And also, if you want to use external commands, like Grip, or just use a Copy command or whatever, that works better in the terminal than it does in gVim. So for Vim, I would recommend using the console version in a good terminal. I mostly use xterm because if there's something in xterm I don't like, I just ask Thomas Dickey to change it, and that works. OK, another question? AUDIENCE: Is it possible to do completion based on Google look-ups? [INAUDIBLE] BRAM MOOLENAAR: No, you'll have to make that. AUDIENCE: I tried making it [INAUDIBLE] BRAM MOOLENAAR: OK, the question actually was, can we do completion based on Google look-ups? AUDIENCE: Or anything, like wiki, [INAUDIBLE] BRAM MOOLENAAR: Yes, some clever way of doing completion. Well, if you look into the completion methods, there's actually a function you can define to do your own kind of completion, and so you can use that basically to fetch the matches you want to find anywhere. The only tricky thing is speed. Of course, if you want to use Google to look up some matches, I don't know how fast it will be depending on your connection, how fast Google is, stuff like that. AUDIENCE: But it's possible? BRAM MOOLENAAR: But there are certainly possibilities there, yeah. I saw a question over there? AUDIENCE: For the older [INAUDIBLE] in the audience, about 10 or 15 years ago, [INAUDIBLE] a half dozen [INAUDIBLE]. What do you think you did right? BRAM MOOLENAAR: What did I do right to make Vim the winner among all competitors? I think the main thing was that I just kept working on it. All the others have disappeared. I know Elvis was very good, and I liked it a lot. There are some ideas that I didn't like, but overall it was good. But what's his name, the person making it, he actually decided at one point that he had to do a complete redesign of the source code. So then for two years, nothing happened except that he was working somewhere on the new version, and then when the new version appeared, it didn't do much more than the previous version. The source code was probably great, but nobody looks at that when you're using it. So that kind of was the end of Elvis. Steve has not been worked on for a long time, I haven't seen it. One of the other good competitors is nvi, new vi, which is actually the reincarnation of the original vi. Keith Bostic worked on that. He did a really fantastic job. I mean, I don't know how he did it, but in just under a year, he created a whole new editing editor that not only was completely vi-compatible, because he really figured out every little bug that vi did that you could call a feature, and he reproduced it in nvi. And he also added a lot of new things like multi-windows, multi-buffers, multi-level, and all kinds of fancy things. So that was great. And actually, at that moment when he introduced it, I was thinking, well, I might as well stop working on Vim, because that one's better. But I didn't. I actually added windows, and buffers, and stuff to Vim, so I thought, well, I can still compete with that one. But the same thing happened. Keith just stopped working on it. If he would have continued, I think nvi would have been much, much better, but he didn't work on it. So now you're stuck with Vim. OK, one more question. AUDIENCE: [INAUDIBLE] GPL license, do you think Vim [INAUDIBLE] GPL? [INAUDIBLE] BRAM MOOLENAAR: About the license, actually the Vim licenses is GPL compatible, but it's not GPL. You want to know why, or--? AUDIENCE: I'm asking is it true that GPL software survives longer than non-GPL software? BRAM MOOLENAAR: Does GPL software survive longer than non-GPL software? I don't think so, because the license doesn't really change your software, but there's tricks there. Using a GPL license sometimes means it's GNU software, so part of the GNU project, and that means there's like a big group of people that will take over the maintenance when the original author disappears or just gives up. And I don't know exactly how they do it, but they have some kind of system to keep things going. But that's different from the licence. GPL is a license, and GNU is a project. So it's not the same thing, although I think every project in GNU has to use the GPL. I think so. I'm not sure, actually. The license for Vim, I wrote a long time ago and I thought, well, let's just make some kind of license. And no one was actually actively discussing about licenses at that time, so I just made one that I thought was nice. Just give it away, but you can actually change it, but you have to give the changes to me. So I can decide if I want to include them or not. Very basic, but over time, you have to add certain exceptions, because people think, hey, but if I do this, then your license doesn't cover it. OK, I'll change it. At one point of time, some people found out that people compiled Vim with the GPL library. I think it was the mouse library that's used on the Linux console, that's actually a GPL library, not L-GPL, but GPL. And then, if you compile Vim like that, you can't give it to somebody else, because the Vim license was incompatible with GPL. If you compile it with a GPL library, you can't pass it on to anybody. So then people asked me to make the license GPL compatible, and I did that. And actually, Rich [? Stormond ?] himself looked into the license and gave me a few hints until he was satisfied with it, meant in a very nice way, so no complaints about it. So now the Vim license is GPL compatible as far as I know. I mean, we don't hire lawyers to do this, so we just have a fresh look at it and think, well, it should be OK. And I've never had a license problem, so I don't worry about it. But basically, you can use Vim, you can use the source code, and just be happy with it. Let's take one or two more questions. In the very back there. AUDIENCE: Do you have any plans to make it easier to integrate Vim and GDB? BRAM MOOLENAAR: And what? AUDIENCE: GDB, [INAUDIBLE] BRAM MOOLENAAR: Oh, GDB. Are there plans to integrate Vim and GDB? Actually, that's been done. It's called [? Arida, ?] and that was actually a project I worked on a few years ago. AUDIENCE: But that's really hard to [INAUDIBLE] BRAM MOOLENAAR: Yeah, the problem is it uses-- the remark is that it's difficult to install. The problem is it uses WX Python, and that's a nice graphical library. It really has a nice interface, but it can be difficult to install. it's like hit or miss. Sometimes it works, but then they make some changes in GTK, or some of the lower layers, and then it doesn't work. Then they fix it, and it works again. Actually, the last time I upgraded my OS, it worked properly, so I can run it. But yeah, it's tricky. And also, I made that as a start, as an example of how it could work. And to explain a little bit more about it, it's a Python application that is a connection between GDB and Vim. So it runs GDB, it runs Vim, and then connects the two. So if you, in GDB list the source code, it will show in Vim, and in Vim you can set a break point, and that break point goes back to GDB. And actually, what I did is I just added enough so I could use it, and I actually use it to debug Vim, but the problem is, I made it myself, so I know how it works. And for other people, they probably use different commands and say, oh, it doesn't do what I like. And they give up and throw it away. So it exists. It could do with a little bit of work, so if somebody's interested, it's all on the web. It's all in download. It's actually-- oh, we don't need it. I actually have a screen saver that picks a random one, so I was wondering if it would pick some of my pictures. So anyway. AUDIENCE: What was the name again of the Vim and GDP integration? BRAM MOOLENAAR: The name is Arrida. Maybe I can look it up. Let's see. No, that's wrong, sorry. I have to take a new window, that works better. OK, that's how it's spelled, and it doesn't work because I'm not connected. AUDIENCE: [INAUDIBLE] BRAM MOOLENAAR: I'm not sure if this works. Let's try. I don't think so. Well, anyway, you can see how it's spelled. Oh, it works. AUDIENCE: What's the best way to connect to the [INAUDIBLE] project? Because I'm trying to code [INAUDIBLE], quite a few options, and which is the most effective [INAUDIBLE] BRAM MOOLENAAR: I don't quite get the question. You have lots of options, of course, yeah? AUDIENCE: To donate money to the Vim project? BRAM MOOLENAAR: Oh, to donate. That's a good question. Thanks for asking. Well actually, when I was working on Vim 7, you may have notice that at that time, I quit my job, basically, and I started working on Vim full time. So at that time, I asked people to please give me some money to survive, and that worked quite well, and I survived. But then Vim 7 was ready, and I thought, well, let's get a real job again. So I decided to work for Google. And at that moment, I thought, well, I don't need that money anymore, but people kept sending it. So that money is actually now all going to the same Uganda project that I've always been talking about as a charityware for Vim. So that kind of doubled the donations that are going to Uganda, so that's very good. And people just keep donating to Vim. I think most people do that as a sort of thank you for this nice editor that they're using the whole day. And they think, well, I would like to give something back. And OK, give me some money, and I'll give it to the needy children in Uganda, and they can really need that money. I should show you at least what I'm talking about. Oh, that's not what I wanted, but actually, this is the right website but the wrong page. This is actually, if you're interested in the books I was talking about, the highly effective people book by Stephen Covey, and the highly defective people book by-- what's his name, the writer of Dilbert. And if you want to buy them, I can recommend that they're really nice books and they're not that expensive. If you use this web page, and click on the links and order them from Amazon, and there's actually several Amazon places where you can get them. So if you're not in the US but somewhere else, in Canada, or UK, or Germany, you can use one of the links, then actually a percentage of the sales also goes to the children in Uganda. So doesn't cost you anything extra. What can I say about the project? Well, this is not really a talk about the project itself, so I'll just-- that's the wrong one-- I'll just mention it. There's a website here with information, and a nice picture. There's more pictures. Yeah basically, I've always been trying to promote this project in Uganda that's very good to help the children there. Most of them are orphans. They really need our help, and the project concentrates around education. These people are poor, you would think, well, just feed them, and that's it. No, we want to educate them, so that eventually, hopefully after several years, they can take care of themselves. That's the goal of the project. But we are not there yet. It's going to take a long time. We have a big school. We have about 700 children in school. Every year, about 20 to 50 children finish school, and hopefully they will do something useful. And we already see some of the students coming back to the center as a teacher, or as a help in the clinic, and we can see it starting to run itself, and that's very promising. But we are not there yet. We need a lot of money to keep it running. So if you feel you need to give something to someone, think about this one. AUDIENCE: How did you get involved? BRAM MOOLENAAR: I think we're going too far off track here of Vim, because it's totally unrelated to Vim. So maybe we can talk about this afterwards. I'll hang around so we can talk about it. But I've been there for more than a year, so I know quite a few things about the project. So that's why I can recommend it, and not all the other ones. There's many of them, but this one is really good. OK, that's a very short summary. OK, maybe one or two more questions? OK, there's one. AUDIENCE: So you mentioned multiple windows or tabs. Do you have any tips on using those effectively? BRAM MOOLENAAR: Using tabs effectively. AUDIENCE: Or multiple windows, [INAUDIBLE] BRAM MOOLENAAR: Yeah of course, you can use lots of windows, as many as you like. Mostly it depends on your screen size, actually. If you have a big screen, you can use lots of windows. If you have a small screen, like this small laptop that I'm using, you can't really fit more than two windows on there without having the problem that you have to scroll a lot. I think that's the main problem if your windows get too small, you have to scroll to see where you are. And for me, what I'm mostly doing, I start multiple xterms, like four or even more. And it's very easy to switch between xterms. So inside Vim, I don't use many windows, mostly two, maximum. And then if I need to work on something else, I just go to another xterm, start Vim there, and continue. And of course, you can Copy, Paste file names, and marks, and whatever, so that works good for me. Tab pages, they're very nice, and you can actually have multiple windows on one Tab page, so it's like you have multiple Vim sessions just next to each other. Organize them as you like. I don't really use them myself very much, but that's probably mainly because I'm an old time Vim user, and they weren't there, so I have the habit of doing it one way. And now we have Tab pages, and I don't really need them. So obviously, you can sort of sort your work in different Tab pages, especially if you don't have an xterm, but you have to use, gVim, for example, on Windows. Then they are very useful, because you don't want to start many copies of gVim there, perhaps. Depends on what you're doing. And of course, it's a quick way to switch between different pages with Windows, and so if you organize them in different work groups, or different things you're working on. You have to be careful not to get too many of them. If you have like 20 different Tab pages, you're probably doing something wrong. That's not the right way to do that. There's other ways to organize lots of files. OK, does that answer the question hopefully? OK. I think I'll take one more question and then we can just socialize. OK, final question. who's up for it? OK. AUDIENCE: So I use the [INAUDIBLE] BRAM MOOLENAAR: Yeah, how to use the Vim info. AUDIENCE: [INAUDIBLE] multiple sessions, [INAUDIBLE] BRAM MOOLENAAR: Well, if you talk about sessions or Vim info, those are two different things. Vim info just stores the last information or the last Vim you exited, because that's when it stores it automatically. You can also store it manually. At one point in time, you can say, OK, store what I have now in my Vim Info file, or even create another Vim Info file, but that's not very comfortable. If you talk about sessions, like what we were talking about a session with multiple windows. So you're working on some project, and you have multiple source files that you're working on. You say, OK, now I have to go home. I want to start this again tomorrow. The best thing to do is then to make a session from it, with the Make Session, MK Session command. You can store it somewhere and recall it later. You can also use it to store a fuse on a file with all your Options settings and stuff. But I think the main thing is store session as a session under a name, and you can reload it. It doesn't store everything. There's actually an option that specifies what you can store in your session, and that you can switch on and off. The default is pretty good, I think, but again, it depends on what you're doing. The Vim Info is completely automatic. I use it an awful lot. For example, if you edit a file, you exit Vim, you open it again, and you type Colon E, and just use going back in the command line history, you find what's been stored in the Vim Info file. Same for search patterns, marks, and stuff like that. Quite often, you don't really think ahead, and think, I have to get back here. So you don't remember to put a mark there, you just exit Vim, and then a few hours later, think, oh, I have to go back there. Where was I? And then, the numbered marks are very useful. So you can use quote one, quote two, quote three, and you go back to all the positions where you exited Vim the last nine times. So that's not really a session, but in the Vim Info file. OK, I think that's it. Thank you very much for coming. I'm so happy that so many of you showed up. I really enjoyed talking to you. Thank you. [APPLAUSE]
A2 Google bram inaudible file editor find 7 Habits For Effective Text Editing 2.0 673 51 李掌櫃 posted on 2014/05/07 More Share Save Report Video vocabulary