Sunday, March 27, 2011

programmatically create a node with file upload attachment

After much sweat and frustration, I've finally figured out how to tweak my tried
and true Drupal import script to work for Drupal 6.


I often find myself creating Drupal sites for groups with either existing web
sites (in other content management systems) or with file libraries that they
want to use to import into their new site.


Drupal's bootstrap function and node api makes it really easy to create a
script that can be run from the command line to handle the import.


Here are the key components for making it work with Drupal 6.


The import script has to be located in the web directory. Since I don't want
people to accidentally or on purpose run it from a web session, I include the
followig line:


    // prevent this from running under apache:
    if (array_key_exists('REQUEST_METHOD', $_SERVER)) {
    echo 'nope.  not executing except from the command line.';
    exit(1);
    }

Unfortunately, Drupal's boostrap function will complain if it doesn't detect
the HTTP_HOST variable, so I add it here. It doesn't matter what that variable
is:


    // set HTTP_HOST or drupal will refuse to bootstrap
    $_SERVER['HTTP_HOST'] = 'example.org';

Next comes the boostrap function will brings in all the Drupal libraries:


    include_once 'includes/bootstrap.inc';
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

Although not stricly necessary, some modules require a $user variable, so it
makes sense to create one. Setting the user id to 1 will guarantee that you'll
have access to do what you need to do. Depending on what you're doing, you
might want to use a user with less privileges to prevent any bug from
destroying all your data.


    global $user;
    $user = user_load(1);

Here is the basic node creation:


    $node = new stdClass();
    $node->type = 'story';
    $node->status = 1;
    $node->uid = 1;
    $node->title = 'My Title';
    $node->body = 'My body;
    $node->created = time();
    $node->changed = $node->created;
    $node->promote = 1;
    $node->sticky = 0;
    $node->format = 1;
    $node->language = 'en';

Here's an example of a CCK field:


    $node->field_date = array(
        0 => array(
         'value' => '2009-02-09T00:00:00',
        ),
    );

And at last, here's the elusive file attachment code:


    $file = '/path/to/your/file.odt';
 
    // Get the file size
    $details = stat($file);
    $filesize = $details['size'];
 
    // Get the path to your Drupal site's files directory 
    $dest = file_directory_path();
 
    // Copy the file to the Drupal files directory 
    if(!file_copy($file,,$dest)) {
        echo "Failed to move file: $file.\n";
        return;
    } else {
        // file_move might change the name of the file
        $name = basename($file);
    }
 
    // Build the file object
    $file_obj = new stdClass();
    $file_obj->filename = $name;
    $file_obj->filepath = $file;
    $file_obj->filemime =  file_get_mimetype($name);
    $file_obj->filesize = $filesize;
    $file_obj->filesource = $name;
    // You can change this to the UID you want
    $file_obj->uid = 1;
    $file_obj->status = FILE_STATUS_TEMPORARY;
    $file_obj->timestamp = time();
    $file_obj->list = 1;
    $file_obj->new = true;
 
    // Save file to files table
    drupal_write_record('files', $file_obj);
 
    // change file status to permanent
    file_set_status($file_obj, 1);
 
    // Attach the file object to your node
    $node->files[$file_obj->fid] = $file_obj;

Lastly, save the node:



  node_save($node);
  upload_save($node); // to upload table.
  echo "Savied node: $node->nid\n";

That's it. Below I've copied a real life working version that takes all the
files in a given directory and creates a node for each file in which the node's
title is the title of the file, the date of the file is entered as a CCK date
field, and the body of the node is a text version of the document (if it's pdf,
doc, or wpd).


    <?php
    /* 
     * This script is used to manually import files 
     *
     */
 
    // edit the following two lines
    // set the path where the files you want to  import exist. 
    $target = '../import-files-from-mbox/files';
 
    // what user id should the files be imported as?
    $uid = 1;
 
    // prevent this from running under apache:
    if (array_key_exists('REQUEST_METHOD', $_SERVER)) {
        echo 'nope.  not executing except from the command line.';
        exit(1);
    }
 
    // set HTTP_HOST or drupal will refuse to bootstrap
    $_SERVER['HTTP_HOST'] = 'example.org';
    include_once 'includes/bootstrap.inc';
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 
    // create a user that will be the author of the files/nodes
    // created
 
    global $user;
    $user = user_load($uid);
 
    // iterate over directory
    $d = dir($target);
    while (false !== ($name = $d->read())) {
        if($name != '.' && $name != '..') {
            $errors = file_validate_name_length($name);
            if(count($errors) > 0) {
                echo "Invalid name length, skipping: $name\n";
                continue;
            }
 
            // set some defaults for the file we will be importing
            $file = "$target/$name";
            $details = stat($file);
            $filesize = $details['size'];
            $mtime = $details['mtime'];
            $date_value = date('Y-m-d\T00:00:00',$mtime);
 
            // create the node object
            $node = new stdClass();
            $node->type = 'lib_item';
            $node->status = 1;
            $node->uid = 1;
            $node->title = $name;
            $node->body = extract_body($file);
            $node->created = time();
            $node->changed = $node->created;
            $node->promote = 1;
            $node->sticky = 0;
            $node->format = 1;
            $node->language = 'en';
 
            // custom node fields
            $node->field_date = array(
                0 => array(
                 'value' => $date_value,
                ),
            );  
 
            // handle the file upload
            $dest = file_directory_path();
            // copy the file to the files directory 
            if(!file_copy($file,$dest)) {
                echo "Failed to move file: $file\n";
                continue;
            } else {
                // file_move might change the name of the file
                $name = basename($file);
            }
 
            // build file object
            $file_obj = new stdClass();
            $file_obj->filename = $name;
            $file_obj->filepath = $file;
            $file_obj->filemime =  file_get_mimetype($name);
            $file_obj->filesize = $filesize;
            $file_obj->filesource = $name;
            $file_obj->uid = 1;
            $file_obj->status = FILE_STATUS_TEMPORARY;
            $file_obj->timestamp = time();
            $file_obj->list = 1;
            $file_obj->new = true;
 
            // save file to database
            drupal_write_record('files', $file_obj);
 
            // change file status to permanent (default is temporary)
            file_set_status($file_obj, 1);
 
            $node->files[$file_obj->fid] = $file_obj;
            node_save($node);
            upload_save($node); // to upload table.
            echo "Savied node: $node->nid\n";
            exit;
        }
    }
 
    function extract_body($name) {
        $pos = strrpos($name,'.');
        $ext = strtolower(substr($name,$pos+1));
        $cmd = '';
        if($ext == 'doc') {
            $cmd = 'antiword';
        } elseif($ext == 'pdf') {
            $cmd = 'pdftotext';
        } elseif($ext == 'wpd') {
            $cmd = 'wpd2text';
        } else {
            return '';
        }
        exec(escapeshellcmd($cmd) . ' ' . escapeshellarg($name),$ret,$error);
        if($error != 0) return '';
        return implode("\n",$ret);
    }
    ?>

Reference:
http://workingdirectory.net/posts/2009/attach-file-to-node-drupal-6/

Sunday, March 20, 2011

copy selection to OS X system clipboard in Vim

Method 1:
To copy the output in Mac OSX Terminal to clipboard, you can use the the command pbcopy:

Add this to your ~/.vimrc:

" ctrl-x for cut
vmap <C-x> :!pbcopy<cr>
" ctrl-c for copy
vmap <C-c> :w !pbcopy<cr><cr>

Then, on your desktop application, press command-v to paste.

Note: pbcopy is a system command. For example:
# cat fileName.txt | pbcopy

Method 2:
Download and install MacVim

For MacVim and Windows Gvim, simply add the following to your ~/.vimrc:

set clipboard=unnamed

Now all operations such as yy, D, and P work with the clipboard. No need to prefix them with "* or "+.

Method 3:
If the clipboard is enabled, you can copy a selected region to the clipboard by hitting:

"*y
or
"+y

Note: In X11, Vim's "* is PRIMARY, "+ is CLIPBOARD, and SECONDARY doesn't get a named register. (Not that anybody uses it...).

To see if it is enabled, execute vim --version and look for +clipboard or -clipboard. For example, it's not enabled by default on my 10.6.0 box:

# vim --version | grep clipboard
-clipboard

For MacVim and Windows Gvim, simply add the following to your ~/.vimrc:

set clipboard=unnamed

Now all operations such as yy, D, and P work with the clipboard. No need to prefix them with "* or "+.

Method 4:
If you are using MacPorts you can upgrade your VIM to include clipboard support via:

port install vim +x +x11

Now you use the "+ register to yank your text directly to your Mac clipboard. Works like a charm.

Reference:
http://stackoverflow.com/questions/677986/vim-copy-selection-to-os-x-clipboard

Saturday, March 19, 2011

Disable auto indent when pasting code text into vim

Method 1:
Paste toggle

Put the following in your vimrc (change the <F2> to whatever key you want):

set pastetoggle=<F2>

Note: if F2 key does not work, you might need to press ctrl-v F2 keys instead of just "F2" key.

To paste from another application:
Press (toggles the 'paste' option on).
Use your terminal to paste text from the clipboard. (Shift - Insert key)
Press (toggles the 'paste' option off).
Then the existing indentation of the pasted text will be retained.
If you have a mapping for , that mapping will apply (and the 'pastetoggle' function will not operate).
Some people like the visual feedback shown in the status line by the following alternative for your vimrc:

nnoremap <F2> :set invpaste paste?<CR>
imap <F2> <C-O><F2>
set pastetoggle=<F2>

The first line sets a mapping so that pressing <F2> in normal mode will invert the 'paste' option, and will then show the value of that option. The second line does the same in insert mode (but insert mode mappings only apply when 'paste' is off). The third line allows you to press <F2> when in insert mode, to turn 'paste' off.

http://gala4th.blogspot.com/2009/11/toggle-auto-indenting-for-code-paste.html

Method 2:
When you copy multiple lines text and paste it into the vim , sometimes you might find the text is aligned wrongly as the following:

Line1
    Line 2
        Line 3
            Line 4

To solve this problem, enter the paste mode by

: set paste

Then do all the pasting works, and when finished, type

: set nopaste

Reference:
http://www.linuxask.com/questions/disable-auto-indent-when-pasting-text-into-vim

Tuesday, March 15, 2011

Create multiple step form in Drupal 6

Create multiple step form in Drupal 6
Fri, Apr 24, 2009 by Sae
Multiple step form which consists of multiple steps or pages is useful sometimes. It allows you to create a form workflow and helps to make your web site user-friendly and flexible. For example, you can make different contents on next pages based on user inputs from previous pages.

The key things to make a form multiple pages are setting $form_state['rebuild'] and $form_state['storage'] variables in a submit function.



function example_form_submit($form, &$form_state) {
if($form_state['storage']['page'] == 1) {
$form_state['rebuild'] = TRUE;
$form_state['storage'][$page]['values'] = $form_state['values'];
$form_state['storage']['page']++;
else {
//process the data
}
}

In Drupal 6 FormAPI, a form is cached after it is built once, so setting $form_state['rebuld'] to TRUE rebuilds the form from scratch and allows you to make changes on the form structure after the form is submitted. Also, storing the input from the form into $form_state['storage'] cache the data and carries them to the next page so you can process all inputs together when the last step form is submitted.

I was working on a very simple multi-step form which asks users to choose a type of contents on the first page and provides different input fields based on user's choice from the first step on the next page. My form function was like:

function example_form(&$form_state) {
if(isset($form_state['storage']['page'])) {
$page = $form_state['storage']['page'];
} else {
$page = 1;
}
switch($page) {
case 1:
$form['content_types'] = array(
'#type' => 'radios',
'#title' => t('Content Type'),
'#description' => t('Select a content type'),
'#options' => $options );
break;
case 2:
$type = $form_state['values']['content_types'];
$form['content_fields'] = example_content_fields_form($type);
break;
}
return $form;
}

When the form is loaded first time, $form['storage']['page'] is not set yet. Set this 'page' key to 1 as a default value. Now you can create form elements based on the value of this 'page' variable. When the form is submitted, the submit function stores the input data to $form_state['storage'] variable and increments the page counter. Drupal FAPI reloads the form and back to the form function again.

You can create a form with more steps in the same way applying more page counts. Also, this works with hook_form_alter() so you can customize Drupal forms such as a registration form
=========================================
create article . I got this other solution on the intenet, it is worth looking at.

How to Handle the Three Scenerios

Let's step back for a moment. We now understand the cause of the problem in Form API 1.0: a mismatch between the user's submitted input, and the form array that's build based on it. We also understand how Form API 2.0 fixes that, allowing one form array to be used for processing and another for display. With that in mind, how can your module handle the three dynamic form scenerios outlined at the beginning of the article?

The Long Form

As with all of these scenerios, the real action will happen in your form building function. It will use hidden fields to indicate what 'stage' is currently being displayed, and to store the user input from previous stages. While this was theoretically possible using Form API 1.0, the new features make it much simpler. Here's an example of how your form-building code would look:

function my_form($param1, $param2, $form_values = NULL) {
// In a multistep form, drupal_get_form() will always
// pass the incoming form values to you after any other
// parameters that you specify manually. Do this instead
// of looking at the incoming $_POST variable manually.

if (!isset($form_values)) {
$step = 1;
}
else {
$step = $form_values['step'] + 1;
}

$form['step'] = array(
'#type' => 'hidden',
'#value' => $step,
);

switch ($step) {
case 1:
// Create the fields for the first step of your form here
break;

case 2:
// First, add a hidden field for each of the incoming
// form values.
// Then, add the fields regular form fields that the user
// will see in this second step.
break;

case 3:
// And so on and so forth, until you've reached the final
// step.
break;
}

// This part is important!
$form['#multistep'] = TRUE;
$form['#redirect'] = FALSE;

$form['submit'] = array(
'#type' => 'submit',
);

return $form;
}

In the validation code for your form, you can check the 'step' field to see which set of fields you need to check, and display any errors. The function will keep accumulating hidden values and displaying a new set of fields until it reaches the final step. You'll probably want to prevent your form submission handler from processing the form data until all the steps have been completed. To do that, something like this would be effective:

function my_form_submit($form_id, $form_values) {
$final_step = 10;

if ($form_values['step'] == $final_step) {
// Process the form here!
}
}

The Wizard

This scenerio, from a code perspective, is almost exactly the same as The Long Form. Depending on how your Wizard works, though, you may want to have your form submission handler actually process each step's data, rather than storing it as hidden fields in the next step. Or, you may want to process 'batches' of steps together before proceeding. For example:

function my_form_submit($form_id, $form_values) {
switch ($form_values['step']) {
case 3:
// Process the form data from steps 1, 2, and 3
break;
case 9:
// Process the form data from steps 4 through 9
break;
case 10:
// Process the form data from step 10,
break;
}
}

For very complex wizards, you may also want to split out individual steps as helper functions, but you'll still need to use the 'core' function as the central dispatcher. It's the one that the Form API knows to call automatically during the building and processing stages.

Reference:
http://www.appnovation.com/create-multiple-step-form-drupal-6

Saturday, March 12, 2011

Friday, March 11, 2011

To Comment / UnComment single / multiple lines of code for different source files

To Comment / UnComment single / multiple lines of code for different source files

Method 1:
Vim Visual Mode
Ctrl-v jjjjjj shift-i # Ctrl-[

Method 2:
Ctrl-v jjjjjj shift-i # ESC

Method 3 (GOOD):
Put following lines in your ~/.vimrc
map ,c I#

In vim, press ctrl-v to switch to block visual mode, then press ,c to comment.

To uncomment, press ctrl-v jjjjjjx (cut).
Note: this works in visual mode as well.

Method 4:
Put these lines in your ~/.vimrc
map ,c :s/^/#/
map ,u :s/^#//

Note: this works in visual mode as well.

Method 5:
Use this plugin: comments.vim

Tuesday, March 8, 2011

how to reload the current file in Vim vi

You can use the following command, without specifying a file name, to reload the current file:

:edit

or shortcut
:e

If you have made modifications to the file, you can use the following command to force the reload of the current file (you will lose your modifications):

:edit!

or shortcut
:e!

For more information, read:

:help :edit
:help :edit!
:help 'confirm'

Reference:
http://stevemorin.blogspot.com/2005/11/vim-vi-how-to-reload-file-your-editing.html

Monday, March 7, 2011

The ultimate Vim Confiruation vimrc sample example

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Maintainer: amix the lucky stiff
" http://amix.dk - amix@amix.dk
"
" Version: 3.6 - 25/08/10 14:40:30
"
" Blog_post:
" http://amix.dk/blog/post/19486#The-ultimate-vim-configuration-vimrc
" Syntax_highlighted:
" http://amix.dk/vim/vimrc.html
" Raw_version:
" http://amix.dk/vim/vimrc.txt
"
" How_to_Install_on_Unix:
" $ mkdir ~/.vim_runtime
" $ svn co svn://orangoo.com/vim ~/.vim_runtime
" $ cat ~/.vim_runtime/install.sh
" $ sh ~/.vim_runtime/install.sh <system>
" <sytem> can be `mac`, `linux` or `windows`
"
" How_to_Upgrade:
" $ svn update ~/.vim_runtime
"
" Sections:
" -> General
" -> VIM user interface
" -> Colors and Fonts
" -> Files and backups
" -> Text, tab and indent related
" -> Visual mode related
" -> Command mode related
" -> Moving around, tabs and buffers
" -> Statusline
" -> Parenthesis/bracket expanding
" -> General Abbrevs
" -> Editing mappings
"
" -> Cope
" -> Minibuffer plugin
" -> Omni complete functions
" -> Python section
" -> JavaScript section
"
"
" Plugins_Included:
" > minibufexpl.vim - http://www.vim.org/scripts/script.php?script_id=159
" Makes it easy to get an overview of buffers:
" info -> :e ~/.vim_runtime/plugin/minibufexpl.vim
"
" > bufexplorer - http://www.vim.org/scripts/script.php?script_id=42
" Makes it easy to switch between buffers:
" info -> :help bufExplorer
"
" > yankring.vim - http://www.vim.org/scripts/script.php?script_id=1234
" Emacs's killring, useful when using the clipboard:
" info -> :help yankring
"
" > surround.vim - http://www.vim.org/scripts/script.php?script_id=1697
" Makes it easy to work with surrounding text:
" info -> :help surround
"
" > snipMate.vim - http://www.vim.org/scripts/script.php?script_id=2540
" Snippets for many languages (similar to TextMate's):
" info -> :help snipMate
"
" > mru.vim - http://www.vim.org/scripts/script.php?script_id=521
" Plugin to manage Most Recently Used (MRU) files:
" info -> :e ~/.vim_runtime/plugin/mru.vim
"
" > Command-T - http://www.vim.org/scripts/script.php?script_id=3025
" Command-T plug-in provides an extremely fast, intuitive mechanism for opening filesa:
" info -> :help CommandT
" screencast and web-help -> http://amix.dk/blog/post/19501
"
"
" Revisions:
" > 3.6: Added lots of stuff (colors, Command-T, Vim 7.3 persistent undo etc.)
" > 3.5: Paste mode is now shown in status line if you are in paste mode
" > 3.4: Added mru.vim
" > 3.3: Added syntax highlighting for Mako mako.vim
" > 3.2: Turned on python_highlight_all for better syntax
" highlighting for Python
" > 3.1: Added revisions ;) and bufexplorer.vim
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => General
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Sets how many lines of history VIM has to remember
set history=700

" Enable filetype plugin
filetype plugin on
filetype indent on

" Set to auto read when a file is changed from the outside
set autoread

" With a map leader it's possible to do extra key combinations
" like <leader>w saves the current file
let mapleader = ","
let g:mapleader = ","

" Fast saving
nmap <leader>w :w!<cr>

" Fast editing of the .vimrc
map <leader>e :e! ~/.vim_runtime/vimrc<cr>

" When vimrc is edited, reload it
autocmd! bufwritepost vimrc source ~/.vim_runtime/vimrc


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => VIM user interface
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Set 7 lines to the curors - when moving vertical..
set so=7

set wildmenu "Turn on WiLd menu

set ruler "Always show current position

set cmdheight=2 "The commandbar height

set hid "Change buffer - without saving

" Set backspace config
set backspace=eol,start,indent
set whichwrap+=<,>,h,l

set ignorecase "Ignore case when searching
set smartcase

set hlsearch "Highlight search things

set incsearch "Make search act like search in modern browsers
set nolazyredraw "Don't redraw while executing macros

set magic "Set magic on, for regular expressions

set showmatch "Show matching bracets when text indicator is over them
set mat=2 "How many tenths of a second to blink

" No sound on errors
set noerrorbells
set novisualbell
set t_vb=
set tm=500


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Colors and Fonts
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
syntax enable "Enable syntax hl

" Set font according to system
if MySys() == "mac"
set gfn=Menlo:h14
set shell=/bin/bash
elseif MySys() == "windows"
set gfn=Bitstream\ Vera\ Sans\ Mono:h10
elseif MySys() == "linux"
set gfn=Monospace\ 10
set shell=/bin/bash
endif

if has("gui_running")
set guioptions-=T
set t_Co=256
set background=dark
colorscheme peaksea
set nonu
else
colorscheme zellner
set background=dark

set nonu
endif

set encoding=utf8
try
lang en_US
catch
endtry

set ffs=unix,dos,mac "Default file types


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Files, backups and undo
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Turn backup off, since most stuff is in SVN, git anyway...
set nobackup
set nowb
set noswapfile

"Persistent undo
try
if MySys() == "windows"
set undodir=C:\Windows\Temp
else
set undodir=~/.vim_runtime/undodir
endif

set undofile
catch
endtry


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Text, tab and indent related
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set expandtab
set shiftwidth=4
set tabstop=4
set smarttab

set lbr
set tw=500

set ai "Auto indent
set si "Smart indet
set wrap "Wrap lines


""""""""""""""""""""""""""""""
" => Visual mode related
""""""""""""""""""""""""""""""
" Really useful!
" In visual mode when you press * or # to search for the current selection
vnoremap <silent> * :call VisualSearch('f')<CR>
vnoremap <silent> # :call VisualSearch('b')<CR>

" When you press gv you vimgrep after the selected text
vnoremap <silent> gv :call VisualSearch('gv')<CR>
map <leader>g :vimgrep // **/*.<left><left><left><left><left><left><left>


function! CmdLine(str)
exe "menu Foo.Bar :" . a:str
emenu Foo.Bar
unmenu Foo
endfunction

" From an idea by Michael Naumann
function! VisualSearch(direction) range
let l:saved_reg = @"
execute "normal! vgvy"

let l:pattern = escape(@", '\\/.*$^~[]')
let l:pattern = substitute(l:pattern, "\n$", "", "")

if a:direction == 'b'
execute "normal ?" . l:pattern . "^M"
elseif a:direction == 'gv'
call CmdLine("vimgrep " . '/'. l:pattern . '/' . ' **/*.')
elseif a:direction == 'f'
execute "normal /" . l:pattern . "^M"
endif

let @/ = l:pattern
let @" = l:saved_reg
endfunction



"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Command mode related
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Smart mappings on the command line
cno $h e ~/
cno $d e ~/Desktop/
cno $j e ./
cno $c e <C-\>eCurrentFileDir("e")<cr>

" $q is super useful when browsing on the command line
cno $q <C-\>eDeleteTillSlash()<cr>

" Bash like keys for the command line
cnoremap <C-A> <Home>
cnoremap <C-E> <End>
cnoremap <C-K> <C-U>

cnoremap <C-P> <Up>
cnoremap <C-N> <Down>

" Useful on some European keyboards
map ½ $
imap ½ $
vmap ½ $
cmap ½ $


func! Cwd()
let cwd = getcwd()
return "e " . cwd
endfunc

func! DeleteTillSlash()
let g:cmd = getcmdline()
if MySys() == "linux" || MySys() == "mac"
let g:cmd_edited = substitute(g:cmd, "\\(.*\[/\]\\).*", "\\1", "")
else
let g:cmd_edited = substitute(g:cmd, "\\(.*\[\\\\]\\).*", "\\1", "")
endif
if g:cmd == g:cmd_edited
if MySys() == "linux" || MySys() == "mac"
let g:cmd_edited = substitute(g:cmd, "\\(.*\[/\]\\).*/", "\\1", "")
else
let g:cmd_edited = substitute(g:cmd, "\\(.*\[\\\\\]\\).*\[\\\\\]", "\\1", "")
endif
endif
return g:cmd_edited
endfunc

func! CurrentFileDir(cmd)
return a:cmd . " " . expand("%:p:h") . "/"
endfunc


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Moving around, tabs and buffers
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Map space to / (search) and c-space to ? (backgwards search)
map <space> /
map <c-space> ?
map <silent> <leader><cr> :noh<cr>

" Smart way to move btw. windows
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l

" Close the current buffer
map <leader>bd :Bclose<cr>

" Close all the buffers
map <leader>ba :1,300 bd!<cr>

" Use the arrows to something usefull
map <right> :bn<cr>
map <left> :bp<cr>

" Tab configuration
map <leader>tn :tabnew<cr>
map <leader>te :tabedit
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove

" When pressing <leader>cd switch to the directory of the open buffer
map <leader>cd :cd %:p:h<cr>


command! Bclose call <SID>BufcloseCloseIt()
function! <SID>BufcloseCloseIt()
let l:currentBufNum = bufnr("%")
let l:alternateBufNum = bufnr("#")

if buflisted(l:alternateBufNum)
buffer #
else
bnext
endif

if bufnr("%") == l:currentBufNum
new
endif

if buflisted(l:currentBufNum)
execute("bdelete! ".l:currentBufNum)
endif
endfunction

" Specify the behavior when switching between buffers
try
set switchbuf=usetab
set stal=2
catch
endtry


""""""""""""""""""""""""""""""
" => Statusline
""""""""""""""""""""""""""""""
" Always hide the statusline
set laststatus=2

" Format the statusline
set statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{CurDir()}%h\ \ \ Line:\ %l/%L:%c


function! CurDir()
let curdir = substitute(getcwd(), '/Users/amir/', "~/", "g")
return curdir
endfunction

function! HasPaste()
if &paste
return 'PASTE MODE '
else
return ''
endif
endfunction


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Parenthesis/bracket expanding
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
vnoremap $1 <esc>`>a)<esc>`<i(<esc>
vnoremap $2 <esc>`>a]<esc>`<i[<esc>
vnoremap $3 <esc>`>a}<esc>`<i{<esc>
vnoremap $$ <esc>`>a"<esc>`<i"<esc>
vnoremap $q <esc>`>a'<esc>`<i'<esc>
vnoremap $e <esc>`>a"<esc>`<i"<esc>

" Map auto complete of (, ", ', [
inoremap $1 ()<esc>i
inoremap $2 []<esc>i
inoremap $3 {}<esc>i
inoremap $4 {<esc>o}<esc>O
inoremap $q ''<esc>i
inoremap $e ""<esc>i
inoremap $t <><esc>i


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => General Abbrevs
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
iab xdate <c-r>=strftime("%d/%m/%y %H:%M:%S")<cr>


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Editing mappings
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Remap VIM 0
map 0 ^

"Move a line of text using ALT+[jk] or Comamnd+[jk] on mac
nmap <M-j> mz:m+<cr>`z
nmap <M-k> mz:m-2<cr>`z
vmap <M-j> :m'>+<cr>`<my`>mzgv`yo`z
vmap <M-k> :m'<-2<cr>`>my`<mzgv`yo`z

if MySys() == "mac"
nmap <D-j> <M-j>
nmap <D-k> <M-k>
vmap <D-j> <M-j>
vmap <D-k> <M-k>
endif

"Delete trailing white space, useful for Python ;)
func! DeleteTrailingWS()
exe "normal mz"
%s/\s\+$//ge
exe "normal `z"
endfunc
autocmd BufWrite *.py :call DeleteTrailingWS()

set guitablabel=%t


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Cope
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Do :help cope if you are unsure what cope is. It's super useful!
map <leader>cc :botright cope<cr>
map <leader>n :cn<cr>
map <leader>p :cp<cr>


""""""""""""""""""""""""""""""
" => bufExplorer plugin
""""""""""""""""""""""""""""""
let g:bufExplorerDefaultHelp=0
let g:bufExplorerShowRelativePath=1
map <leader>o :BufExplorer<cr>


""""""""""""""""""""""""""""""
" => Minibuffer plugin
""""""""""""""""""""""""""""""
let g:miniBufExplModSelTarget = 1
let g:miniBufExplorerMoreThanOne = 2
let g:miniBufExplModSelTarget = 0
let g:miniBufExplUseSingleClick = 1
let g:miniBufExplMapWindowNavVim = 1
let g:miniBufExplVSplit = 25
let g:miniBufExplSplitBelow=1

let g:bufExplorerSortBy = "name"

autocmd BufRead,BufNew :call UMiniBufExplorer

map <leader>u :TMiniBufExplorer<cr>


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Omni complete functions
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
autocmd FileType css set omnifunc=csscomplete#CompleteCSS


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Spell checking
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Pressing ,ss will toggle and untoggle spell checking
map <leader>ss :setlocal spell!<cr>

"Shortcuts using <leader>
map <leader>sn ]s
map <leader>sp [s
map <leader>sa zg
map <leader>s? z=


""""""""""""""""""""""""""""""
" => Python section
""""""""""""""""""""""""""""""
let python_highlight_all = 1
au FileType python syn keyword pythonDecorator True None False self

au BufNewFile,BufRead *.jinja set syntax=htmljinja
au BufNewFile,BufRead *.mako set ft=mako

au FileType python inoremap <buffer> $r return
au FileType python inoremap <buffer> $i import
au FileType python inoremap <buffer> $p print
au FileType python inoremap <buffer> $f #--- PH ----------------------------------------------<esc>FP2xi
au FileType python map <buffer> <leader>1 /class
au FileType python map <buffer> <leader>2 /def
au FileType python map <buffer> <leader>C ?class
au FileType python map <buffer> <leader>D ?def


""""""""""""""""""""""""""""""
" => JavaScript section
"""""""""""""""""""""""""""""""
au FileType javascript call JavaScriptFold()
au FileType javascript setl fen
au FileType javascript setl nocindent

au FileType javascript imap <c-t> AJS.log();<esc>hi
au FileType javascript imap <c-a> alert();<esc>hi

au FileType javascript inoremap <buffer> $r return
au FileType javascript inoremap <buffer> $f //--- PH ----------------------------------------------<esc>FP2xi

function! JavaScriptFold()
setl foldmethod=syntax
setl foldlevelstart=1
syn region foldBraces start=/{/ end=/}/ transparent fold keepend extend

function! FoldText()
return substitute(getline(v:foldstart), '{.*', '{...}', '')
endfunction
setl foldtext=FoldText()
endfunction


""""""""""""""""""""""""""""""
" => MRU plugin
""""""""""""""""""""""""""""""
let MRU_Max_Entries = 400
map <leader>f :MRU<CR>


""""""""""""""""""""""""""""""
" => Command-T
""""""""""""""""""""""""""""""
let g:CommandTMaxHeight = 15
set wildignore+=*.o,*.obj,.git,*.pyc
noremap <leader>j :CommandT<cr>
noremap <leader>y :CommandTFlush<cr>


""""""""""""""""""""""""""""""
" => Vim grep
""""""""""""""""""""""""""""""
let Grep_Skip_Dirs = 'RCS CVS SCCS .svn generated'
set grepprg=/bin/grep\ -nH



"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => MISC
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Remove the Windows ^M - when the encodings gets messed up
noremap <Leader>m mmHmt:%s/<C-V><cr>//ge<cr>'tzt'm

"Quickly open a buffer for scripbble
map <leader>q :e ~/buffer<cr>
au BufRead,BufNewFile ~/buffer iab <buffer> xh1 ===========================================

map <leader>pp :setlocal paste!<cr>

map <leader>bb :cd ..<cr>

Reference
http://amix.dk/vim/vimrc.html

how to save the output of a program while seeing it on the screen?

0. putty's log file.

1.可以用 tee , 就是管線的T型頭,分流用的.看看底下的說明.

http://en.wikipedia.org/wiki/Tee_(command)

這樣就能紀錄某一指令的輸出到指定檔案,又能在螢幕上看到.

2.直接先打一個指令叫 script. 系統會先show

Script started, file is typescript

接下來就繼續操作.....
要結束時輸入exit, 或是ctrl-d,然後系統會出現:

Script done, file is typescript

typescript裡面的內容,前面還有紀錄起始時間,後面有紀錄結束時間.這樣就
很方便紀錄.

也可以使用 script -a logfile 的方式來指定紀錄檔,

另外 script有一個搭配的指令, scriptreplay.
參考這裡:
http://www.linuxinsight.com/replayi...riptreplay.html

這樣你就可以把這些紀錄重新跑一遍.這樣就很方便移到別的機器使用,或是重新安裝時,就再讓它跑一次就好啦~~~
-----------------------------------------------
額外補充:
mysqlclient 也有一個參數叫 tee 也可以紀錄.

Disk Data Recovery Tools

[] DiskGenius - helps you restore files that are deleted by mistake, lost without reason, partition reformatted, system crashes, virus attack, partition failure...; Recovering lost partitions by rebuilding MBR, rebuilding partition table; and what's more it is a useful tool to manage disk partitions and it can backup partitions.

// 好像評價不錯?

[] R-Studio - is a family of powerful and cost-effective undelete and data recovery software. Empowered by the new unique data recovery technologies, it is the most comprehensive data recovery solution for recovery files from FAT12/16/32/exFAT, NTFS, NTFS5 (created or updated by Windows 2000/XP/2003/Vista/2008/Win7), HFS/HFS+ (Macintosh), Little and Big Endian variants of UFS1/UFS2 (FreeBSD/OpenBSD/NetBSD/Solaris) and Ext2/Ext3/Ext4 FS (Linux) partitions. It functions on local and network disks, even if such partitions are formatted, damaged or deleted. Flexible parameter settings give you absolute control over data recovery.

// 重量級

[] testdsik - is powerful free data recovery software! It was primarily designed to help recover lost partitions and/or make non-booting disks bootable again when these symptoms are caused by faulty software, certain types of viruses or human error (such as accidentally deleting a Partition Table). Partition table recovery using TestDisk is really easy.

How do you reload your .vimrc file without restarting vim?

How do you reload your .vimrc file without restarting vim?

If you're editing it, you can reload it with:

:so %

Note: % stands for current file name

Note: :so is short for :source which reads the content of the specified file and treats it as Vim code.

Or specify the file path:
:so $MYVIMRC

Use spaces instead of tab in PHP files

Add following line to /usr/local/share/vim/vim73/syntax/php.vim
# vim /usr/local/share/vim/vim73/syntax/php.vim
set ts=2 sts=2 sw=2 expandtab

// ts: tabstop
// sts: softtabstop
// sw: shiftwidth

How to disable the highlighting of parenthesis matching brace bracket

How to disable the highlighting of parenthesis matching brace bracket

The reason why the matching parenthesis / braces / brackets are highlighted is becuase there is a plugin called /usr/local/share/vim/vim73/plugin/matchparen.vim.

You can press % to jump to the matching parenthesis / braces / brackets.

To disable the highlight:

Method 1:
Put this line in your ~/.vimrc:
let loaded_matchparen = 1

Method 2:
run this command in vim:
:NoMatchParen

NoMatchParen is a command to the loaded plugin to ask it to stop matching.
Setting "loaded_matchparen", on the other hand, stops the plugin from
ever loading (by making it think that it's already running).

Saturday, March 5, 2011

Run a Virtual Machine on Mac OS X

- VMware Fusion
- Parallels Desktop
- Sun VirtualBox (which is free)

How to paste in a new line with vim?

I often have to paste some stuff on a new line in vim. What I usually do is:

o<esc>p

Which inserts a new line and puts me in insertion mode, than quits insertion mode, and finally pastes.

Three keystrokes. Not very efficient. Any better ideas?

Solution 0:
You can paste a buffer in insert mode using <C-R> followed by the name of the buffer top paste. The default buffer is ", so you would do

o<C-R>"

I found that I use <C-R>" very often and bound that to <C-F> in my vimrc:

inoremap <C-F> <C-R>"

Solution 1:
Use yy to yank the whole line (including the end of line character). p will then paste the line on a new line after the current one and P (Shift-P) will paste above the current line.

Solution 2:
Make a mapping: then it's only one or two keys:

:nmap ,p o<ESC>p
:nmap <F4> o<ESC>p

Solution 3:
The function version of the mapping (unnecessary really, but just for completeness):

:nmap <F4> :call append(line('.'), @")<CR>

" This one may be a little better (strip the ending new-line before pasting)
:nmap <F4> :call append(line('.'), substitute(@", '\n$', '', ''))<CR>

:help let-register
:help :call
:help append()
:help line()
:help nmap

Reference:
http://stackoverflow.com/questions/1346737/how-to-paste-in-a-new-line-with-vim

Friday, March 4, 2011

How to move windows tabs in GNU Screen?

How to move windows tabs in GNU Screen?

Type following command in screen:

^a:number 0

Explanation:
^a // the host key for screen
:number // typed literally. The command.
0 // the position to move the current screen to.

Kill all processes owned by a certain user

Kill all processes owned by a certain user

View processes to be killed first:
# ps ax -o user,pid,command | grep 'TheUserName'

Confirm to kill:
# ps ax -o user,pid | grep 'TheUserName' | awk '{print $2}' | xargs -I {} kill {}

PHP automatically print files on windows

<?php
// Method 1:
exec('print /d:\\\\192.168.0.11\\HP3050 c:\\test.html');

// Method 2:
exec('start /min notepad /P c:\\test.txt');
?>

Wednesday, March 2, 2011

How to watch network interface bandwidth usage on FreeBSD?

How to watch network interface bandwidth usage on FreeBSD?

# systat -ifstat 1

or

# netstat -I interface_name seconds
# netstat -I re0 1

Reference:
http://www.mostlygeek.com/tech/how-to-watch-network-interface-bandwidth-usage-on-freebsd/