Text
Vim - Menus
Our beloved Vim offers some possibilities to create and use menus to execute various kinds of commands. I know the following solutions ...
the menu command family
the confirm function
the insert user completion (completefunc)
I will not bother you with a detailed tutorial. For more information I always recommend the best place to learn about Vim - the integrated help.
:menu
Let's start with the most obvious one, the menu commands. The menu commands can be used to create menus that can be called via GUI (mouse and keyboard) and via ex-mode. A good use-case is to create menus entries for commands that are not needed often, for which a mapping would be a waste of valueable key combinations and which can probably not be remembered anyway as they are used less frequently.
I'll keep it short here and as there are already tutorials out there. And of course the Vim help is the best place to read about it. :h creating-menus
Vim offers several menu commands. Depending on the current Vim mode your menu changes accordingly. Means if you are in normal mode you will see your normal mode menus, in visual mode you can see only the menus that make sense in visual mode, and so on.
Let's say we want to have a command in the menu that removes duplicate lines and keeps only one. We want that in normal mode the command runs for the whole file and that in visual mode, by selecting a range of lines, the command shall run only for the selected lines. We could put the following lines in our vimrc.
nmenu Utils.DelMultDuplLines :%s/^\(.*\)\(\n\1\)\+$/\1/<cr> vmenu Utils.DelMultDuplLines :s/^\(.*\)\(\n\1\)\+$/\1/<cr>
The here used commands are quite simple. After the menu command you see only 2 parameters. First one is the menu path. I say path because by using the period you can nest your menus. Here it is only the command directly under the Utils menu entry. The second parameter is the command to be executed just like you would do from normal mode.
There are 2 special characters that can be used in the first parameter. & and <tab>. & can be used to add a shortcut key to the menu and <tab> to add a right aligned text in the menu. Try it out!
Remember that you can access the menu also via ex-mode.
:menu Utils.DelMultDuplLines
But please don't type all the text and use the tabulator key to do the autocompletion for you. ;-)
confirm()
The confirm function. Luckily I already wrote about this possibility. So instead of copy-pasting the text I just link to it.
vim-confirm-function
set completefunc
Let's get dirty now. I guess the insert completion pop-up menu is well known by everyone. But did you know that you can misuse it for more than just auto-completion? I did not. I will show you what I mean.
Usually the auto-completion is triggered by pressing Ctrl-n, Ctrl-p or Ctrl-x Ctrl-something in insert mode. One of these key mappings is Ctrl-x Ctrl-u which triggers an user specific function. Means we can write a function that does what we want and assign it to the completefunc option. Let's check what we need to consider when writing such a function.
The completefunc you have to write has 2 parameters. And the function gets called twice by Vim. When calling the function the first time, Vim passes the parameters 1 and empty. In this case it is your task to usually find the beginning of the word you want to complete and return the start column. One the second call Vim passes 0 and the word the shall be completed.
function! MyCompleteFunc(findstart, base) if a:findstart " write code to find beginning of the word else " write code to create a list of possible completions end endfunction set completefunc=MyCompleteFunc
For more information and an example check :h complete-functions.
Now let's re-create the LaTeX example using the completefunc. Here is a possible solution that supports nested menus, so for 1 level menus the code can be reduced a lot.
https://gist.github.com/marcotrosi/e2918579bce82613c504e7d1cae2e3c0
Okay let's go through it step by step.
In the beginning you see 2 variables. InitMenu and NextMenu. InitMenu defines the menu entry point and NextMenu remembers the name of the next menu. I just wanted to have nested menus and that's what is this for.
Next is the completefunc we have to write. I called mine LatexFont. As shown before it consists of an if-else-block, where the if-true-block gets the word before the cursor and the else-block will return a list that contains some information. In the simplest form this would only be a list of strings that would be the popup-menu-entries. See the CompleteMonths example from the Vim help. But I added some more information. Let's see what it is.
The basic idea is to have one initial menu and many sub-menus, they are all stored in a single dictionary name menus and are somehow connected and I want to decide which one to return. As I initialized my InitMenu variable with "Font" this must be my entry point. After the declaration of the local menus dictionary you can see an if clause that checks if s:NextMenu is empty. So if s:NextMenu is empty it will be initialized with my init value I defined in the very beginning. And at the end I return one of the menus so that Vim can display it as a popup menu.
Now let's have a closer look at the big dictionary. You can see 4 lists named Font, FontFamily, FontStyle and FontSize. Each list contains the popup-menu entries. I use the key user_data to decide whether I want to attach a sub-menu or if the given menu is the last in the chain. To attach a sub-menu I just provide the name of the menu and when the menu ends there I use the string "_END_". So the restriction is that you can't name a menu "_END_" as it is reserved now. By the way, I didn't try it, but I guess that user_data could be of any datatype and is probably not limited to strings.
Let's see what the other keys contain. There are the keys word, abbr and dup. word contains the string that replaces the word before the cursor, which is also stored in a:base. abbr contains the string that is used for display in the popup-menu. From the insert auto-completion we are used to the word displayed is also the word to be inserted. Luckily Vim can distinguish that. This gives me the possibility to display a menu (like FontFamily, FontStyle, FontSize) but at the same time keeping the original unchanged word before the cursor. This is basically the whole trick. Plus the additional user_data key that allows me to store any kind of information for re-use and decisions. With the dup key I tell Vim to display also duplicate entries. For more information on supported keys check :h complete-items.
Now let's get to the rest of the nested menu implementation. Imagine you have selected an entry of the initial menu. You confirm by pressing SPACE and now I want to open the sub-menu automatically. To achieve that I use a Vim event named CompleteDone which triggers my LatexFontContinue function, and the CompleteDone event is triggered when closing the popup menu either by selecting a menu entry or by aborting. Within that function I decide whether to trigger the user completion again or to quit. Beside the CompleteDone event Vim also has a variable named v:completed_item that contains a dictionary with the information about the selected menu item. The first thing I do is saving the user_data value in a function local variable.
let l:NextMenu = get(v:completed_item, 'user_data', '')
The last parameter is the default value for the get function and is an empty string just in case the user aborted the popup-menu in which case no user_data would be available.
One more info - this line ...
inoremap <expr><esc> pumvisible() ? "\<c-e>" : "\<esc>"
... allows the user to abort the menu by pressing the ESC key intead of Ctrl-e.
And last but not least the if clause that either sets the script variable s:NextMenu to empty string when the local l:NextMenu is empty or "_END_" and quits the function without doing anything else, or the else branch that stores the next menu string in s:NextMenu and re-triggers the user completion.
The rest of the file is self-explanatory.
I'm sure we can change the code a bit to execute also other command types, e.g. by storing a command as a string and executing it.
Let me know what you did with it.
2 notes
·
View notes
Text
Blender - Link Collection
I think it was in 2004 when I installed Linux the first time on my PC. I tested some pre-installed programs and discovered Blender (Version 2.30). I did my first Blender tutorial, the famous "gingerbread man", and since then I am following the Blender community. With the growing number of Blender users worldwide and the way the internet evolved also the number of internet sites covering the topic Blender increased. Over the years I collected some links and today I want to share them with you. Maybe you'll discover something new. Happy Blending.
Feel free to report if a link is broken or an important site is missing. Thanks.
Blender
Blender.org
Blender Cloud
Blender Store
Blender Manual
Blender Wiki
Blender Wiki (german)
Wikibooks Blender_3D
Wikibooks Blender_3D (german)
Wikibooks Blender_Doc (german)
BlenderDay
BlenderNation
BlenderCommunity
BlenderNetwork
BlenderWorld
BlenderClan
BlenderGuru
BlenderArtists
Blendswap
BlenderModels
CyclesMaterialVault
BlenderStackExchange
AdventuresInBlender
BlenderHD
BlenderNerd
BlenderStar
BlenderSupport
BlenderSkool
BlenderCourse
BlenderDiplom
BlenderGrid
BlenderMada
BlenderMama
BlenderUnleashed
CGCookie
CGCoookieMarkets
AgenZasBrothers
CreativeShrimp
Blenderpedia
BlenderArtGallery
BlenderStuff
BlenderArt
CGMasters
Chocofur
OpenShading
BlenderAddonList
BlenderNewbies
BlenderSushi
Blender Facile (italian)
KatsBits
ShortcutMapper
Video
Youtube
Blender Foundation
Blender Developers
Blender Today
CGBros
BornCG
CGMeetup
MadArtistPublishing
BlenderGuru
CGGeek
CGMasters
CGCookieBlender
GlebAlexandrov
BlenderCampus
BlenderBuzz
BlenderUnleashed - Brandon Hix
Kenan Proffitt
Vimeo
BlenderFoundation
CGCookie
Andrew Price
Pablo Vazquez
Oliver Villar Diz
Sebastian König
CGMasters
BlenderTuts Vimeo
Render Farms
BlenderGrid
Flamenco
GarageFarm
LionRender
RayVision
RebusFarm
Render4You
RenderStorm
RenderStreet
RentRender
SheepIt
RayPump
Textures
Textures
AmazingTextures
ArrowTextures
Episcura
MayangTextures
PlainTextures
TextureMate
FreeStockTextures.com
TextureKing
3DXO
Hongkiat
TutsPlus
FreeTextureSite
Models
Blendswap
BlenderModels
SketchFab
3DSky
Archive3D
TurboSquid
TF3DM
CGTrader
other CG sites
3DArtistOnline
3DM3
3DRender
3DRing (german)
3DTotal
Animago (german)
ArtStation
CGArena
CGChannel
CGGallery
CGIndia
CGSociety
CGTutorials
CGW
CreativeBloq
CreativeCrash
RenderSpirit
Renderosity
SigGraph
TDT3D
TheFoundry
other Renderers
3Delight
Appleseed
Aqsis
Arion (former Fryrender)
Hyperion
Indigo
Kerkythea
Lucille
LuxRender
Maratis
Maxwell Render
Mitsuba
Moskito Render
NOX Renderer
NVIDIA
POV-Ray
Renderman
SolidAngle
SplutterFish
SunFlox
VRay
Yafaray
0 notes
Text
Vim - search, list & count
Besides the search commands /, ? and *, g*, #, g# in normal mode where you can get the search pattern highlighted and can jump between findings with n and N, Vim can also present the findings as a list. Here are the built-in solutions I know about.
ilist
Run :ilist word, which is the short form for :ilist /\<word>/, and Vim will display all occurences of the word with line numbers. But if you want to search a more complex pattern than just a single simple word, you have to wrap the pattern with slashes :ilist /pattern/. Normal Vim regex rules have to be followed. Furthermore every line is listed only ones also for multiple matches per line. The interesting but also tricky part is that ilist ignores matches within comments unless you run it with !. This way :ilist! /pattern/ also comments will be taken into account. So ilist comes in handy if you don't want to be distracted with findings within comments. In order to jump to a search result line you can only use :linenumber. And to those who didn't know, the search result window doesn't need to be closed for that.
For more info type :h :ilist
internal grep
Run :vim /pattern/ filename(s) and Vim will create a quickfix list window (or a location list window if :lvim is used instead) containing your search results. Filename can be % for the current buffer or * or just some filenames or whatever Vim supports here. vimgrep lists each line only ones unless a g is used after the pattern /pattern/g. The cool thing is that you can jump to every finding, you can open and close the quickfix/location list anytime without loosing it and Vim also remembers old search results and you still have access to them. In my imagination the location (or quickfix) lists are of course below the current window and sorted from left (first) to right (last). As I don't use splits so often my Ctrl+[h|j|k|l] key mappings are set as follows
nnoremap <c-h> :lolder<cr> nnoremap <c-l> :lnewer<cr> nnoremap <c-j> :lnext<cr>zz nnoremap <c-k> :lprevious<cr>zz nnoremap <leader>s :call ToggleLocationList()<cr>
As you can see I have also a mapping for toggling my search results window. Here are some proposals for how to toggle the quickfix/location list window.
For more info type :h :vimgrep
external grep
The external grep is pretty much like the internal with all that quickfix/location list stuff, but all that is done with an external grepping tool as you can guess. The call is :grep [arguments] and the arguments depend on the grep tool you are using. By default it is the standard unix grep but you can change that. You could use any other tool by adjusting the settings grepprg and grepformat. Lets assume you have the_silver_searcher installed and you want to use that because it is so unbelievable blazing fast (probably black magic used to develop this tool), put the following in your .vimrc.
set grepprg=ag\ --vimgrep\ $* set grepformat=%f:%l:%c:%m
What a conincidence, ag (the_silver_searcher) comes with a vimgrep option which makes the integration quite easy. The backslashes before the whitespace indicate that Vim expects one string. The $* is probably all the arguments straightly passed to the external tool. And grepformat is for parsing the tool output. It tells Vim how the tool prints the findings. Here we pass --vimgrep as an option to ag and then it will use the format file:line:column:match and that's exactly how we set grepformat.
For more info type :h :grep
global
The global command :g can be used to run commands on all lines matching or not matching :v a certain pattern. But if you give no command to excute :g /pattern/, then global behaves as if you would give the p or # command, which simply prints the matching lines. Now this is what we already had with the :ilist! /pattern/ command, so why would I use this? Probably just because you can check, before executing any command, which lines would be affected and then recall the global command from the history and append the desired action.
For more info type :h :global
substitute
The substitute command actually does not list the lines containing a pattern but you can count how often a pattern appears in the text :%s/pattern//gn or on how many lines it appears :%s/pattern//n. Like the global command you can run the same also only for a certain range :'<,'>s/pattern//gn
For more info type :h :substitute
1 note
·
View note
Text
OSX - cocoaDialog
Sometimes it would be just nice to have a graphical user interface (GUI) for your own tiny scripts, but writing a full program using a graphic library is absolutely exaggerated. cocoaDialog could be the solution for some of these use cases.
What is cocoaDialog? cocoaDialog is a command line interface that allows the use of common GUI dialogs such as file selectors, text input, progress bars, confirmations and more.
I really like this program. It is easy, fun and can be integrated quickly in a script.The cool thing is that it can be used also by people without GUI programming skills. I want to show you such an example of how cocoaDialog could be used.
This is what you get.
1. Preparation
Go to https://mstratman.github.io/cocoadialog/ and get the latest version of cocoaDialog. If you want to download the stable or the beta version, that's up to you. Check the documentation for more info.
I downloaded the version 3.0-beta7. This is a dmg file which you open and then you drag 'n' drop the cocoaDialog app either to your applications directory (/Applications) or inside your app (see next chapter). This depends on if you want to have the cocoaDialog app only ones on your system and reuse it OR if you want to have it inside the app you are creating so that it becomes a single all in one package.
For my example I will use an existing command line tool named youtube-dl. For more info check https://rg3.github.io/youtube-dl/ or http://youtube-dl.org or https://github.com/rg3/youtube-dl/ With youtube-dl you can download videos from many video sites and it also allows extracting the audio track from the downloaded video.
2. The app folder
Create a directory with a name representing your app you want to create. In my case I named it YoutubeDL and I placed in /Users/USERNAME/Applications since OSX has a directory for user specific apps. Inside that folder create another folder named Contents. Inside Contents create 2 more folders named MacOS and Resources. Download this Info.plist file here and put it into the Contents folder.
Now it should look like this ...
Open the Info.plist file for editing and fill out the fields ...
CFBundleExecutable (this shall be the name of the script)
CFBundleIconFile (the name of the icon file we will create later)
CFBundleIdentifier (a unique identifier for your app)
CFBundleName (simply the app name)
CFBundleShortVersionString
CFBundleVersion
The CFBundleIdentifier normally consists of 3 parts separated by period. What I have seen so far is that the middle part (blurred) is the company name. I don't know if there is a syntax we have to follow or if it can be any string.
Later we will rename this app directory by appending ".app". This way OSX will recognize the folder as an application, automatically display the icon and it can be executed like any other application.
3. The icon
For the icon we need a icns file. Design your own icon (1024x1024) and save it (I think with alpha channel) as png. To convert from png to icns download the following script and call it with your png file as first parameter.
https://gist.github.com/marcotrosi/0a1a87e671d89e545dcd
I don't know why but once I had a file which I could not convert. I could not figure out what the problem was. Maybe it had to do with the alpha channel.
You can also download one of these files for testing.
YoutubeDL.png
YoutubeDL.icns
Put the icns file into the Resources folder and make sure it has the same name as given in the Info.plist file.
4. Pre-Testing
To understand everything a little bit better we will do some intermediate steps. I want to know how cocoaDialog works, I want to check if the created basic app is working as expected and I want to see what the environment looks like when running an app.
4.1. Testing cocoaDialog
To test cocoaDialog we need to run the command line tool which is inside the cocoaDialog app. Open the Terminal app and run the following command to create a bubble
/Applications/cocoaDialog.app/Contents/MacOS/cocoaDialog bubble --title "foo" --text "bar"
and this to test the OK message box
/Applications/cocoaDialog.app/Contents/MacOS/cocoaDialog ok-msgbox --text "foo" --informative-text "bar"
Let's break this down. As usual at first the tool name. Here cocoaDialog, but we are calling it with the absolute path. Second thing (but first tool argument) is the type of box you want to create (bubble or ok-msgbox). And then some box specific parameters follow.
For information read the cocoaDialog documentation
4.2. Testing the app
Create in the MacOS folder a new file with the exact name as given in the Info.plist file in the CFBundleExecutable tag. I named mine YoutubeDL. Put the following lines into the file.
#!/bin/bash set > /Users/${USER}/Desktop/youtubedl.log
First line is the shebang line, and with the second line we write all environment variables into a log file placed on the desktop.
And now we finally rename our app folder by appending .app. So the YoutubeDL folder becomes YoutubeDL.app. But you won't see it really. OSX hides the extension and replaces the folder icon with the icon we created. If this happens then you did everything correctly. You will also notice that if you try to rename it again the .app in the filename will not be visible and can not be changed with the usual Finder renaming shortcut (enter key). Press Cmd+i instead to open the info box and rename the folder in the "Name & Suffix" field. Of course command line works too - it's just a folder.
If we double-click the app icon we won't see a lot, but on your desktop the file youtubedl.log should appear. This means the app executed the YoutubeDL script. The app basically works.
In the beginning of this chapter I told you that I am interested in the environment when running the app. That's why I choose the set command in the bash script. Open the log file. Have a look at the PWD variable. Mine is set to /. I hope yours is too. This means the working directory is the root directory when an app gets executed this way. The variable would be different when started from command line. Furthermore the PATH variable shows me that my bashrc/profile file has not been loaded. This all may sound now logic to you, but actually it took me a while to figure out these simple facts. I tested everything on command line and was pretty confused when suddenly things didn't work when executed normally.
5. Creating the script
Theoretically you can start cocoaDialog in any language via system calls, but in bash this is pretty easy and we already did it. So let's stick with that.
If you wanna access a tool/program or a file you can do that with absolute or with relative paths. For tools there is even a third option under Bash, by just typing the tool name and the Bash finds the tool for you by searching in each path given in the PATH variable. Depending on where we place the tools and what we are intending to do with the app we have to decide wether to call a tool with absolute path, relative path or through the PATH variable. That's totally up to you.
For this Bash script let's assume (as prepared above) …
cocoaDialog is in /Applications
YoutubeDL is in /Users/USERNAME/Applications
youtube-dl is in /usr/local/bin
… and we are going to use absolute paths which is of course not dynamic but easy.
5.1. Version 1
This version downloads the video directly by taking the URL from the clipboard and informs with a bubble failure or success. Imagine you are watching a youtube video in Safari and you want to download it. Press Cmd+L, Cmd+C, Cmd+Space, type YoutubeDL, press Enter (select URL, copy URL, start YoutubeDL).
https://gist.github.com/marcotrosi/89f535a0052f8e3c8454
5.2. Version 2
In this version you can decide between full video and audio track only, and you can paste the URL manually in case you started YoutubeDL before copying the URL into clipboard.
We discovered earlier that the bashrc/profile files are not loaded and this leads now to the first problem. For the audio extraction youtube-dl uses ffmpeg. But the /usr/local/bin path is not part of the PATH variable. We fix this with a quick workaround in line 4.
https://gist.github.com/marcotrosi/ec4fa686682745d5021d
5.3. Version 3
To get rid of the workaround from version 2 we need a second file. The filename will be YoutubeDL and the actual script (like version 1 and 2) will be renamed to YoutubeDL.sh.
The YoutubeDL wrapper script starts a shell in login mode (-l), which means that the users normal environment is available, and then it executes the main script (-c). The PATH variable is now set as the user needs it and therefore we can remove the workaround from version 2.
Additionally I changed the audio format to MP3. Without the --audio-format option you get whatever format is inside the video file. I added a progressbar and fancy icons to the bubbles.
https://gist.github.com/marcotrosi/b5997d48b0a594f35959
Btw. if you want to put now cocoaDialog/youtube-dl inside your application you have to create the absolute path to them. But as the working directory is the root directory, the absolute path is the same as the relative path start from the working directory which is the root. Clear? :-) You can use for example
dirname $0
to get the full path to the MacOS folder, and this is a good starting point I think. Let's assume you put the cocoaDialog.app into the MacOS folder then you could replace the line
CocoaDialog='/Applications/cocoaDialog.app/Contents/MacOS/cocoaDialog'
with
CocoaDialog='$(dirname $0)/cocoaDialog.app/Contents/MacOS/cocoaDialog'
and now it should work no matter where I put the YoutubeDL application. I didn't test it but I would expect it. Of course this needs to be repeated for youtube-dl too.
I would like to know what you can do with cocoaDialog
0 notes
Text
Vim - Confirm Function
Many of us have the problem remembering hardly used keymappings. For me there are only 2 ways of dealing with it. Either admitting that the keymapping of which I initially thought is very nice is actually absolutely useless why I radically remove it, or I realize the mapping is still handy but simply not needed that often. In that case I move it to my menus.
The menu command is probably known to most of you. That is why I wanna demonstrate an alternative solution by using the confirm function. Of course there are advantages and disadvantages for both solutions. I use both and not only for seldom used mappings as the first example will show.
Example 1 - Make Menu
All my makefiles have the targets build, test, tags, clean and some more. So I could have created mappings like ...
nmap <leader>mb :make build<cr> nmap <leader>mt :make test<cr> nmap <leader>mg :make tags<cr> nmap <leader>mc :make clean<cr> ...etc
My weak brain was not able to remember the shortcut for creating the tags file. So I came up with a solution using the confirm function to get a more visual feedback ...
https://gist.github.com/15e154f3aa0c31972aab
... which called looks like ...
... and now I can type the single letter representing the target I want to execute. If I want to abort I press the Escape key (confirm returns 0), and when I want the default target (in this case #1, calling make without target) I can alternatively press the Enter key. As you can see I needed an extra entry "abort" in my list to shift all other targets by 1, so I can directly use the return value of confirm to get the correct string for concat. Yes, I could instead subtract 1 from the return value when accessing the table.
Example 2 - LaTeX Menu
Nesting? Let's try. Here another example for LaTeX. I don't know if this useful, but it is just an example.
https://gist.github.com/3e13689d05a07b8297b8
Note that I set the FontSize default value to footnotesize (3rd parameter) because I wanted to keep the commands sorted by size.
And this is how it looks like. First you will be asked wether you want to set the FontFamily or the FontSize and then for the sub-values of the selected category. It works for the word under the cursor and for the selected text. Sorry for the bad quality.
For more information type :h confirm() inside Vim.
For what are you using the confirm function?
1 note
·
View note
Text
Vim - Link Collection
I had my first contact with Vim approx. 10 years back when I studied. In one of our C programming practicing lessons I asked my professor for help. He opened Vim on commandline and started typing. He was blazing fast with just two fingers. The characters jumped over the screen so crazy and I thought "Holy shit - how is he doing this, I don't understand". I just knew I loved it and I wanted to be able to this. A new nerd was born. I think three semesters later I had finally the time and chance to start using Vim during my practical semester. And of course you have to google a lot in the beginning and whenever I stumbled upon a good Vim site I saved it in my browser.
This is my Vim Link Collection in no particular order. Maybe you'll discover a Vim site you did not know yet.
Is there a cool site missing? Let me know.
vim.org
neovim.io
macvim-dev
vimdoc.sourceforge.net
vim-scripts.org
github vim-scripts
learnvimscriptthehardway.stevelosh.com
vim.wikia.com
vimrcfu.com
vim-adventures.com
vimgolf
openvim.com
vimawesome.com
vimgifs
vimcasts.org
vimninjas.com
shortcutfoo.com
vimregex.com
vi-improved.org
vim.begin-site.org
usevim.com
vim-fu
vim-galore
vim-bootstrap.appspot.com
dailyvim.blogspot.de
dailyvim.tumblr.com
derekwyatt blog & derekwyatt vids
rayninfo.co.uk
thomer.com
tnerual.eriogerg.free.fr
oualline.com
yannesposito.com
danielmiessler.com
cs.oberlin.edu
swaroopch.com
poho
vim.rtorr cheat sheet in various languages
vimsheet.com
graphical cheat sheet
vim cheat sheet for programmers
vim quickreference
vimcheatsheet.com
11 notes
·
View notes
Text
Lua - automatic logging idea
What is probably the most used debugging technique? Yes, a print call between each line. I tried to find a way to avoid such actions. My first attempt was a print wrapper function called dbg which only printed when a global flag called DEBUG was set to true. This was better because I could turn the debugging on/off when I needed it. But I still was not satisfied. I had annoying function calls in the code which may cost performance.
Some time ago I had the idea of an automatic logging mechanism where it is possible to observe functions previously registered in a table.
And this is what I have so far.
https://gist.github.com/1a150a36e900b15602ca
You can register the functions you want to observe. Unless you change the default value the last 20 entries will be printed. You can change the name/path of the logfile. And you can turn the logging really off.
log.IsOn = false log.Max = 35 log.File = "./myscript.log"
What do you think? How do you debug your code?
0 notes
Text
Vim - balloon and sign - Part 2
Part 1
For part 2 I promised a practical use case and I thought we could display some messages from a static analyzer (lint) like cppcheck or splint. Of course you could use a quickfixlist for that like you would do for the compiler messages, but the number of compile errors tends to be short, whereas the number of lint messages can get quite long - but that's a different topic.
First of all let's create some crappy code which produces some lint messages. Here are 3 pretty useless files - main.c, foo.c and foo.h.
Running splint gives the following messages (shortened)
foo.c:8:26: Variable Result initialized to type double, expects unsigned int
foo.c:12:11: Return value type unsigned int does not match declared type int
main.c:17:15: Fall through case (no preceding break)
main.c:19:17: Variable var used before definition
main.c:19:13: Return value (type int) ignored: foo(var)
The messages are in standard gcc format.
filename:linenum:colnum: message
I use signs to show in which line is at least one issue and balloons to show all messages refering to the line I hover with the mouse. E.g. line 19 in main.c ...
sign
Let's start with the signs. If you prefer pure Vim script then a possible solution could be ...
https://gist.github.com/c6af19db33d9af20880b
I mostly prefer writing Lua scripts and for debugging and test purposes I like to have intermediate files. Here is how I do it with an external script.
run the static analyzer and capture the output in a file
parse the lint messages file and create a Vim script file containing the sign placings with a "sign unplace *" command in the first line
run the generated Vim script with the :source command
Some lint tools distinguish between different types of messages. You can parse this information too and select a proper sign for each message type.
balloon
Next step is to create the balloon text. Therefore the filename and the linenumber in which the mouse is positioned will be used. Possible Vim script solution could be ...
https://gist.github.com/04d6d32cc7a6c5e56d8c
Now we have two functions - LintSign() and LintBalloon(). LintSign() could be triggered either manually or automatically e.g. after writing a file. The LintBalloon() function simply needs to assigned to balloonexpr.
autocmd BufWritePost *.c,*.h call LintSign() set balloonexpr=LintBalloon()
To get the same result but with an external Lua script I do something like ...
https://gist.github.com/c41b08945a162642c6ee
For what are you using the balloon and/or sign feature?
0 notes
Text
Vim - balloon and sign - Part 1
Do you know Vim's balloon and sign feature? There are some scripts which make use of them. For example the famous taglist.vim plugin which uses balloons to show the definition of a symbol, and most GDB plugins use signs to display the breakpoints.
I haven't seen many tutorials explaining these features, so I thought I could give at least an introduction. This tutorial consists of 2 parts. Part 1 will briefly explain how to set up balloons and signs in your .vimrc and part 2 will show an use case combining both features.
balloon
What it does is that when you hover with your mouse over a word a rectangle window pops up and usally shows some text. The cool thing is that you control what information to be displayed and as it is only a string it could be anything - spelling suggestions, the dictionary text or synonyms for that particular word, the documentation+examples of a function or whatever you can think of.
So how to set it up? Actually for balloon there is not so much to explain. There are only 2 important keywords you need to know. There is ballooneval and balloonexpr. We use set ballooneval to turn balloon on and of course set noballooneval to turn it off. balloonexpr is simply a variable you need to assign a function which returns a string. So whenever you hover with the mouse over a word and balloon is on then this function will be exectued and the returned string will be displayed in a box. Okay let's try this.
function! Balloon() return "hello world" endfunction set balloonexpr=Balloon() set ballooneval
So far so good. Now we will tweak the function a little bit and print some special balloon variables but of course you could use any available variable. For more information type :h v:
function! Balloon() let Info = "Window: " . v:beval_winnr let Info = Info . "\nBuffer: " . v:beval_bufnr let Info = Info . "\nLine: " . v:beval_lnum let Info = Info . "\nColumn: " . v:beval_col let Info = Info . "\nText: " . v:beval_text return Info endfunction
As you can see the newline character can be used too. And in case you didn't know, the dot operator concatenates two strings.
Now you can write your own balloon expression functions. Just create and return the string you want to display. And if there is nothing to display then return an empty string "", this way Vim doesn't create a balloon at all.
In part 2 we will invoke an external script which gets the information it needs to do something and it will return the string which Vim is then going to display in a balloon pop-up.
sign
Signs can be short strings (1 or 2 char) or tiny images which will be displayed on the left margin of a buffer. I will show you first how they look like, so that you know what I am talking about.
The image shows 4 different signs I defined and I placed them right beside the line which defines the corresponding sign. As you can already guess there is a command to define a sign and one to place a sign in a certain line.
hi red guifg=#F92672 guibg=#232526 gui=bold hi grn guifg=#A6E22E guibg=#232526 gui=bold hi org guifg=#FD971F guibg=#232526 gui=bold hi blu guifg=#66D9EF guibg=#232526 gui=bold sign define Error text=× texthl=red sign define Warn text=! texthl=org sign define Info text=i texthl=blu sign define Okay text=✔ texthl=grn
To define a sign you need a name (first parameter after 'define') and either a text (max. 2 chars) or an icon (icon=/path/to/icon). I think you can give a text and an icon and Vim decides automatically which to use. There are two optional arguments called texthl and linehl and both expect a highlight group name.
For placing a sign some more arguments are required.
sign place {id} line={lnum} name={name} file={fname} sign place {id} line={lnum} name={name} buffer={nr}
id is unique number to identify the placed sign
lnum is the line number where the sign will be placed
name is the name of the sign you want to place
fname is the file in which the sign will be placed
nr is the buffer number in which to place the sign and also the alternative to using the filename.
This means for the example above I used the following commands.
sign place 1 line=696 name=Error buffer=1 sign place 2 line=697 name=Warn buffer=1 sign place 3 line=698 name=Info buffer=1 sign place 4 line=699 name=Okay buffer=1
Instead of the buffer number I could have used the filename. The IDs have to be unique - no special sequence required.
To remove a single (id) or all (*) signs in one or all buffers use ...
sign unplace {id} file={fname} sign unplace * file={fname} sign unplace {id} buffer={nr} sign unplace * buffer={nr} sign unplace {id} sign unplace *
Part 2
0 notes
Text
Vim - listchars
Do you use :set list? I do sometimes - and this for a good reason. I once got from somewhere a code snippet and it was not compileable. It took me a while to figure out what was wrong with the code. You know - one of those moments when you want to smash everything into millions of pieces. Oh no no no, the code was fine, but there was a fucking non-breakable-whitespace somewhere. Looks like a normal whitespace but is a pain in the ass.
Afterwards I figured out that Vim can actually display this type of characters and some more. Check the Vim help for more info.
In the beginning I just extended the listchars string and kept the default $ for eol. Then I realized using a $ as an indicator for the end of a line is weird when your last character in a line is a $ too.
Many moons later I found this symbols overview on my Mac and I thought "Hey, can Vim (MacVim) display them?". Yes, at least some of them.
You can copy the symbols and paste them into a file to see how they look like inside Vim. Here are a bunch of them.
↩ ↵ ↲ ␣ • … → » ∎ ¶ ▶ ▸ ▷ ▹
My current listchars is this.
set listchars=eol:↲,tab:▶▹,nbsp:␣,extends:…,trail:•
And this is how it looks like with :set nolist and with :set list.
Notes:
the extends character is always visible (if :set nowrap)
the tab expects 2 characters
some characters may work better with a different font type but I do not recommend to change your favorite font just for the list characters
try different characters cause they always look different inside Vim
1 note
·
View note
Text
OS - compare this to that
Have you ever tried to compare 2 files on OSX? It's possible with FileMerge, but it is not so convenient. So I tried to find a way that makes it possible to select a file in Finder as a reference file and then a second file you want to compare with it. Of course I could use the Terminal, but the goal was to do it in the GUI with the Finder. Here is how I do it. If you have a better way let me know.
1 - create a new service
Start 'Automator' and create a new Service.
2 - select "run shell script"
Select "Run Shell Script" from the "Utilities" category.
3 - compare this ...
Make sure the settings are like in the image. Service receives selected files or folders in Finder. Shell is /bin/bash and pass input as arguments. And then echo the first parameter $1 (which will be the file you select in the active Finder window) and redirect it into a file of your choice. I use ~/.compare which would be a hidden file in my user home directory. Save this service with a proper name e.g. "compare_this".
echo $1 > ~/.compare
4 - ... to that
Repeat the steps 1, 2 and the settings of step 3 and instead of the echo you call your favorite diff/merge tool with what is selected now in Finder and compare it with what we selected before. So in case of MacVim it's ...
/usr/local/bin/mvim -d $1 `cat ~/.compare` &
Save the Service as e.g. "compare_to_that".
Explanation to step 4
/usr/local/bin/mvim is the path to my MacVim
-d is the parameter which starts Vim in diff mode
$1 is the file currently selected in the Finder window
cat ~/.compare means put the content of the file right here. cat is for printing files and the backticks put the output of cat right there. $(cat ~/.compare) may also work, I haven't tried it.
& ampersand to run MacVim in the background so the we do not wait for the process to finish
If I remember correct that's all. The services should now be available in the context menu in Finder. If you like you can go to the keyboard settings and give hotkeys to both services.
5 - compare files
The solution above is good and necessary when the 2 files you want to compare are placed in different dirctories. But when the files are in the same directory then it's annoying. I created a 3rd Automator service which takes 2 selected files as input.
/usr/local/bin/mvim -d $1 $2
Very cool with a keyboard shortcut.
0 notes
Text
OS - My favorite Mac Apps
From time to time it is necessary to clean-up a hard drive. You know, actions like moving thousands of files from the temp folder into the proper directory and giving better filenames, deleting useless files, tagging imported vintage CDs from the 90ies in iTunes, confirming faces in iPhoto and removing unknown programs. What? Unknown? Ya, the Apps you download and you think "Hey, that's a great tool, I definitely need this, and it's for free!!" and then you never use them. But there are exceptions. There are tools you don't want to live without.
Here is a list of not pre-installed Apps I use quite often or even daily.
MacVim
BetterTouchTool
Palua
Go2Shell (AppStore)
Telegram (AppStore)
MPlayerX (AppStore)
Vienna
MacVim
What shall I say? The one and only editor.
BetterTouchTool
Extend your trackpad (and more) gestures program-wise. You need this. Believe me.
Palua
Toggle Fn mode automatically. It relaxes my brain.
Go2Shell
Opens the terminal and sets the working directory to what was selected in Finder. I am sure other users would write an AppleScript for that, but it's so small and I wanted to have an App with such a cool name.
Telegram
Another InstantMessenger. Maybe the coolest. If you have already Telegram on your mobile device, then you should get this too.
MPlayerX
Probably the best video player.
Vienna
RSS Reader. Unfortunately Apple removed their RSS feature from Safari, so I needed a replacement. Other RSS tools were too big and Vienna does what I need without being complicated.
What are your most used tools?
0 notes
Text
Vim - statusline
My current statusline settings ...
hi slred guifg=#F92672 guibg=#232526 gui=bold hi slgrn guifg=#A6E22E guibg=#232526 gui=bold hi slorg guifg=#FD971F guibg=#232526 gui=bold hi slblu guifg=#66D9EF guibg=#232526 gui=bold set statusline=%#slorg#CD=%{getcwd()}%=%#slred#\ PERM=%{getfperm(expand('%'))}\ FORMAT=%{&ff}\ TYPE=%Y\ SPELL=%{&spelllang}\ %#slgrn#\ LINE=%l/%L(%p%%)\ COL=%v\ BYTE=%o\ %#slblu#\ DEC=\%b\ HEX=\%B\
... and that's what you get
Arrrgh - damn small. Just download it. ;-)
How does your statusline look like? Or do you use vim-airline?
2 notes
·
View notes
Text
Lua - printTable
Maybe my most frequent used Lua function is 'printTable'. I use it for debugging and for data storage. As Lua has no built-in function for printing tables (which is good), this might be the function which every Lua developer has to write.
I changed this function right before posting it, so it's kind of untested. So here is my solution.
https://gist.github.com/163b9e890e012c6a460a
Let's assume you have this table ...
MyData_t = { ["Name"]="John Doe", ["Address"]={["Street"]="Sesame Street 42", ["City"]="6666 RockCity"}, "foo", "bar"}
... and then you call printTable with a filename ...
printTable(MyData_t, "MyData.lua")
... you will get a readable and well indented table like ...
return { [1] = "foo", [2] = "bar", ["Address"] = { ["City"] = "6666 RockCity", ["Street"] = "Sesame Street 42", }, ["Name"] = "John Doe", }
... and because of the return the table can even be loaded with dofile
AnyTable_t = dofile("MyData.lua")
How do you print your tables?
0 notes