hasenj blog

Why I won’t use D for my next project

Posted in hacking, rant by hasen on 11/08/2009

I used to follow the D programming language closely, I thought it has some really great ideas, and it could potentially replace C++,

I’ve had an idea for a new project for a while now, and I started working on a proof of concept, which I wrote in D, and while the language syntax is great, I’m afraid I’m going to have to switch to another language. Before I say why I won’t use D, I want to mention why I wanted to use D in the first place:

I considered using Python, but I want to create an application that’s usable by ordinary people who are not programming nerds. I know I can convert the project into a windows application with tools like py2exe, but that will create a huge executable; not a good thing.

C++ is too complicated, I just hate the language.
Java is too bloated and complicated, I hate the language, and its environment, and the monster that’s called Eclipse.

C is certainly a lot less complicated than C++, but it’s old and its age shows. Though still, I might end up using it.

D seems just perfect, the syntax is nice, build tools are nice, it should be able to produce a small executable, and working with it should be a pleasure.

BUT, here are the problems:

I put a lot of effort into creating an environment for programming in D on windows. I downloaded DSSS and Tango, and also Tangobos. I also downloaded gtkD since I want a GUI for this project of mine. Setting these things up to work together is not exactly a very easy task; but still it wasn’t too difficult on windows. Though still, it’s not a very easy or pleasant task.

Recently I switched to Linux, and setting up a D environment in linux proved to be quite the hassle, that I essentially gave up on it. While I was able to install dmd with no problem, I didn’t know how to install DSSS. I tried with apt-get, but the DSSS I got expects to find gdc, when I have dmd.

Why is it so hard to setup a development environment for D? This is a problem, not only because it will cause me a headache, but it could put-off many potential/would-be contributors.

Also, I was considering switching from GTK+ to Qt, however the QtD project is also difficult to install, even on windows.

Above all, one of the main reasons I love(d) D is because its syntax and features and build system should theoretically make working with it a pleasure; but … it’s not a pleasure at all!! So why even bother? If it’s gonna cause more pain than pleasure, then I might as well work in C++, at least it’s well supported.

Do I wish to see D succeed? Yes.
Would I love to contribute to its success? Sure!
Am I gonna make sacrifices for it as if it was my religion? No.

I didn’t really explain in detail why installing D and setting up its dependencies is complicated, but those who’ve worked with it should have a good idea of why that is the case.

My entire point is: why the hell, after 10 years of development, is it still so dam hard to setup a D development environment on linux? Stop thinking about crazy new features for D2 and work on making sure that D1 (the original D) is well supported across-platforms. The way I see it, D is slowly turning into vaporware.

While this is an exaggeration, it will eventually die if the author(s) don’t make it their priority to make D usable with the least amount of hassle that’s possible, instead of cramming new features into D2.

Making a fancy window in wxPython

Posted in hacking by hasen on 14/04/2009

I’m pretty much a n00b when it comes to GUI programming. The truth of the matter is, I *hate* to program a GUI by assembling its parts together inside code. I mean, things like:

  • prepare an app object
  • prepare a window object
  • prepare a panel object (or several thereof)
  • prepare a sizer (layout manager) object (or several thereof)
  • sepcify initial sizes and dimensions
  • bind events
  • etc etc ..

Of course, this is an excuse for procrastination.

Also the fact that there are several frameworks outthere (wxwidgets, qt, etc) cause further confusion.

Anyway, for varios reasons, I’m trying to experiment with wxPython (the python interface to wxWidgets). And also for some reasons which I won’t go through, I wanted to make a “fancy” sort of window (like launchy’s window):

  • Has round corners
  • Maybe some transparency
  • Draggable around
  • No standard windows frames, buttons, etc
  • always on top

I’ll go through making each requirement of those, but since I’m a n00b myself, and just started, maybe I’m doing something simple in an overly complex way, so please let me know if you spot such issues with this post.

I’ll start with the easier stuff: always on top, no frames buttons etc, and some transparency.

First of all, read ZetCode’s “First Steps” tutorial for a very basic structure of an “app” that consists of a single window (frame)

So, Here’s a basic “empty” application, with nothing more than a window.

import wx

class FancyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title='Fancy')
        self.Show(True)

app = wx.App()
f = FancyFrame()
app.MainLoop()

Note that we’re subclassing Frame. I suppose it’s also possible to achieve this functionality without subclassing it, but this is the way I’m doing it, so .. there.

The result is the following:

Empty normal window

Empty normal window

Nothing fancy yet.

Now, make it always on to, and without any borders or controls, it’s really simple: just supply a “styles” parameter to the frame constructor.

You can see a list of styles here: http://docs.wxwidgets.org/2.6/wx_wxframe.html

We’ll use these styles:

wx.CLIP_CHILDREN | wx.STAY_ON_TOP | wx.NO_BORDER | wx.FRAME_SHAPED

By simple specifying some style other than the default, we already lost all the default stuff (the title bar and the minimize/maximize/close buttons).

import wx

class FancyFrame(wx.Frame):
    def __init__(self):
        style = ( wx.CLIP_CHILDREN | wx.STAY_ON_TOP |
                  wx.NO_BORDER | wx.FRAME_SHAPED  )
        wx.Frame.__init__(self, None, title='Fancy', style = style)
        self.Show(True)

app = wx.App()
f = FancyFrame()
app.MainLoop()

So now we have .. nothing! Just a gray rectangle! You might wonder, how are we gonna close that? Well, for now you can use alt-F4

Let’s add transparency too, it’s just a single line of code:

self.SetTransparent( value )

The value is from 0 to 255, with 0 being completely transparent, and 255 being competely opaque. Let’s use 220

import wx

class FancyFrame(wx.Frame):
    def __init__(self):
        style = ( wx.CLIP_CHILDREN | wx.STAY_ON_TOP |
                  wx.NO_BORDER | wx.FRAME_SHAPED  )
        wx.Frame.__init__(self, None, title='Fancy', style = style)
        self.SetTransparent( 220 )
        self.Show(True)

app = wx.App()
f = FancyFrame()
app.MainLoop()

Now, we have a transparent gray box!

Well, it’d be nice if we can close it with somethign other than alt-F4. That’s simple, we’ll just need an event handler for keyboard events. We’ll also add a wx.FRAME_NO_TASKBAR style so our “fancy” window doesn’t appear on the task bar. (is that evil?)

import wx

class FancyFrame(wx.Frame):
    def __init__(self):
        style = ( wx.CLIP_CHILDREN | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR |
                  wx.NO_BORDER | wx.FRAME_SHAPED  )
        wx.Frame.__init__(self, None, title='Fancy', style = style)
        self.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
        self.SetTransparent( 220 )
        self.Show(True)
    def OnKeyDown(self, event):
        """quit if user press q or Esc"""
        if event.GetKeyCode() == 27 or event.GetKeyCode() == ord('Q'): #27 is Esc
            self.Close(force=True)
        else:
            event.Skip()

app = wx.App()
f = FancyFrame()
app.MainLoop()

So now there’s no taskbar, and q or Esc can quit.

Now we want to be able to move it around by just dragging it with the mouse. Again, we need an event handle for mouse movements. Dragging is really simple: when we start dragging, we record the relative position of the mouse. While we’re draging, we move the window so that the relative position of the mouse always stays the same.

There are several ways to implement this, I’ve seen code that uses two handlers: one for when the mouse is clicked, another handler for when moving the mouse. for me, I find it simpler to handle it all in one function that handles wx.EVT_MOTION, here’s the handler: (note that the event recieved is a MouseEvent )

#in ctor
        self.Bind(wx.EVT_MOTION, self.OnMouse)
#in class def:
    def OnMouse(self, event):
        """implement dragging"""
        if not event.Dragging():
            self._dragPos = None
            return
        self.CaptureMouse()
        if not self._dragPos:
            self._dragPos = event.GetPosition()
        else:
            pos = event.GetPosition()
            displacement = self._dragPos - pos
            self.SetPosition( self.GetPosition() - displacement )

This will make the window draggable.

So far, this is what we have:

import wx

class FancyFrame(wx.Frame):
    def __init__(self):
        style = ( wx.CLIP_CHILDREN | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR |
                  wx.NO_BORDER | wx.FRAME_SHAPED  )
        wx.Frame.__init__(self, None, title='Fancy', style = style)
        self.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
        self.Bind(wx.EVT_MOTION, self.OnMouse)
        self.SetTransparent( 220 )
        self.Show(True)

    def OnKeyDown(self, event):
        """quit if user press q or Esc"""
        if event.GetKeyCode() == 27 or event.GetKeyCode() == ord('Q'): #27 is Esc
            self.Close(force=True)
        else:
            event.Skip()

    def OnMouse(self, event):
        """implement dragging"""
        if not event.Dragging():
            self._dragPos = None
            return
        self.CaptureMouse()
        if not self._dragPos:
            self._dragPos = event.GetPosition()
        else:
            pos = event.GetPosition()
            displacement = self._dragPos - pos
            self.SetPosition( self.GetPosition() - displacement )

app = wx.App()
f = FancyFrame()
app.MainLoop()
Transparent Draggable "window" with no titlebar or taskbar button

Transparent Draggable Gray Box

The snapshot doesn’t make much sense, but it’s there for completeness’ sake.

Now the part that’s a bit tougher and more problomatic: giving it a decent shape.

We passed a wx.FRAME_SHAPED style to the wx.Frame ctor, so that we can set the frame’s shape. To set the shape, we call SetShape and pass it a Region object. We want to construct a region object that is basically a rectangle with round corners. The easiest way to set such a shape is from a bitmap. We can get such a bitmap from an image file, but that’s not the only way. Infact, I specifically want to be able to do that without any external media file. I asked on stackoverflow but no one gave me an answer, so I had to dig on my own.

So we need a bitmap of a roned-corner rectangle, where do we get that without a file? Well, I found that you can draw a bitmap without a file using a MemoryDC. Basically, you bind the memory dc to an empty bitmap, draw some stuff on the memorydc, then when you unbind it from the bitmap, all the stuff that we drew will be on the bitmap. All DC objects had a DrawRoundedRectangle method.

So, now we can get a bitmap object that has a rounded rectangle drawn on it. To get that into a shape (region), we must first set a color mask for the bitmap, where the areas that have the color mask are to be transparent, and thus not part of the region.

The process to get that shape involves quite a bit of code, so we’ll put it into its own function, which takes a width, height, and radius:

def GetRoundBitmap( w, h, r ):
    maskColor = wx.Color(0,0,0)
    shownColor = wx.Color(5,5,5)
    b = wx.EmptyBitmap(w,h)
    dc = wx.MemoryDC(b)
    dc.SetBrush(wx.Brush(maskColor))
    dc.DrawRectangle(0,0,w,h)
    dc.SetBrush(wx.Brush(shownColor))
    dc.SetPen(wx.Pen(shownColor))
    dc.DrawRoundedRectangle(0,0,w,h,r)
    dc.SelectObject(wx.NullBitmap)
    b.SetMaskColour(maskColor)
    return b

def GetRoundShape( w, h, r ):
    return wx.RegionFromBitmap( GetRoundBitmap(w,h,r) )

Now, we have a region, we need to apply it to the window. To do that, we have to call SetShape, but apparently there’s a little trick involved in order to achieve cross-platformity. In windows, we set the shape in the constructor, while in GTK we set it on the event of the window creation.

#in ctor:
        if wx.Platform == '__WXGTK__':
            self.Bind(wx.EVT_WINDOW_CREATE, self.SetRoundShape)
        else:
            self.SetRoundShape()        

#in class body:
    def SetRoundShape(self, event=None):
        w, h = self.GetSizeTuple()
        self.SetShape(GetRoundShape( w,h, 10 ) )

So there, this makes the window rounded. Note however that we hard-coded the radius of the rounded corner, which is generally a bad idea.

Round corners (somewhat rough)

Round corners (somewhat rough)

The problem is that the edges are rough, I don’t know how to properly fix this, so I’ll try to hide it by drawing a border.

We’ll need to handle Paint events and draw whatever we want in there:

For painting, we just get a PaintDC to the window, and draw a rounded rectangle on the entire window with a pen (border) and a brush (backgrond)

#in ctor:
        self.Bind(wx.EVT_PAINT, self.OnPaint)
#in class body:
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        dc = wx.GCDC(dc)
        w, h = self.GetSizeTuple()
        r = 10
        dc.SetPen( wx.Pen("#806666", width = 2 ) )
        dc.SetBrush( wx.Brush("#80A0B0") )
        dc.DrawRoundedRectangle( 0,0,w,h,r )

The GCDC makes the drawing anti-aliased. (I tried to use it when making the shape but it didn’t work, or I didn’t know how to properly make it work).

For an additonal touch, we’ll call SetPosition() so the window starts somehwere in the middle of the screen rather than the top left corner

import wx

def GetRoundBitmap( w, h, r ):
    maskColor = wx.Color(0,0,0)
    shownColor = wx.Color(5,5,5)
    b = wx.EmptyBitmap(w,h)
    dc = wx.MemoryDC(b)
    dc.SetBrush(wx.Brush(maskColor))
    dc.DrawRectangle(0,0,w,h)
    dc.SetBrush(wx.Brush(shownColor))
    dc.SetPen(wx.Pen(shownColor))
    dc.DrawRoundedRectangle(0,0,w,h,r)
    dc.SelectObject(wx.NullBitmap)
    b.SetMaskColour(maskColor)
    return b

def GetRoundShape( w, h, r ):
    return wx.RegionFromBitmap( GetRoundBitmap(w,h,r) )

class FancyFrame(wx.Frame):
    def __init__(self):
        style = ( wx.CLIP_CHILDREN | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR |
                  wx.NO_BORDER | wx.FRAME_SHAPED  )
        wx.Frame.__init__(self, None, title='Fancy', style = style)
        self.SetSize( (300, 120) )
        self.SetPosition( (400,300) )
        self.SetTransparent( 220 )

        self.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
        self.Bind(wx.EVT_MOTION, self.OnMouse)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        if wx.Platform == '__WXGTK__':
            self.Bind(wx.EVT_WINDOW_CREATE, self.SetRoundShape)
        else:
            self.SetRoundShape()

        self.Show(True)

    def SetRoundShape(self, event=None):
        w, h = self.GetSizeTuple()
        self.SetShape(GetRoundShape( w,h, 10 ) )

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        dc = wx.GCDC(dc)
        w, h = self.GetSizeTuple()
        r = 10
        dc.SetPen( wx.Pen("#806666", width = 2 ) )
        dc.SetBrush( wx.Brush("#80A0B0") )
        dc.DrawRoundedRectangle( 0,0,w,h,r )

    def OnKeyDown(self, event):
        """quit if user press q or Esc"""
        if event.GetKeyCode() == 27 or event.GetKeyCode() == ord('Q'): #27 is Esc
            self.Close(force=True)
        else:
            event.Skip()

    def OnMouse(self, event):
        """implement dragging"""
        if not event.Dragging():
            self._dragPos = None
            return
        self.CaptureMouse()
        if not self._dragPos:
            self._dragPos = event.GetPosition()
        else:
            pos = event.GetPosition()
            displacement = self._dragPos - pos
            self.SetPosition( self.GetPosition() - displacement )

app = wx.App()
f = FancyFrame()
app.MainLoop()
with color and border

with color and border

There you have it, it’s not quiet so fancy, but it should be a good starting point for adding more fancier stuff.

Vim through examples

Posted in hacking, tutorial by hasen on 11/04/2009

I’ve seen several people in varios places (specially stackoverflow) claim that vim increases their productivity by ten folds or whatever.

Now, I remember trying vim once or twice, and it drove me nuts. See, the thing is, with typical text editors, you type text and it’s there. But not so with vim.

In vim, to start typing yo must first press ‘i’ to go to “insert mode”. What a dumb idea, (one is forced to think), who would ever think of making a text editor that works like that? And so you just dismiss vim as an idiotic backward tool that’s still left over from the old days of terminals and main-frame: dumb keyboard, no mouse, dumb terminal screen (no colors!), etc.

But all these people saying that vim is so good, I mean, there must be something to it. So I started investigating into vim, and found this excellent article:

Why, oh WHY do those #?@! nutheads use vim?

Please go and read it! I can’t stress enough how good it is. I mean, FINALLY vim makes (at least) some sense.

The killer in that article are the couple of examples that it presents. *That’s what bought me into vim*. Examples are also a great way of learning something complicated like vim.

I mean, sure, you can google “vim tutorials” and find tons of “manuals” that explain what each key does. But that’s the /booooring/way of learning.

What I like instead is an interactive learning by example. It gives you first hand experience, withot delays, and helps your brain absorb the different concepts step by step (incrementally) by actually applying it directly, as opposed to holding it in your brain (or on a piece of paper, if you like taking notes, which I sorta doubt).

I also found this tutorial where the author pasted his irc chat log where he teaches someone how to edit with vim by example. I also found his tutorial very good.

Since I’m myself starting to learn vim and try to work with it, I thought I’d share my experience and present what I learn as a “vim by example” tutorial (or series of tutorials).

For completeness’ sake, I’ll steal some key points from the “nutheads” article.

The foundational concepts:

The first thing you need to understand about vim is that it’s different from typical text editors. The default mode is not “inserting text”, but “managing the text with commands”. You only enter “insert mode” briefly to insert text, then go back to command mode right away. Notice that “command mode” is called “normal mode”.

The second thing you need to know, is that everything in vim is designed so that you edit text without having to move your hand too much. Moving your hand too much means moving too far away from the “home raw” (the middle raw of the keyboard, asdf .. jkl;). For example, reaching for the mouse is “too much movement”, even reaching for the arrow keys is too much movement. You can do most of the editing tasks in vim without ever moving your right hand too much. The only extra movement that’s un-avoidable is reaching for the ctrl and shift keys. You might also need to reach for Esc, but it’s not unavoidable. (to change from insert mode to normal command mode, you either press Esc or `ctrl-[`, so as yo can see, you /can/ avoid reaching out for the Esc key.

Finally, you need to be fast with the keyboard, and be able to type without looking. You don’t really have to be a touch-typist (I am not anyway), but just be good enough with typing without looking too much (I still look when I type numbers).

Before we start, I want you to edit your vim settings file. On unix, that’s ~/.vimrc, on windows, it’ll be a file called _vimrc in the vim installation directory.

Add this line to what’s already in the file:
set tabstop=4 softtabstop=4 shiftwidth=4 expandtab autoindent cindent number
What is does is use spaces for tabs and makes it 4 spaces. I won’t go into why it does that (I don’t even really know myself, I just kinda googled it!) Also this will set auto indentation on (if it’s not on by default for some reason).  And finally this will make vim show line numbers.

Of course, since you’re just starting with vim (as I assume), you’ll need to edit that file with a text editor that you’re comfortable with, such as notepad++ or whatever else you’re using. Don’t try to be a smartass and use vim to edit that file!

For the rest of this tutorial, we’ll use a file that already has text in it and explore various ways to edit it using vim. Meaning we’ll not start from scratch.

So, first, opening and exiting vim:

I’m personally using gvim 7.2, so if you’re using that, open it from the start menu or using launchy or from your desktop shortcut, what ever. If you’re using the command-line version (please make sure it’s v7.2, not some 5.x or 6.x) then simpy type vim at the command line.

To quit vim right away, type :q!

: is used to enter text commands (different from the typical commands in command mode, and the text commands are referred to as Ex commands).
q is the command for quitting.
! means ignore unsaved changes.

So, the easiest way to quit vim at any time is to type :q! when you’re in command mode. If for any reason you’re not in command mode, just press Esc before typing that.

So if you’re following along but want to stop for some reason and quit vim, you know what to do.

For the purpose of this tutorial, create a text file that has the following text (again, create this file from an editor other than vim, such as notepad++):

//vim example
void main()
{
    std::cout << "ihello vimEsc" << std::end;
    return 0
}

I know there are errors there. It’s on purpose so we can correct them with vim! Now, go ahead an open that file with vim. Just type vim at the terminal followed by the file’s name (assuming you’re in its directory). If you see an empty file instead, that means you didn’t open the file, so quit vim and try again.

Moving around:

You’ll start with the cursor at the top, in command mode (normal mode).

Now, make sure your hand is rested on the home row, with the index finger of the right hand on the ‘j’ key. That key is used to move the cursor down. It’s the down arrow key :)

It may seem weird at first, but don’t we spend most of the time moving the cursor up and down? well, it’s right at your finger tips (literally!) j is down, and k is up. So move the cursor up and down, get yourself used to that.

Now, we want to include iostream library, which we “forgot”! So we need to open a new line below the “vim example” comment.

There are two ways to do that, let’s start with the dumb way:

go up to the first line, press `i` to enter insert mode, press End, then Enter, and start typing the include statement. When done, press Esc to go back to normal mode.

Now, press `u` to undo that, because we’ll do it again but differently.

Pressing End then Enter is the typical way to open new lines in typical text editors. In vim though, there’s a shortcut: press `o` to open a new line and enter insert mode. Now, type the include statement again and press Esc or ctrl-[ to go back to normal mode (command mode).

Or, you can also open a line “above” where the cursor is, using `O` (capital o). You’ll find this pattern repeated through out other commands, where the capital letter does something similar but in reverse or something.

Now, to move left and right, you can use `l` and `h`, but that’s boring and stupid. better use `w` and `b` which move by words.

w moves a word forward
b moves a word back

Try it now, move arond with w and b. Get used to it for a bit.

now, we want to change that void main to int main. so go to that line (with k and j ), move the cursor to the beginning of the line with 0 (zero), and type (in command mode) cw

cw means “change word”. It will delete the word under the cursor and put you in insert mode.

Now, type `int` and press Esc or ctrl-[ to go back to normal mode.

Commands and motions:

What you saw just now is an example of motions and commands that act on motions.

j, k, l, h, w, b are motions. They move the cursor to a new place.

c is a command (change) that acts on motions. When you press c, vim waits for you to tell it which motion to use for it.

The change command, like I said, deletes the text that you moved over with the motion, and puts you in insert mode.

See, if you are standing at the beginning of the phrase “void main”, and press w, the cursor would move to the location of “m”. The cursor moved over the word “void “. So, cw changes that block of text that the cursor moved over.

This is somewhat of a simplification, as it doesn’t always work like this. For instance, cj will delete the current line and the line below it *entirely*, not just from where the cursor was to where it would’ve been by pressing j alone.

Going in insert mode:

As you already saw, `i` is not the only way of entering insert mode. We saw that c{motion} also enters insert mode, after deleting a segment of text. and `o` also enters insert mode, after opening a new line.

Another way is `a`, which enters insert mode after moving the cursor one step forward. You can think of it as inserting “after” the cursor position.

`A` (capital a) moves the cursor to the end of the line and enters insert mode from there. We’ll use this to add the missing semicolon from “return 0”. So, go to the line that says return 0. For fun, move the cursor to the beginning or middle of the line (using h or w) just in case it already was at the end of it.

Now, press `A`, then `;`, then ctrl-[

I hope you’re following along, because it’s pointless to just read this without doing it.

Repeating commands and motions:

Motions can be repeated. For instance, 3w will move the cursor 3 words forward. Also, c2w will change two words.

I’ll list a coupe of extra commands (we won’t be using them right away, but just so you know them):

d is like c, but it doesn’t enter insert mode; it just deletes the segment.

cc will change the entire line, and dd deletes the entire line.

Actually, cc and dd don’t just “delete” the stuff, they also copy it.

You can copy stuff without deleting it, using y. (y stands for yank, which is vim-jargon for copy).
y works just like c and d, but it doesn’t delete the text; just copies it. You can paste it using p. (more on that later inshallah)

2dd will delete 2 lines
5yy will copy five lines
y5w will copy five words

Another command that can be “repeated”: {number}G will go to the line number

3G will go to line 3

:3 also goes t line 3 (in this case it’s not a repeat, it’s an Ex command .. I think so anyway)

pasting can also be repeated:
3p will paste the copied text three times

Going directly to where you want:

Suppose you’re looking at the hello vim string “ihello vimEsc”, and you want to capetalize the h in hello so it becomes Hello

simple, go to the line that contains it (I have it as line 6) by pressing 6G,or :6, or just with j and k,  then go the start of the line, using 0

Now, press `fh`, which means “find h”. This will find the first occurance of the letter h and move the cursor to it. If you happened to have another h before where you want to go, you can repeat this “find” using the semicolon ; which repeats the last `f` motion.

Now, your cursor is on h in ihello, to capetalize it, press the tilde ~ button. This will toggle the case of the letter under the cursor and move the cursor forward. (notice that you didn’t even need to enter insert mode!). This is also repeatable, so 3~ will toggle the case of the next three letters.

F will do the same as f but backwards. Meaning search backward to the first occurance of character c.
t is similar to f but it stops right before the character. T is the same but backwards.
`;` will repeat the last such motion like I already said
`,` will repeat the motion in reverse. So if you did `fh`, then `,` will search backward for h

Saving:

So maybe you know feel like you want to save this file, sure, just type :w in command mode. w is the Ex command for saving, it stands for “write”.

Summary so far:

jkhl — basic navigation
wbe — word level navigation
d/c/y{motion} — delete/change/copy text
p — paste text
u — undo
ctrl-r — redo (I forgot to mention this! oh well)
~ — toggle case
0 — go to line beginning
$ — go to line end
{number}G — go to line number

This is the end of the first part of this tutorial, I hope (inshalla) that other parts will follow soon.

Tagged with: , ,

modifying plink to work with unison

Posted in hacking, webdev by hasen on 19/12/2008

Last time I talked about how to make unison work on windows with ssh.

Well, there was still one problem that remained unsolved, that is, password input.

I thought about the issue and figured I could hack plink’s source code to make the modifications necessary to make it work like unison expects it to.

The changes are simple:

  • make it accept -e none
  • make it print the password prompt to stderr instead of stdout

in winsoncs.h change hin and hout, around line 325:

    hin = CreateFile("CONIN$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
    hout = GetStdHandle(STD_ERROR_HANDLE);

and in cmdline.c around line 438:

    //ignore "-e" option! (for unison compatibility)
    if( !strcmp(p,"-e") )
    {
        RETURN(2);       
    }

It’s not heavy tested, and frankly it’s a hack in a sense, I didn’t study plink’s source code in any kind of depth! Who knows, maybe my changes break the behavior in some (at least subtle) ways, but it works for me!

here is the result

This is not a wrapper; it’s a modified plink, and we call it ssh.exe so that it integrates with unison.