From ba2c7d83cb482ce8b9d8703594ba65d811716c40 Mon Sep 17 00:00:00 2001 From: Kolan Sh Date: Fri, 18 May 2012 15:06:11 +0400 Subject: [PATCH] Initial commit for desktop branch --- .Xdefaults | 2 + .config/LyX/lyx.conf | 44 + .config/geany/geany.conf | 192 ++ .config/geany/keybindings.conf | 245 +++ .fonts/lucon.ttf | Bin 0 -> 115068 bytes .gqview/gqviewrc | 243 +++ .urxvt/Xdefaults | 109 + .urxvt/perl/tabbedex | 635 ++++++ .vim/plugin/VimExplorer.vim | 3538 ++++++++++++++++++++++++++++++++ .vim/plugin/cscope_maps.vim | 165 ++ .xinitrc | 21 + .xprofile | 1 + .xscreensaver | 257 +++ 13 files changed, 5452 insertions(+) create mode 100644 .Xdefaults create mode 100644 .config/LyX/lyx.conf create mode 100644 .config/geany/geany.conf create mode 100644 .config/geany/keybindings.conf create mode 100644 .fonts/lucon.ttf create mode 100644 .gqview/gqviewrc create mode 100644 .urxvt/Xdefaults create mode 100644 .urxvt/perl/tabbedex create mode 100644 .vim/plugin/VimExplorer.vim create mode 100644 .vim/plugin/cscope_maps.vim create mode 100644 .xinitrc create mode 100644 .xprofile create mode 100644 .xscreensaver diff --git a/.Xdefaults b/.Xdefaults new file mode 100644 index 0000000..e7c7b3a --- /dev/null +++ b/.Xdefaults @@ -0,0 +1,2 @@ +#include ".fonts/Xdefaults" +#include ".urxvt/Xdefaults" \ No newline at end of file diff --git a/.config/LyX/lyx.conf b/.config/LyX/lyx.conf new file mode 100644 index 0000000..d5c7fd4 --- /dev/null +++ b/.config/LyX/lyx.conf @@ -0,0 +1,44 @@ +[ui_files] +0=/usr/share/lyx/ui/default.ui +0\date=@Variant(\0\0\0\x10\0%x\xcd\x3j_\xd8\x1) + +[views] +0\pos=@Point(3 30) +0\size=@Size(1672 998) +0\layout=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x2\0\0\0\0\0\0\0\0\0\0\0\0\xfc\x2\0\0\0\x1\xfb\0\0\0\x6\0t\0o\0\x63\0\0\0\0\0\xff\xff\xff\xff\0\0\x1[\0\xff\xff\xff\0\0\0\x3\0\0\0\0\0\0\0\0\xfc\x1\0\0\0\x1\xfb\0\0\0\x16\0v\0i\0\x65\0w\0-\0s\0o\0u\0r\0\x63\0\x65\0\0\0\0\0\xff\xff\xff\xff\0\0\x1\xb6\0\xff\xff\xff\0\0\x6\x88\0\0\x3\xa0\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x1d\0\0\0\x2\0\0\0\x3\0\0\0\x10\0s\0t\0\x61\0n\0\x64\0\x61\0r\0\x64\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\n\0\x65\0x\0t\0r\0\x61\x1\0\0\x2s\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x16\0v\0i\0\x65\0w\0/\0u\0p\0\x64\0\x61\0t\0\x65\x1\0\0\x4\xfb\0\0\0P\0\0\0\0\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\x1\0\0\0\f\0r\0\x65\0v\0i\0\x65\0w\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x2\0\0\0\0\0\0\0\x2\0\0\0\x1\0\0\0\x6\0v\0\x63\0s\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\n\0t\0\x61\0\x62\0l\0\x65\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\b\0m\0\x61\0t\0h\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\"\0m\0\x61\0t\0h\0m\0\x61\0\x63\0r\0o\0t\0\x65\0m\0p\0l\0\x61\0t\0\x65\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x14\0m\0i\0n\0i\0\x62\0u\0\x66\0\x66\0\x65\0r\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x16\0m\0\x61\0t\0h\0_\0p\0\x61\0n\0\x65\0l\0s\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x12\0\x66\0u\0n\0\x63\0t\0i\0o\0n\0s\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\n\0s\0p\0\x61\0\x63\0\x65\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x16\0s\0q\0r\0t\0-\0s\0q\0u\0\x61\0r\0\x65\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\n\0s\0t\0y\0l\0\x65\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x16\0\x66\0r\0\x61\0\x63\0-\0s\0q\0u\0\x61\0r\0\x65\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\b\0\x66\0o\0n\0t\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x14\0l\0\x61\0t\0\x65\0x\0_\0\x64\0o\0t\0s\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x14\0l\0\x61\0t\0\x65\0x\0_\0\x64\0\x65\0\x63\0o\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x16\0l\0\x61\0t\0\x65\0x\0_\0\x61\0r\0r\0o\0w\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x12\0l\0\x61\0t\0\x65\0x\0_\0\x62\0o\0p\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x14\0l\0\x61\0t\0\x65\0x\0_\0\x62\0r\0\x65\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x16\0l\0\x61\0t\0\x65\0x\0_\0g\0r\0\x65\0\x65\0k\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x14\0l\0\x61\0t\0\x65\0x\0_\0m\0i\0s\0\x63\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x16\0l\0\x61\0t\0\x65\0x\0_\0v\0\x61\0r\0s\0z\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x1c\0l\0\x61\0t\0\x65\0x\0_\0\x61\0m\0s\0_\0m\0i\0s\0\x63\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0 \0l\0\x61\0t\0\x65\0x\0_\0\x61\0m\0s\0_\0\x61\0r\0r\0o\0w\0s\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x1a\0l\0\x61\0t\0\x65\0x\0_\0\x61\0m\0s\0_\0r\0\x65\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x1c\0l\0\x61\0t\0\x65\0x\0_\0\x61\0m\0s\0_\0n\0r\0\x65\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x3\0\0\0\x1\0\0\0\x1a\0l\0\x61\0t\0\x65\0x\0_\0\x61\0m\0s\0_\0o\0p\0s\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0) +0\icon_size=@Size(14 14) +0\extra\visibility=5 +0\font\visibility=10 +0\frac-square\visibility=10 +0\functions\visibility=10 +0\latex_ams_arrows\visibility=10 +0\latex_ams_misc\visibility=10 +0\latex_ams_nrel\visibility=10 +0\latex_ams_ops\visibility=10 +0\latex_ams_rel\visibility=10 +0\latex_arrow\visibility=10 +0\latex_bop\visibility=10 +0\latex_brel\visibility=10 +0\latex_deco\visibility=10 +0\latex_dots\visibility=10 +0\latex_greek\visibility=10 +0\latex_misc\visibility=10 +0\latex_varsz\visibility=10 +0\math\visibility=200 +0\math_panels\visibility=200 +0\mathmacrotemplate\visibility=1096 +0\minibuffer\visibility=10 +0\review\visibility=580 +0\space\visibility=10 +0\sqrt-square\visibility=10 +0\standard\visibility=5 +0\style\visibility=10 +0\table\visibility=328 +0\vcs\visibility=6 +0\view\update\visibility=5 +0\aboutlyx\geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\x1\x2\0\0\0\xaa\0\0\x2J\0\0\x1\xd6\0\0\x1\x3\0\0\0\xbc\0\0\x2I\0\0\x1\xd5\0\0\0\0\0\0) +0\prefs\geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\xdd\0\0\0\x17\0\0\x3\xc7\0\0\x1\xf8\0\0\0\xde\0\0\0)\0\0\x3\xc6\0\0\x1\xf7\0\0\0\0\0\0) +0\toc\geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\0\xcf\0\0\x1Z\0\0\0\0\0\0\0\0\0\0\0\xcf\0\0\x1Z\0\0\0\0\0\0) +0\view-source\geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\0\0\0\0\0\0\0\0\x1\xb5\0\0\0[\0\0\0\0\0\0\0\0\0\0\x1\xb5\0\0\0[\0\0\0\0\0\0) +0\view-source\fullsource=false +0\view-source\autoupdate=true diff --git a/.config/geany/geany.conf b/.config/geany/geany.conf new file mode 100644 index 0000000..29341a2 --- /dev/null +++ b/.config/geany/geany.conf @@ -0,0 +1,192 @@ + +[geany] +default_open_path=/home/kolan +cmdline_new_files=true +notebook_double_click_hides_widgets=false +tab_pos_sidebar=2 +highlighting_invert_all=false +pref_main_suppress_search_dialogs=false +pref_main_search_use_current_word=true +check_detect_indent=false +use_tab_to_indent=true +pref_editor_tab_width=8 +indent_hard_tab_width=8 +indent_mode=2 +indent_type=1 +autocomplete_doc_words=false +completion_drops_rest_of_word=false +autocompletion_max_entries=30 +mru_length=10 +disk_check_timeout=30 +show_editor_scrollbars=true +brace_match_ltgt=false +use_gtk_word_boundaries=true +complete_snippets_whilst_editing=false +show_symbol_list_expanders=true +allow_always_save=false +use_safe_file_saving=false +documents_show_paths=true +sidebar_page=2 +pref_main_load_session=true +pref_main_project_session=true +pref_main_project_file_in_basedir=true +pref_main_save_winpos=true +pref_main_confirm_exit=false +pref_main_suppress_status_messages=false +switch_msgwin_pages=false +beep_on_errors=true +auto_focus=false +sidebar_symbol_visible=true +sidebar_openfiles_visible=true +editor_font=Liberation Mono 8 +tagbar_font=Sans 8 +msgwin_font=Sans 8 +show_notebook_tabs=true +show_tab_cross=true +tab_order_ltr=true +tab_pos_editor=2 +tab_pos_msgwin=0 +show_indent_guide=false +show_white_space=false +show_line_endings=false +show_markers_margin=true +show_linenumber_margin=true +long_line_type=0 +long_line_column=72 +long_line_color=#C2EBC2 +symbolcompletion_max_height=10 +symbolcompletion_min_chars=4 +use_folding=true +unfold_all_children=true +use_indicators=true +line_wrapping=true +auto_close_xml_tags=true +complete_snippets=true +auto_complete_symbols=true +pref_editor_disable_dnd=false +pref_editor_smart_home_key=true +pref_editor_newline_strip=true +line_break_column=72 +auto_continue_multiline=true +comment_toggle_mark=~ +scroll_stop_at_last_line=true +autoclose_chars=31 +pref_editor_default_new_encoding=UTF-8 +pref_editor_default_open_encoding=WINDOWS-1251 +default_eol_character=2 +pref_editor_new_line=true +pref_editor_replace_tabs=false +pref_editor_trail_space=true +pref_toolbar_show=true +pref_toolbar_append_to_menu=false +pref_toolbar_icon_style=0 +pref_toolbar_icon_size=0 +pref_template_developer=Kolan Sh. +pref_template_company=InSys Ltd +pref_template_mail=mecareful@gmail.com +pref_template_initial=SNS +pref_template_version=1.0 +pref_template_year=%Y +pref_template_date=%Y-%m-%d +pref_template_datetime=%d.%m.%Y %H:%M:%S %Z +context_action_cmd= +sidebar_visible=true +statusbar_visible=true +msgwindow_visible=true +fullscreen=false +scribble_text= +scribble_pos=0 +treeview_position=0 +msgwindow_position=687 +geometry=3;30;1672;968;0; +custom_date_format= +sidebar_pos=0 +virtualspace=1 +color_scheme= +compiler_tab_autoscroll=true +tab_order_beside=false +msgwin_status_visible=true +msgwin_compiler_visible=true +msgwin_messages_visible=true +msgwin_scribble_visible=true +use_native_windows_dialogs=false +long_line_enabled=true +pref_toolbar_use_gtk_default_style=false +pref_toolbar_use_gtk_default_icon=true +gio_unsafe_save_backup=false +find_selection_type=0 +statusbar_template= +new_document_after_close=false +pref_editor_ensure_convert_line_endings=false + +[search] +pref_search_current_file_dir=true +find_all_expanded=false +replace_all_expanded=true +fif_mode=0 +fif_extra_options= +fif_case_sensitive=true +fif_match_whole_word=false +fif_invert_results=false +fif_recursive=false +fif_use_extra_options=false +position_find_x=90 +position_find_y=386 +position_replace_x=800 +position_replace_y=464 +position_fif_x=1154 +position_fif_y=409 +fif_regexp=false +fif_files= +fif_use_files=false + +[plugins] +load_plugins=true +custom_plugin_path=/home/kolan/.geany/plugins +active_plugins=/usr/lib64/geany/codenav.so;/usr/lib64/geany/geanyextrasel.so;/usr/lib64/geany/geanylatex.so;/usr/lib64/geany/spellcheck.so;/usr/lib64/geany/treebrowser.so;/usr/lib64/geany/classbuilder.so;/usr/lib64/geany/saveactions.so;/usr/lib64/geany/addons.so;/usr/lib64/geany/splitwindow.so;/usr/lib64/geany/shiftcolumn.so;/usr/lib64/geany/htmlchars.so;/usr/lib64/geany/export.so; + +[tools] +make_cmd=make +term_cmd=urxvt +browser_cmd=firefox +grep_cmd=grep + +[printing] +print_cmd= +use_gtk_printing=true +print_line_numbers=true +print_page_numbers=true +print_page_header=true +page_header_basename=false +page_header_datefmt=%c + +[VTE] +load_vte=true +emulation=xterm +font=Terminus 10 +scroll_on_key=true +scroll_on_out=true +enable_bash_keys=false +ignore_menu_bar_accel=false +follow_path=true +run_in_vte=true +skip_run_script=false +cursor_blinks=true +scrollback_lines=500 +shell=/bin/bash +colour_fore=#FFFFFF +colour_back=#000000 +last_dir=/home/kolan/projects/dataserver +send_selection_unsafe=false + +[project] +session_file=/home/kolan/projects/dataserver/dataserver.geany +project_file_path=/home/kolan/projects + +[files] +recent_files=/home/kolan/projects/dataserver/netfuncs.h;/home/kolan/projects/dataserver/netfuncs.c;/home/kolan/projects/dataserver/mpool.h;/home/kolan/projects/dataserver/mpool.c;/home/kolan/projects/dataserver/xerror.c;/home/kolan/projects/dataserver/xerror.h;/home/kolan/projects/dataserver/xmalloc.h;/home/kolan/projects/dataserver/xmalloc.c;/home/kolan/dev/c/malloc_speed_test/pool_list.c;/home/kolan/projects/dataserver/dataserver.c; +recent_projects=/home/kolan/projects/dataserver/dataserver.geany;dataserver.geany;/home/kolan/Projects/cpp/sockets/sockets.geany;/home/kolan/Projects/cpp/multithreading/pthread_ex.geany;/home/kolan/Projects/c/tmp2/tmp2.geany;/home/kolan/Projects/c/tmp1/tmp1.geany;/home/kolan/Projects/CPP/hello/hello.geany;/home/kolan/Projects/CPP/multithreading/pthread_ex.geany;/home/kolan/Projects/C/hello/hello.geany; +current_page=0 +FILE_NAME_0=6788;C;0;16;1;1;1;/home/kolan/projects/dataserver/dataserver.c;0 +FILE_NAME_1=0;C;0;16;1;1;1;/home/kolan/projects/dataserver/dataserver.h;0 +FILE_NAME_2=0;C;0;16;1;1;1;/home/kolan/projects/dataserver/echo-client.c;0 diff --git a/.config/geany/keybindings.conf b/.config/geany/keybindings.conf new file mode 100644 index 0000000..3cc9eaa --- /dev/null +++ b/.config/geany/keybindings.conf @@ -0,0 +1,245 @@ +#Keybindings for Geany +#The format looks like "a" or "F1". +#But you can also change the keys in Geany's preferences dialog. + +[Bindings] +menu_new=n +menu_open=o +menu_open_selected=o +menu_save=s +menu_saveas= +menu_saveall=s +menu_print=p +menu_close=w +menu_closeall=w +menu_reloadfile=r +project_properties= +menu_undo=z +menu_redo=y +edit_deleteline=k +edit_duplicateline=d +edit_transposeline=t +edit_scrolltoline=l +edit_scrolllineup=Up +edit_scrolllinedown=Down +edit_completesnippet=Tab +edit_suppresssnippetcompletion= +move_snippetnextcursor= +popup_contextaction= +edit_autocomplete=space +edit_calltip=space +edit_macrolist=Return +edit_deletelinetoend=Delete +menu_cut=x +menu_copy=c +menu_paste=v +edit_cutline=x +edit_copyline=c +menu_selectall=a +edit_selectword=w +edit_selectline=l +edit_selectparagraph=p +edit_togglecase=u +edit_commentlinetoggle=e +edit_commentline= +edit_uncommentline= +edit_increaseindent=i +edit_decreaseindent=u +edit_increaseindentbyspace= +edit_decreaseindentbyspace= +edit_autoindent= +edit_sendtocmd1=1 +edit_sendtocmd2=2 +edit_sendtocmd3=3 +edit_sendtovte= +format_reflowparagraph=j +menu_insert_date=d +edit_insertwhitespace= +menu_preferences=p +menu_find=f +menu_findnext=g +menu_findprevious=g +menu_findinfiles=f +menu_replace=h +menu_findnextsel= +menu_findprevsel= +menu_nextmessage= +menu_previousmessage= +popup_findusage= +popup_finddocumentusage= +find_markall=m +nav_forward= +nav_back= +menu_gotoline=l +edit_gotolinestart=Home +edit_gotolineend=End +edit_gotomatchingbrace=b +edit_togglemarker=m +edit_gotonextmarker=period +edit_gotopreviousmarker=comma +edit_prevwordstart=slash +edit_nextwordstart=backslash +popup_gototagdefinition= +popup_gototagdeclaration= +edit_gotolineendvisual=End +menu_toggleall= +menu_fullscreen=F11 +menu_messagewindow= +toggle_sidebar= +menu_zoomin=plus +menu_zoomout=minus +switch_editor=F2 +switch_scribble=F6 +switch_vte=F4 +switch_search_bar=F7 +switch_sidebar= +switch_compiler= +switch_tableft=Page_Up +switch_tabright=Page_Down +switch_tablastused=Tab +move_tableft=Page_Up +move_tabright=Page_Down +move_tabfirst= +move_tablast= +menu_replacetabs= +menu_replacespaces= +menu_togglefold= +menu_foldall= +menu_unfoldall= +reloadtaglist=r +menu_linewrap= +menu_linebreak= +build_compile=F8 +build_link=F9 +build_make=F9 +build_makeowntarget=F9 +build_makeobject= +build_nexterror= +build_previouserror= +build_run=F5 +build_run2= +build_options= +menu_opencolorchooser= +menu_help=F1 + +file_openlasttab= +edit_wordpartcompletion=Tab +edit_movelineup= +edit_movelinedown= +edit_selectwordpartleft= +edit_selectwordpartright= +menu_pluginpreferences= +normal_size=0 +switch_messages= +switch_message_window= +switch_sidebar_doc_list= +switch_sidebar_symbol_list= +remove_markers= +remove_error_indicators= + +[file_browser] +focus_file_list= +focus_path_entry= + +[split_window] +split_horizontal= +split_vertical= +split_unsplit= + +[html_chars] +insert_html_chars= +replace_special_characters= +htmltoogle_toggle_plugin_status= + +[code_navigation] +switch_head_impl=s +goto_file=g + +[extra_select] +column_mode= +goto_line_extend= +brace_match_extend= + +[debug] +"_Load"= +"_Unload"= +"_Run"= +"_Kill"= +"_Pause"= +"_Continue"= +"_Step"= +"Step _Into"= +"_Next"= +"Ne_xt in"= +"Run _To"= +"Sta_ck"= +"_Break"= +"_Watches"= +"_Finish"= +"_Return"= +"En_vironment"= +"_Options"= + +[geanylatex] +run_latex_wizard= +insert_latex_label= +insert_latex_ref= +insert_new_line= +latex_toggle_status= +latex_insert_environment= +latex_insert_item= +latex_replace_chars= +format_bold= +format_italic= +format_typewriter= +format_center= +format_left= +format_right= +insert_description_list= +insert_itemize_list= +insert_enumerate_list= +structure_lvl_up= +structure_lvl_down= +usepackage_dialog= +latex_insert_command= + +[geanylipsum] +insert_lipsum= + +[sendmail] +send_file_as_attachment= + +[geanyvc] +vc_show_diff_of_file= +vc_show_diff_of_dir= +vc_show_diff_of_basedir= +vc_commit= +vc_status= +vc_update= +vc_revert_file= +vc_revert_dir= +vc_revert_basedir= + +[insert_numbers] +insert_numbers= + +[spellcheck] +spell_check= +spell_toggle_typing= + +[prettyprinter] +run_pretty_printer_xml= + +[doc_chars] +Документация на слово под курсором= +Document interactive= + +[addons] +focus_bookmark_list= +focus_tasks= +update_tasks= +xml_tagging= + +[shiftcolumn] +shift_left=9 +shift_right=0 diff --git a/.fonts/lucon.ttf b/.fonts/lucon.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2885d7e1e058b29c07189dfa9d40e856e2a4d581 GIT binary patch literal 115068 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

SjH{&^5Tv$>VS-`F*p1o#wTrVJLm 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. +# +## +## Tabbed plugin for rxvt-unicode +## Modified by Michal Nazarewicz (mina86/AT/mina86.com), StephenB +## (mail4stb/AT/gmail.com) and Steven Merrill +## +## +## The following has been added: +## +## 1. Depending on time of last activity, activity character differs. +## By default, after 4 seconds an asterisk becomes a plus sing, +## after next 4 it becomes a colon, and finally, after another 8 +## seconds it becomes a dot. This can be configured via +## tabbar-timeouts resource. It's format is: +## +## ( ":" ":" )* ":" ":" +## +## where is timeout in seconds and is +## a single activity character. +## +## 2. The "[NEW]" button can be disabled (who on Earth uses mouse to +## create new tab anyways?) by setting new-button resource to yes. +## +## 3. If title resource is true, tab's title is displayed after last +## button. This is handy if you have terminal with no window +## decorations. Colours can be configured via title-fg and +## title-bg. +## +## 4. Incorporated Alexey Semenko patch adding +## autohide resource. If it's true tab bar is hidden if there is +## no more then one tab opened. +## +## 5. Tabs are indexed in starting with zero hex. :] If you're such +## a geek to use urxvt it shouldn't be a problem for you and it +## saves few character when many tabs are opened. +## +## 6. As a minor modification: Final pipe character is removed (unless +## title is displayed). This make tab bar look nicer. +## +## Added by StephenB: +## +## 7. Tabs can be named with Shift+Up (Enter to confirm, Escape to +## cancel). +## +## 8. "[NEW]" button disabled by default. +## +## Added by Steven Merrill +## +## 9. Ability to start a new tab or cycle through tabs via user +## commands: tabbedex:(new|next|prev)_tab . +## e.g. (in .Xdefaults) URxvt.keysym.M-t: perl:tabbedex:new_tab +## (see the urxvt man file for more info about keysym) +## +## 10. Fix an issue whereby on_user_command would not properly get sent +## to other extension packages if the mouse was not over the urxvt +## window. +## + + +sub update_autohide { + my ($self, $reconfigure) = @_; + my $oldh = $self->{tabheight}; + if ($self->{autohide} && @{ $self->{tabs} } <= 1 && + ! (@{ $self->{tabs} } == 1 && $self->{tabs}[-1]->{name})) { + $self->{tabheight} = 0; + } else { + $self->{tabheight} = $self->{maxtabheight}; + } + if ($reconfigure && $self->{tabheight} != $oldh) { + $self->configure; + $self->copy_properties; + } +} + + +sub tab_activity_mark ($$) { + my ($self, $tab) = @_; + return ' ' unless defined $tab->{lastActivity}; + return ' ' if $tab == $self->{cur}; + if (defined $self->{timeouts}) { + my $diff = int urxvt::NOW - $tab->{lastActivity}; + for my $spec (@{ $self->{timeouts} }) { + return $spec->[1] if $diff > $spec->[0]; + } + } + '*'; +} + + +sub refresh { + my ($self) = @_; + + # autohide makes it zero + return unless $self->{tabheight}; + + my $ncol = $self->ncol; + + my $text = " " x $ncol; + my $rend = [($self->{rs_tabbar}) x $ncol]; + + my ($ofs, $idx, @ofs) = (0, 0); + + if ($self->{new_button}) { + substr $text, 0, 7, "[NEW] |"; + @$rend[0 .. 5] = ($self->{rs_tab}) x 6; + push @ofs, [0, 6, -1 ]; + $ofs = 7; + } + + for my $tab (@{ $self->{tabs} }) { + my $name = $tab->{name} ? $tab->{name} : $idx; + my $act = $self->tab_activity_mark($tab); + my $txt = sprintf "%s%s%s", $act, $name, $act; + my $len = length $txt; + + substr $text, $ofs, $len + 1, "$txt|"; + @$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab}) x $len + if $tab == $self->{cur}; + + push @ofs, [ $ofs, $ofs + $len, $idx ]; + ++$idx; + $ofs += $len + 1; + } + + substr $text, --$ofs, 1, ' '; # remove last '|' + + if ($self->{tab_title} && $ofs + 3 < $ncol) { + my $term = $self->{term}; + my @str = $term->XGetWindowProperty($term->parent, $self->{tab_title}); + if (@str && $str[2]) { + my $str = '| ' . $str[2]; + my $len = length $str; + $len = $ncol - $ofs if $ofs + $len > $ncol; + substr $text, $ofs, $len, substr $str, 0, $len; + @$rend[$ofs + 2 .. $ofs + $len - 1] = ($self->{rs_title}) x ($len - 2); + } + } + + $self->{tabofs} = \@ofs; + + $self->ROW_t (0, $text, 0, 0, $ncol); + $self->ROW_r (0, $rend, 0, 0, $ncol); + + $self->want_refresh; +} + + +sub new_tab { + my ($self, @argv) = @_; + + my $offset = $self->fheight; + + $self->{tabheight} = $self->{maxtabheight} + unless $self->{autohide} && !(defined $self->{tabs} && @{ $self->{tabs} }); + + # save a backlink to us, make sure tabbedex is inactive + push @urxvt::TERM_INIT, sub { + my ($term) = @_; + $term->{parent} = $self; + + for (0 .. urxvt::NUM_RESOURCES - 1) { + my $value = $self->{resource}[$_]; + + $term->resource ("+$_" => $value) + if defined $value; + } + + $term->resource (perl_ext_2 => $term->resource ("perl_ext_2") . ",-tabbedex"); + }; + + push @urxvt::TERM_EXT, urxvt::ext::tabbedex::tab::; + + my $term = new urxvt::term + $self->env, $urxvt::RXVTNAME, + -embed => $self->parent, + @argv; +} + + +sub configure { + my ($self) = @_; + + my $tab = $self->{cur}; + + # this is an extremely dirty way to force a configurenotify, but who cares + $tab->XMoveResizeWindow ( + $tab->parent, + 0, $self->{tabheight} + 1, + $self->width, $self->height - $self->{tabheight} + ); + $tab->XMoveResizeWindow ( + $tab->parent, + 0, $self->{tabheight}, + $self->width, $self->height - $self->{tabheight} + ); +} + + +sub copy_properties { + my ($self) = @_; + my $tab = $self->{cur}; + + my $wm_normal_hints = $self->XInternAtom ("WM_NORMAL_HINTS"); + + my $current = delete $self->{current_properties}; + + # pass 1: copy over properties different or nonexisting + for my $atom ($tab->XListProperties ($tab->parent)) { + my ($type, $format, $items) = $self->XGetWindowProperty ($tab->parent, $atom); + + # fix up size hints + if ($atom == $wm_normal_hints) { + my (@hints) = unpack "l!*", $items; + + $hints[$_] += $self->{tabheight} for (4, 6, 16); + + $items = pack "l!*", @hints; + } + + my $cur = delete $current->{$atom}; + + # update if changed, we assume empty items and zero type and format will not happen + $self->XChangeProperty ($self->parent, $atom, $type, $format, $items) + if $cur->[0] != $type or $cur->[1] != $format or $cur->[2] ne $items; + + $self->{current_properties}{$atom} = [$type, $format, $items]; + } + + # pass 2, delete all extraneous properties + $self->XDeleteProperty ($self->parent, $_) for keys %$current; +} + + +sub make_current { + my ($self, $tab) = @_; + + if (my $cur = $self->{cur}) { + delete $cur->{lastActivity}; + $cur->XUnmapWindow ($cur->parent) if $cur->mapped; + $cur->focus_out; + } + + $self->{cur} = $tab; + + $self->configure; + $self->copy_properties; + + $tab->focus_out; # just in case, should be a nop + $tab->focus_in if $self->focus; + + $tab->XMapWindow ($tab->parent); + delete $tab->{lastActivity}; + $self->refresh; + + (); +} + + +sub on_focus_in { + my ($self, $event) = @_; + $self->{cur}->focus_in; + (); +} + +sub on_focus_out { + my ($self, $event) = @_; + $self->{cur}->focus_out; + (); +} + +sub on_key_press { + my ($self, $event) = @_; + $self->{cur}->key_press ($event->{state}, $event->{keycode}, $event->{time}); + 1; +} + +sub on_key_release { + my ($self, $event) = @_; + $self->{cur}->key_release ($event->{state}, $event->{keycode}, $event->{time}); + 1; +} + +sub on_button_release { + my ($self, $event) = @_; + + if ($event->{row} == 0) { + my $col = $event->{col}; + for my $button (@{ $self->{tabofs} }) { + last if $col < $button->[0]; + next unless $col <= $button->[1]; + if ($button->[2] == -1) { + $self->new_tab; + } else { + $self->make_current($self->{tabs}[$button->[2]]); + } + } + return 1; + } + + (); +} + +sub on_init { + my ($self) = @_; + + $self->{resource} = [map $self->resource ("+$_"), 0 .. urxvt::NUM_RESOURCES - 1]; + + $self->resource (int_bwidth => 0); + $self->resource (name => "URxvt.tabbed"); + $self->resource (pty_fd => -1); + + $self->option ($urxvt::OPTION{scrollBar}, 0); + + my $fg = $self->x_resource ("tabbar-fg"); + my $bg = $self->x_resource ("tabbar-bg"); + my $tabfg = $self->x_resource ("tab-fg"); + my $tabbg = $self->x_resource ("tab-bg"); + my $titfg = $self->x_resource ("title-fg"); + my $titbg = $self->x_resource ("title-bg"); + + defined $fg or $fg = 3; + defined $bg or $bg = 0; + defined $tabfg or $tabfg = 0; + defined $tabbg or $tabbg = 1; + defined $titfg or $titfg = 2; + defined $titbg or $titbg = 0; + + $self->{rs_tabbar} = urxvt::SET_COLOR (urxvt::DEFAULT_RSTYLE, $fg + 2, $bg + 2); + $self->{rs_tab} = urxvt::SET_COLOR (urxvt::DEFAULT_RSTYLE, $tabfg + 2, $tabbg + 2); + $self->{rs_title} = urxvt::SET_COLOR (urxvt::DEFAULT_RSTYLE, $titfg + 2, $titbg + 2); + + + my $timeouts = $self->x_resource ("tabbar-timeouts"); + $timeouts = '16:.:8:::4:+' unless defined $timeouts; + if ($timeouts ne '') { + my @timeouts; + while ($timeouts =~ /^(\d+):(.)(?::(.*))?$/) { + push @timeouts, [ int $1, $2 ]; + $timeouts = defined $3 ? $3 : ''; + } + if (@timeouts) { + $self->{timeouts} = [ sort { $b->[0] <=> $a-> [0] } @timeouts ]; + } + } + + $self->{new_button} = + ($self->x_resource ('new-button') or 'false') !~ /^(?:false|0|no)/i; + $self->{tab_title} = + ($self->x_resource ('title') or 'true') !~ /^(?:false|0|no)/i; + $self->{autohide} = + ($self->x_resource ('autohide') or 'false') !~ /^(?:false|0|no)/i; + + (); +} + + +sub on_start { + my ($self) = @_; + + $self->{maxtabheight} = $self->int_bwidth + $self->fheight + $self->lineSpace; + $self->{tabheight} = $self->{autohide} ? 0 : $self->{maxtabheight}; + + $self->{running_user_command} = 0; + + $self->cmd_parse ("\033[?25l"); + + my @argv = $self->argv; + + do { + shift @argv; + } while @argv && $argv[0] ne "-e"; + + if ($self->{tab_title}) { + $self->{tab_title} = $self->{term}->XInternAtom("WM_NAME", 1); + } + + $self->new_tab (@argv); + + if (defined $self->{timeouts}) { + my $interval = ($self->{timeouts}[@{ $self->{timeouts} } - 1]->[0]); + $interval = int($interval / 4); + $self->{timer} = urxvt::timer->new + ->interval($interval < 1 ? 1 : $interval) + ->cb ( sub { $self->refresh; } ); + } + + (); +} + + +sub on_configure_notify { + my ($self, $event) = @_; + + $self->configure; + $self->refresh; + + (); +} + + +sub on_user_command { + my ($self, $event) = @_; + + $self->{cur}->{term}->{parent}->tab_user_command($self->{cur}, $event, 1); + + (); +} + + +sub on_wm_delete_window { + my ($self) = @_; + $_->destroy for @{ $self->{tabs} }; + 1; +} + + +sub tab_start { + my ($self, $tab) = @_; + + $tab->XChangeInput ($tab->parent, urxvt::PropertyChangeMask); + + push @{ $self->{tabs} }, $tab; + +# $tab->{name} ||= scalar @{ $self->{tabs} }; + $self->make_current ($tab); + + (); +} + + +sub tab_destroy { + my ($self, $tab) = @_; + + $self->{tabs} = [ grep $_ != $tab, @{ $self->{tabs} } ]; + $self->update_autohide (); + + if (@{ $self->{tabs} }) { + if ($self->{cur} == $tab) { + delete $self->{cur}; + $self->make_current ($self->{tabs}[-1]); + } else { + $self->refresh; + } + } else { + # delay destruction a tiny bit + $self->{destroy} = urxvt::iw->new->start->cb (sub { $self->destroy }); + } + + (); +} + + +sub tab_key_press { + my ($self, $tab, $event, $keysym, $str) = @_; + + # setting binding keys + #open FILE, ">/tmp/key.txt" or die $!; + #printf FILE $keysym; + #close FILE; + + if ($tab->{is_inputting_name}) { + if ($keysym == 0xff0d || $keysym == 0xff8d) { # enter + $tab->{name} = $tab->{new_name}; + $tab->{is_inputting_name} = 0; + $self->update_autohide (1); + } elsif ($keysym == 0xff1b) { # escape + $tab->{name} = $tab->{old_name}; + $tab->{is_inputting_name} = 0; + $self->update_autohide (1); + } elsif ($keysym == 0xff08) { # backspace + substr $tab->{new_name}, -1, 1, ""; + $tab->{name} = "$tab->{new_name}█"; + } elsif ($str !~ /[\x00-\x1f\x80-\xaf]/) { + $tab->{new_name} .= $str; + $tab->{name} = "$tab->{new_name}█"; + } + $self->refresh; + return 1; + } + + if ($event->{state} & urxvt::ControlMask) { + + # previous tab + if ($keysym == 0x004a || $keysym == 0x006a) { + if (@{ $self->{tabs} } > 1) { + $self->change_tab($tab, -1); + } + return 1; + } + + # next tab + if ($keysym == 0x004b || $keysym == 0x006b) { + if (@{ $self->{tabs} } > 1) { + $self->change_tab($tab, 1); + } + return 1; + } + + + # new tab + if ($keysym == 0x003b) { + $self->new_tab; + return 1; + + # tab title + } elsif ($keysym == 0x0054 || $keysym == 0x0074) { + $tab->{is_inputting_name} = 1; + $tab->{old_name} = $tab->{name} ? $tab->{name} : ""; + $tab->{new_name} = ""; + $tab->{name} = "█"; + $self->update_autohide (1); + $self->refresh; + return 1; + } + + # move tab left + if ($keysym == 0x0048 || $keysym == 0x0068) { + if (@{ $self->{tabs} } > 1) { + my $idx1 = 0; + ++$idx1 while $self->{tabs}[$idx1] != $tab; + my $idx2 = ($idx1 - 1) % @{ $self->{tabs} }; + + ($self->{tabs}[$idx1], $self->{tabs}[$idx2]) = + ($self->{tabs}[$idx2], $self->{tabs}[$idx1]); + $self->make_current ($self->{tabs}[$idx2]); + } + return 1; + } + + # move tab right + if ($keysym == 0x0047 || $keysym == 0x0067) { + if (@{ $self->{tabs} } > 1) { + my $idx1 = 0; + ++$idx1 while $self->{tabs}[$idx1] != $tab; + my $idx2 = ($idx1 + 1) % @{ $self->{tabs} }; + + ($self->{tabs}[$idx1], $self->{tabs}[$idx2]) = + ($self->{tabs}[$idx2], $self->{tabs}[$idx1]); + $self->make_current ($self->{tabs}[$idx2]); + } + return 1; + } + } + + (); +} + + +sub tab_property_notify { + my ($self, $tab, $event) = @_; + + $self->copy_properties + if $event->{window} == $tab->parent; + + (); +} + + +sub tab_add_lines { + my ($self, $tab) = @_; + my $mark = $self->tab_activity_mark($tab); + $tab->{lastActivity} = int urxvt::NOW; + $self->refresh if $mark ne $self->tab_activity_mark($tab); + (); +} + + +sub tab_user_command { + my ($self, $tab, $cmd, $proxy_events) = @_; + + if ($cmd eq 'tabbedex:new_tab') { + $self->new_tab; + } + elsif ($cmd eq 'tabbedex:next_tab') { + $self->change_tab($tab, 1); + } + elsif ($cmd eq 'tabbedex:prev_tab') { + $self->change_tab($tab, -1); + } + else { + # Proxy the user command through to the tab's term, while taking care not + # to get caught in an infinite loop. + if ($proxy_events && $self->{running_user_command} == 0) { + $self->{running_user_command} = 1; + urxvt::invoke($tab->{term}, 20, $cmd); + $self->{running_user_command} = 0; + } + } + + (); +} + +sub change_tab { + my ($self, $tab, $direction) = @_; + + my $idx = 0; + ++$idx while $self->{tabs}[$idx] != $tab; + $idx += $direction; + $self->make_current ($self->{tabs}[$idx % @{ $self->{tabs}}]); + + (); +} + +package urxvt::ext::tabbedex::tab; + +# helper extension implementing the subwindows of a tabbed terminal. +# simply proxies all interesting calls back to the tabbedex class. + +{ + for my $hook qw(start destroy user_command key_press property_notify add_lines) { + eval qq{ + sub on_$hook { + my \$parent = \$_[0]{term}{parent} + or return; + \$parent->tab_$hook (\@_) + } + }; + die if $@; + } +} + + diff --git a/.vim/plugin/VimExplorer.vim b/.vim/plugin/VimExplorer.vim new file mode 100644 index 0000000..4ef4127 --- /dev/null +++ b/.vim/plugin/VimExplorer.vim @@ -0,0 +1,3538 @@ +"================================================== +" File: VimExplorer.vim +" Brief: VE - the File Manager within Vim! +" Authors: Ming Bai +" Last Change: 2009-05-06 00:20:25 +" Version: 0.99 +" Licence: LGPL +" +" Usage: :h VimExplorer +" +"================================================== + + +" See if we are already loaded, thanks to Dennis Hostetler. +if exists("loaded_vimExplorer") + finish +else + let loaded_vimExplorer = 1 +endif +" + +" Vim version 7.x is needed. +if v:version < 700 + echohl ErrorMsg | echomsg "VimExplorer needs vim version >= 7.0!" | echohl None + finish +endif + +"Load config {{{1 +"####################################################################### +"VimExplorer configuration. +" +let VEConf = {} + +"Normal configurations. + +"Common settings +"========================================== + +"Important! It is used to do iconv() to the path when calling +"sytem() function. Mine is Simplified Chinese (cp936). +if exists("g:VEConf_systemEncoding") + let VEConf.systemEncoding = g:VEConf_systemEncoding +else + let VEConf.systemEncoding = '' +endif + +"VimExplorer will check all the disks in this list at startup. +"Delete some of these to fit your system can increase start up +"speed. +"let VEConf.win32Disks = ["C:","D:","E:"] +if exists("g:VEConf_win32Disks") + let VEConf.win32Disks = g:VEConf_win32Disks +else + let VEConf.win32Disks = ["A:","B:","C:","D:","E:","F:","G:","H:", + \"I:","J:","K:","L:","M:","N:","O:","P:","Q:","R:", + \"S:","T:","U:","V:","W:","X:","Y:","Z:"] +endif + +"Set the forward and backward history stack depth. +if exists("g:VEConf_browseHistory") + let VEConf.browseHistory = g:VEConf_browseHistory +else + let VEConf.browseHistory = 100 +endif + +"Split location of preview window +if exists("g:VEConf_previewSplitLocation") + let VEConf.previewSplitLocation = g:VEConf_previewSplitLocation +else + let VEConf.previewSplitLocation = "belowright" +endif + +"Show hidden files ( .* ) +if exists("g:VEConf_showHiddenFiles") + let VEConf.showHiddenFiles = VEConf_showHiddenFiles +else + let VEConf.showHiddenFiles = 1 +endif + +"External explorer name +if (has("win32") || has("win95") || has("win64") || has("win16") || has("dos32")) + if exists("g:VEConf_externalExplorer") + let VEConf.externalExplorer = g:VEConf_externalExplorer + else + let VEConf.externalExplorer = "explorer.exe" + endif +else + if exists("g:VEConf_externalExplorer") + let VEConf.externalExplorer = g:VEConf_externalExplorer + else + let VEConf.externalExplorer = "nautilus" + endif +endif + +"Sort case sensitive , for everything +if exists("g:VEConf_sortCaseSensitive") + let VEConf.sortCaseSensitive = g:VEConf_sortCaseSensitive +else + let VEConf.sortCaseSensitive = 0 +endif + +"favorite file name +if exists("g:VEConf_favorite") + let VEConf.favorite = g:VEConf_favorite +else + let VEConf.favorite = ".ve_favorite" +endif + +"Overwrite existing files. +"boverWrite 0 ask, 1 allyes, 2 allno +if exists("g:VEConf_overWriteExisting") + let VEConf.overWriteExisting = g:VEConf_overWriteExisting +else + let VEConf.overWriteExisting = 0 +endif + +"Kde or gonme. +if !exists("g:VEConf_usingKDE") + let g:VEConf_usingKDE = 0 +endif +if !exists("g:VEConf_usingGnome") + let g:VEConf_usingGnome = 0 +endif + +"Recycle path +if !exists("g:VEConf_recyclePath") + let g:VEConf.recyclePath = '' +else + let g:VEConf.recyclePath = g:VEConf_recyclePath +endif + +"Tree panel settings +"========================================== + +"Show '+' before empty folders. +"It will cause a little performance lost. +if exists("g:VEConf_showFolderStatus") + let VEConf.showFolderStatus = g:VEConf_showFolderStatus +else + let VEConf.showFolderStatus = 1 +endif + +"Tree panel width +if exists("g:VEConf_treePanelWidth") + let VEConf.treePanelWidth = g:VEConf_treePanelWidth +else + let VEConf.treePanelWidth = 30 +endif + +"Split mode of tree panel +if exists("g:VEConf_treePanelSplitMode") + let VEConf.treePanelSplitMode = g:VEConf_treePanelSplitMode +else + let VEConf.treePanelSplitMode = "vertical" +endif + +"Split location of file panel +if exists("g:VEConf_treePanelSplitLocation") + let VEConf.treePanelSplitLocation = g:VEConf_treePanelSplitLocation +else + let VEConf.treePanelSplitLocation = "leftabove" +endif + +"Set the tree panel sort direction. +if exists("g:VEConf_treeSortDirection") + let VEConf.treeSortDirection = g:VEConf_treeSortDirection +else + let VEConf.treeSortDirection = 1 +endif + +"File panel settings +"========================================== + +"Set the file group sort direction. +if exists("g:VEConf_fileGroupSortDirection") + let VEConf.fileGroupSortDirection = g:VEConf_fileGroupSortDirection +else + let VEConf.fileGroupSortDirection = 1 +endif + +"Delete file confirm. +if exists("g:VEConf_fileDeleteConfirm") + let VEConf.fileDeleteConfirm = g:VEConf_fileDeleteConfirm +else + let VEConf.fileDeleteConfirm = 1 +endif + +"File panel width +if exists("g:VEConf_filePanelWidth") + let VEConf.filePanelWidth = g:VEConf_filePanelWidth +else + let VEConf.filePanelWidth = 40 +endif + +"Split mode of file panel +if exists("g:VEConf_filePanelSplitMode") + let VEConf.filePanelSplitMode = g:VEConf_filePanelSplitMode +else + let VEConf.filePanelSplitMode = "vertical" +endif + +"Split location of file panel +if exists("g:VEConf_filePanelSplitLocation") + let VEConf.filePanelSplitLocation = g:VEConf_filePanelSplitLocation +else + let VEConf.filePanelSplitLocation = "belowright" +endif + +"File panel sort type. +if exists("g:VEConf_filePanelSortType") + let VEConf.filePanelSortType = g:VEConf_filePanelSortType +else + let VEConf.filePanelSortType = 0 +endif + +"Show file size in M/K/B +if exists("g:VEConf_showFileSizeInMKB") + let VEConf.showFileSizeInMKB = g:VEConf_showFileSizeInMKB +else + let VEConf.showFileSizeInMKB = 1 +endif + +"File panel filter. +if exists("g:VEConf_filePanelFilter") + let VEConf.filePanelFilter = g:VEConf_filePanelFilter +else + let VEConf.filePanelFilter = '' +endif + + +"####################################################################### +"Tree panel hot key bindings. +let VEConf.treePanelHotkey = {} +let VEConf.treePanelHotkey.help = '?' +let VEConf.treePanelHotkey.toggleNode = '' +let VEConf.treePanelHotkey.toggleNodeMouse = '<2-LeftMouse>' +let VEConf.treePanelHotkey.refresh = 'r' +let VEConf.treePanelHotkey.favorite = 'f' +let VEConf.treePanelHotkey.addToFavorite = 'F' +let VEConf.treePanelHotkey.browseHistory = 'b' +let VEConf.treePanelHotkey.toggleFilePanel = 't' +let VEConf.treePanelHotkey.toUpperDir = '' +let VEConf.treePanelHotkey.switchPanel = '' +let VEConf.treePanelHotkey.gotoPath = '' +let VEConf.treePanelHotkey.quitVE = 'Q' + +if exists("g:VEConf_treeHotkey") + if type(g:VEConf_treeHotkey) != type({}) + echohl WarningMsg | echo "g:VEConf_treeHotkey is not dictionary type!" | echohl None + finish + endif + for i in keys(g:VEConf_treeHotkey) + let VEConf.treePanelHotkey[i] = g:VEConf_treeHotkey[i] + endfor +endif + +"File panel hot key bindings. +"normal mode hotkeys +let VEConf.filePanelHotkey = {} +"normal +let VEConf.filePanelHotkey.help = '?' +let VEConf.filePanelHotkey.itemClicked = '' +let VEConf.filePanelHotkey.itemClickMouse = '<2-LeftMouse>' +let VEConf.filePanelHotkey.refresh = 'r' +let VEConf.filePanelHotkey.toggleTreePanel = 't' +let VEConf.filePanelHotkey.toggleModes = 'i' +let VEConf.filePanelHotkey.newFile = '+f' +let VEConf.filePanelHotkey.newDirectory = '+d' +let VEConf.filePanelHotkey.switchPanel = '' +let VEConf.filePanelHotkey.quitVE = 'Q' +let VEConf.filePanelHotkey.toggleHidden = 'H' +let VEConf.filePanelHotkey.search = 'g/' +let VEConf.filePanelHotkey.markPlace = 'm' +let VEConf.filePanelHotkey.gotoPlace = "'" +let VEConf.filePanelHotkey.viewMarks = 'J' +let VEConf.filePanelHotkey.contextMenuN = '' +"Browsing +let VEConf.filePanelHotkey.toUpperDir = '' +let VEConf.filePanelHotkey.gotoForward = '' +let VEConf.filePanelHotkey.gotoBackward = '' +let VEConf.filePanelHotkey.favorite = 'f' +let VEConf.filePanelHotkey.addToFavorite = 'F' +let VEConf.filePanelHotkey.browseHistory = 'b' +let VEConf.filePanelHotkey.gotoPath = '' +"single file actions +let VEConf.filePanelHotkey.rename = 'R' +let VEConf.filePanelHotkey.yankSingle = 'yy' +let VEConf.filePanelHotkey.cutSingle = 'xx' +let VEConf.filePanelHotkey.showYankList = 'yl' +let VEConf.filePanelHotkey.deleteSingle = 'dd' +let VEConf.filePanelHotkey.deleteSingleF = 'DD' +let VEConf.filePanelHotkey.openPreview = 'u' +let VEConf.filePanelHotkey.closePreview = 'U' +"mark +let VEConf.filePanelHotkey.toggleSelectUp = '' +let VEConf.filePanelHotkey.toggleSelectDown= '' +let VEConf.filePanelHotkey.toggleSelMouse = '' +let VEConf.filePanelHotkey.markViaRegexp = 'Mr' +let VEConf.filePanelHotkey.markVimFiles = 'Mv' +let VEConf.filePanelHotkey.markDirectory = 'Md' +let VEConf.filePanelHotkey.markExecutable = 'Me' +let VEConf.filePanelHotkey.clearSelect = 'Mc' +"multiple file actions +let VEConf.filePanelHotkey.deleteSelected = 'sd' +let VEConf.filePanelHotkey.deleteSelectedF = 'sD' +let VEConf.filePanelHotkey.yankSelected = 'sy' +let VEConf.filePanelHotkey.cutSelected = 'sx' +let VEConf.filePanelHotkey.tabViewMulti = 'se' +let VEConf.filePanelHotkey.paste = 'p' +let VEConf.filePanelHotkey.diff2files = '=' +"visual mode hotkeys. +let VEConf.filePanelHotkey.visualSelect = '' +let VEConf.filePanelHotkey.visualDelete = 'd' +let VEConf.filePanelHotkey.visualDeleteF = 'D' +let VEConf.filePanelHotkey.visualYank = 'y' +let VEConf.filePanelHotkey.visualCut = 'x' +"User defined hotkeys, see below. +let VEConf.filePanelHotkey.tabView = 'e' +let VEConf.filePanelHotkey.openRenamer = ';r' +let VEConf.filePanelHotkey.startShell = ';c' +let VEConf.filePanelHotkey.startExplorer = ';e' + +if exists("g:VEConf_fileHotkey") + if type(g:VEConf_fileHotkey) != type({}) + echohl WarningMsg | echo "g:VEConf_fileHotkey is not dictionary type!" | echohl None + finish + endif + for i in keys(g:VEConf_fileHotkey) + let VEConf.filePanelHotkey[i] = g:VEConf_fileHotkey[i] + endfor +endif + +"####################################################################### +"User defined file actions. +if !exists("g:VEConf_normalActions") + let VEConf_normalActions = {} +endif +if !exists("g:VEConf_normalHotKeys") + let VEConf_normalHotKeys = {} +endif +if !exists("g:VEConf_singleFileActions") + let VEConf_singleFileActions = {} +endif +if !exists("g:VEConf_singleFileHotKeys") + let VEConf_singleFileHotKeys = {} +endif + +if !exists("g:VEConf_multiFileActions") + let VEConf_multiFileActions = {} +endif +if !exists("g:VEConf_multiFileHotKeys") + let VEConf_multiFileHotKeys = {} +endif + +"Template +" let VEConf_singleFileHotKeys['actionName'] = '' +" function! VEConf_singleFileActions['actionName'](path) +" "do some jobs here. +" endfunction +" +"the 'path' is the file name under cursor in the file panel, you +"can use this path to do some actions. +"Pay attention to the hotKeys you have defined, dont conflict +"whth the default hotKey bindings. +"Normal Actions just run in current path, no path needed to +"pass. + +"There are some examples: +"Open current file using vim in a new tab. +let VEConf_singleFileHotKeys['openInNewTab'] = VEConf.filePanelHotkey.tabView +function! VEConf_singleFileActions['openInNewTab'](path) + if !isdirectory(a:path) + exec "tabe " . g:VEPlatform.escape(a:path) + else + exec "VE " . g:VEPlatform.escape(a:path) + endif +endfunction + +"Renamer is a very good plugin. +let VEConf_normalHotKeys['openRenamer'] = VEConf.filePanelHotkey.openRenamer +function! VEConf_normalActions['openRenamer']() + Renamer +endfunction + +"start shell in current directory. +let VEConf_normalHotKeys['startShell'] = VEConf.filePanelHotkey.startShell +function! VEConf_normalActions['startShell']() + call g:VEPlatform.startShell() +endfunction + +"start file explorer in current directory +"(nautilus,konquer,Explorer.exe and so on). +let VEConf_normalHotKeys['startExplorer'] = VEConf.filePanelHotkey.startExplorer +function! VEConf_normalActions['startExplorer']() + call g:VEPlatform.startExplorer() +endfunction + +"Multiple file name are contained in the fileList. +let VEConf_multiFileHotKeys['openMultiFilesWithVim'] = VEConf.filePanelHotkey.tabViewMulti +function! VEConf_multiFileActions['openMultiFilesWithVim'](fileList) + if empty(a:fileList) + return + endif + for i in a:fileList + exec "tabe " . g:VEPlatform.escape(i) + endfor +endfunction + +"####################################################################### +"Syntax and highlight configuration. +function! VEConf.treePanelSyntax() + syn clear + syn match Question "^.*Press ? for help.*$" "Host name + syn match WarningMsg "\[[A-Z]:[\\/]\]" "root node name + syn match Identifier "^\s*\zs[+-]" "+- + syn match SpecialKey "^.*\[current\]$" "current folder +endfunction + +function! VEConf.filePanelSyntax() + syntax clear + syn match Type "\[ .* \]" "group + syn match Comment '\t.\{10}' "file size + syn match Comment '\d\{4}-\d\{2}-\d\{2}\ \d\{2}:\d\{2}:\d\{2}' "time + syn match Special '^Path: .*$' "path + syn match WarningMsg '^\~*$' "line + syn match Function '^.*[\\/]' "directory + syn match Search '^\*.*$' "selectedFiles + syn match LineNr '[rwx-]\{9}' "perm +endfunction + +"####################################################################### + +" classes relationship +" +" VEFrameWork +" VETreePanel +" VETree +" VENode +" VEFilePanel +" VEPlatform + +" class VEPlatform {{{1 +"============================= +let VEPlatform = {} + +"it's a static class, no constructor + +"has win +function! VEPlatform.haswin32() + if (has("win32") || has("win95") || has("win64") || has("win16") || has("dos32")) + return 1 + else + return 0 + endif +endfunction + +"return a path always end with slash. +function! VEPlatform.getcwd() + let path = getcwd() + if g:VEPlatform.haswin32() && !&ssl + if path[-1:] != "\\" + let path = path . "\\" + endif + else + if path[-1:] != "/" + let path = path . "/" + endif + endif + return path +endfunction + +"get home path, end with a slash +function! VEPlatform.getHome() + if g:VEPlatform.haswin32() && !&ssl + if $HOME[-1:] != "\\" + return $HOME . "\\" + else + return $HOME + endif + else + if $HOME[-1:] != "/" + return $HOME . "/" + else + return $HOME + endif + endif +endfunction + +function! VEPlatform.escape(path) + if g:VEPlatform.haswin32() + return escape(a:path,'%#') + else + return escape(a:path,' %#') + endif +endfunction + +"start a program and then return to vim, no wait. +function! VEPlatform.start(path) + let convPath = self.escape(a:path) + "escape() function will do iconv to the string, so call it + "before iconv(). + if g:VEPlatform.haswin32() + let convPath = substitute(convPath,'/',"\\",'g') + let convPath = " start \"\" \"" . convPath . "\"" + let ret = self.system(convPath) + else + if g:VEConf_usingKDE + let convPath = "kfmclient exec " . convPath + let ret = self.system(convPath) + elseif g:VEConf_usingGnome + let convPath = "gnome-open " . convPath + let ret = self.system(convPath) + else " default using gnome-open. + let convPath = "gnome-open " . convPath + let ret = self.system(convPath) + endif + endif + if !ret + echohl ErrorMsg | echomsg "Failed to start " . a:path | echohl None + return 0 + endif + return 1 +endfunction + +function! VEPlatform.system(cmd) + "can not escape here! example: 'rm -r blabla\ bbb' + "let convCmd = escape(a:cmd,' %#') + let convCmd = a:cmd + if g:VEConf.systemEncoding != '' + let convCmd = iconv(convCmd,&encoding,g:VEConf.systemEncoding) + endif + call system(convCmd) + return !(v:shell_error) +endfunction + +" Return successful copyed file list. +function! VEPlatform.copyMultiFile(fileList,topath) + let boverWrite = g:VEConf.overWriteExisting + let retList = [] + for i in a:fileList + "boverWrite 0 ask, 1 allyes, 2 allno + if boverWrite == 0 + if i[-1:] == "\\" || i[-1:] == "/" + let i = i[:-2] + endif + let tofile = a:topath . matchstr(i,'[\\/]\zs[^\\/]\+$') + if findfile(tofile) != '' + "echohl WarningMsg + "let result = tolower(input("File [ " . tofile . " ] exists! Over write ? (Y)es/(N)o/(A)llyes/A(L)lno/(C)ancel ","Y")) + let result = confirm("File [ " . matchstr(i,'[\\/]\zs[^\\/]\+$') . + \" ] exists! Over write ? ","&Yes\n&No\nYes to &All\nNo &To All\n&Cancel ",1) + "echohl None + if result == 1 + if !self.copyfile(i,a:topath) + echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None + else + let retList += [i] + endif + elseif result == 2 + continue + elseif result == 3 + let boverWrite = 1 + if !self.copyfile(i,a:topath) + echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None + else + let retList += [i] + endif + elseif result == 4 + let boverWrite = 2 + else + break + endif + else + if !self.copyfile(i,a:topath) + echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None + else + let retList += [i] + endif + endif + elseif boverWrite == 1 + if !self.copyfile(i,a:topath) + echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None + else + let retList += [i] + endif + elseif boverWrite == 2 + if i[-1:] == "\\" || i[-1:] == "/" + let i = i[:-2] + endif + let tofile = a:topath . matchstr(i,'[\\/]\zs[^\\/]\+$') + if findfile(tofile) != '' + continue + endif + if !self.copyfile(i,a:topath) + echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None + else + let retList += [i] + endif + endif + endfor + echohl Special | echomsg " " . len(retList) . " file(s) pasted!" | echohl None + return retList +endfunction + +function! VEPlatform.copyfile(filename,topath) + "return + let filename = self.escape(a:filename) + let topath = self.escape(a:topath) + if g:VEPlatform.haswin32() + let filename = substitute(a:filename,'/',"\\",'g') + let topath = substitute(a:topath,'/',"\\",'g') + if isdirectory(filename) + if filename[-1:] == "\\" + let filename = filename[:-2] + endif + let topath = "\"" . topath . matchstr(filename,'[^\\]*$') . "\"" + let filename = "\"" . filename . "\"" + let cmd = "xcopy ".filename . " " . topath . " /E /I /H /R /Y" + else + let topath = "\"" . topath . "\"" + let filename = "\"" . filename . "\"" + let cmd = "xcopy ". filename . " " . topath . " /I /H /R /Y" + endif + return self.system(cmd) + else + let cmd = "cp -r " . filename . " " . topath . "&" + return self.system(cmd) + endif +endfunction + +" The "move" command in win32 is so poor.. +" So I have no choice but copy then delete. +"function! VEPlatform.movefile(filename,topath) +" let filename = self.escape(a:filename) +" let topath = self.escape(a:topath) +" if executable("mv") +" let cmd = "mv -f " . filename . " " . topath +" return self.system(cmd) +" else +" if self.copyfile(a:filename,a:topath) +" return self.delete(a:filename,1) +" else +" return 0 +" endif +" endif +"endfunction + +function! VEPlatform.mkdir(path) + if g:VEConf.systemEncoding != '' + let convPath = iconv(a:path,&encoding,g:VEConf.systemEncoding) + else + let convPath = a:path + endif + return mkdir(convPath,'p') +endfunction + +function! VEPlatform.mkfile(filename) + if findfile(a:filename) != '' || isdirectory(a:filename) + return 0 + endif + if writefile([],a:filename) == 0 "here it is not need to convert filename + return 1 + else + return 0 + endif +endfunction + +function! VEPlatform.executable(filename) + if isdirectory(a:filename) + return 0 + endif + if getfperm(a:filename)[2] == 'x' + return 1 + else + return 0 + endif +endfunction + +function! VEPlatform.search(filename,path) + if a:filename == '.' || a:filename == '..' + return [] + else + return split(globpath(a:path,"**/" . a:filename),"\n") + endif +endfunction + +function! VEPlatform.globpath(path) + if g:VEConf.showHiddenFiles + let tmp = globpath(a:path,"*") . "\n" . globpath(a:path,".[^.]*") "need to cut . and .. + " can not show files start with .. such as ..foo , :( + " I do not know how to write the shell regexp. + if tmp == "\n" + return '' + else + return tmp + endif + else + return globpath(a:path,"*") + endif +endfunction + +"globpath used in file panel, including filter. +function! VEPlatform.globpath_file(path) + if g:VEConf.filePanelFilter != '' + return globpath(a:path,g:VEConf.filePanelFilter) + endif + if g:VEConf.showHiddenFiles + let tmp = globpath(a:path,"*") . "\n" . globpath(a:path,".[^.]*") "need to cut . and .. + " can not show files start with .. such as ..foo , :( + " I do not know how to write the shell regexp. + if tmp == "\n" + return '' + else + return tmp + endif + else + return globpath(a:path,"*") + endif +endfunction + +function! VEPlatform.cdToPath(path) + try + "In win32, VE can create folder starts with space. So ... + exec "lcd " . escape(a:path,' %#') + catch + echohl ErrorMsg | echomsg "Can not cd to path: " . a:path | echohl None + endtry +endfunction + +function! VEPlatform.startShell() + if g:VEPlatform.haswin32() + !start cmd.exe + else + shell + endif +endfunction + +function! VEPlatform.startExplorer() + let pwd = self.escape(g:VEPlatform.getcwd()) + if g:VEPlatform.haswin32() + let pwd = substitute(pwd,'/',"\\",'g') + endif + if !self.system(g:VEConf.externalExplorer . " " . pwd) + "echohl ErrorMsg | echomsg "Failed to start external explorer: " . g:VEConf.externalExplorer | echohl None + " M$ windows Explorer.exe always return 1 even it starts successfully, shit! + endif +endfunction + +function! VEPlatform.getRoot(rootDict) + if g:VEPlatform.haswin32() + "Create new root list. + let newRootList = [] + for i in g:VEConf.win32Disks + if &ssl + let i = i . "/" + else + let i = i . "\\" + endif + if g:VEPlatform.globpath(i) != '' + call add(newRootList,i) + endif + endfor + "Remove nolonger exist root nodes. + for i in keys(a:rootDict) + if index(newRootList,i) == -1 + call remove(a:rootDict,i) + endif + endfor + "Create new root nodes. + for i in newRootList + if !has_key(a:rootDict,i) + let a:rootDict[i] = deepcopy(s:VENode) + call a:rootDict[i].init(i) + let a:rootDict[i].hasOwnChilds = 1 + endif + endfor + else "Assert the other platform acts like UNIX + let newRootList = ["/"] " ~/ + for i in newRootList + if !has_key(a:rootDict,i) + let a:rootDict[i] = deepcopy(s:VENode) + call a:rootDict[i].init(i) + let a:rootDict[i].hasOwnChilds = 1 + endif + endfor + endif +endfunction + +function! VEPlatform.pathToName(path) + let time = strftime("%Y-%m-%d %H:%M:%S",getftime(a:path)) + let size = getfsize(a:path) + let perm = getfperm(a:path) + if g:VEPlatform.haswin32() && !&ssl + if a:path[-1:] != "\\" + let name = substitute(a:path,'^.*\\','','g') + else + let name = substitute(a:path,'^.*\\\ze.\+\\$','','g') + endif + else + if a:path[-1:] != "/" + let name = substitute(a:path,'^.*\/','','g') + else + let name = substitute(a:path,'^.*\/\ze.\+\/$','','g') + endif + endif + if g:VEConf.showFileSizeInMKB + if size > (1024 * 1024) + let size = (size / 1024 / 1024) . ' M' + elseif size > 1024 + let size = (size / 1024) . ' K' + elseif size > 0 + let size = size . ' B' + endif + endif + let tail = printf("%10.10s ".perm . ' ' .time,size==0?'':size) + return name . "\t" . tail +endfunction + +function! VEPlatform.getUpperDir(path) + if g:VEPlatform.haswin32() && !&ssl + return substitute(a:path,'\\\zs[^\\]\+\\$','','g') + else + return substitute(a:path,'\/\zs[^/]\+\/$','','g') + endif +endfunction + +"default choice and return value: 1:YES 0:NO +function! VEPlatform.confirm(text,defaultChoice) + if a:defaultChoice + let ret = confirm(a:text,"&Yes\n&No",1) + else + let ret = confirm(a:text,"&Yes\n&No",2) + endif + if ret == 1 + return 1 + else + return 0 + endif + "if a:defaultChoice + " echohl WarningMsg + " let result = tolower(input(a:text . " ","Y")) + " echohl None + "else + " echohl WarningMsg + " let result = tolower(input(a:text . " "),"N") + " echohl None + "endif + "if result == "y" || result == "ye" || result == "yes" + " return 1 + "else + " return 0 + "endif +endfunction + +"delete a single file or directory +"return 0:failed 1:success +function! VEPlatform.deleteSingle(path,bforce) + if !isdirectory(a:path) + if g:VEConf.fileDeleteConfirm && !self.confirm("Delete \n\"".a:path."\" ?",1) + echo " " + "clear the command line + return 0 + endif + if self.delete(a:path,a:bforce) + echohl Special | echomsg "File: [" . a:path . "] deleted!" | echohl None + return 1 + else + echohl ErrorMsg | echomsg "Can not delete the file! [" . a:path . "]" | echohl None + return 0 + endif + else + if g:VEConf.fileDeleteConfirm && !self.confirm("Remove the folder \n\"".a:path."\" and all its contents?",1) + echo " " + return 0 + endif + echo " " + return self.delete(a:path,a:bforce) + endif +endfunction + +"delete multiple files/directory. +"return 0:failed 1:success +function! VEPlatform.deleteMultiple(fileList,bforce) + if g:VEConf.fileDeleteConfirm && !self.confirm("Delete selected file(s) ?",1) + echo " " + return 0 + endif + for i in a:fileList + if !self.delete(i,a:bforce) + echohl ErrorMsg | echomsg "Failed to delete: " . i | echohl None + endif + endfor + return 1 +endfunction + +function! VEPlatform.delete(name,bforce) + if g:VEPlatform.haswin32() + let recPath = tolower(g:VEConf.recyclePath) + let delName = tolower(a:name) + else + let recPath = g:VEConf.recyclePath + let delName = a:name + endif + if !a:bforce && g:VEConf.recyclePath != '' && (stridx(delName,recPath) == -1) + if !isdirectory(g:VEConf.recyclePath) + if !self.mkdir(g:VEConf.recyclePath) || !isdirectory(g:VEConf.recyclePath) + echohl ErrorMsg | echomsg "Can not access recycle bin!" | echohl None + return 0 + endif + endif + if !self.copyfile(a:name,g:VEConf.recyclePath) + echohl ErrorMsg | echomsg "Failed to move the file: [" . a:name . "] to recycle bin." | echohl None + return 0 + "else + " return 1 + endif + endif + if isdirectory(a:name) + if g:VEPlatform.haswin32() + return g:VEPlatform.system(" rmdir /S /Q \"" . self.escape(a:name) . "\"") + else + return g:VEPlatform.system("rm -r " . self.escape(a:name) . "&") + endif + else + if delete(a:name) == 0 + return 1 + else + return 0 + endif + endif +endfunction + +function! VEPlatform.select(list,title) + let selectList = deepcopy(a:list) + if len(selectList) == 0 + return + endif + call insert(selectList,a:title,0) + for i in range(1,len(selectList)-1) + let selectList[i] = i . " " . selectList[i] + endfor + let result = inputlist(selectList) + if result > len(a:list) || result <= 0 + return -1 + else + return result-1 + endif +endfunction + +" This is not a member of VEPlatform, because sort() +" can not use dict function. +function! VEPlatform_sortCompare(t1,t2) + if g:VEConf.sortCaseSensitive + return a:t1 ==# a:t2 ? 0 : a:t1 ># a:t2 ? 1 : -1 + else + return a:t1 ==? a:t2 ? 0 : a:t1 >? a:t2 ? 1 : -1 + endif +endfunction + + +" class VENode {{{1 +"============================= +let s:VENode = {} +let s:VENode.name = '' +let s:VENode.path = '' +let s:VENode.isopen = 0 +let s:VENode.hasOwnChilds = 0 +let s:VENode.childs = {} + +"Object Constructor +function! s:VENode.init(path) + let self.path = a:path + if g:VEPlatform.haswin32() && !&ssl + let self.name = matchstr(a:path,'[^\\]*\\$','','g') + else + let self.name = matchstr(a:path,'[^/]*\/$','','g') + endif +endfunction + +"Refresh tree node +function! s:VENode.updateNode() + "Once a node is updated, it means that the node has been opened. + let self.isopen = 1 + "Create new dir list + let newDirList = [] + for i in split(g:VEPlatform.globpath(self.path),"\n") + if isdirectory(i) == 1 + if g:VEPlatform.haswin32() && !&ssl + let i = matchstr(i,'[^\\]*$','','g') . "\\" + else + let i = matchstr(i,'[^/]*$','','g') . "/" + endif + call add(newDirList,i) + endif + endfor + "Remove nolonger exist dirs. + for i in keys(self.childs) + if index(newDirList,i) == -1 + call remove(self.childs,i) + endif + endfor + "Create new nodes + for i in newDirList + if !has_key(self.childs,i) + let self.childs[i] = deepcopy(s:VENode) + call self.childs[i].init(self.path . i) + endif + endfor + "find out which child has their own childs + if !empty(self.childs) + let self.hasOwnChilds = 1 + else + let self.hasOwnChilds = 0 + return + endif + if g:VEConf.showFolderStatus == 0 + for i in keys(self.childs) + let self.childs[i].hasOwnChilds = 1 + endfor + else + for i in keys(self.childs) + let _hasOwnChilds = 0 + for j in split(g:VEPlatform.globpath(self.childs[i].path),"\n") + if isdirectory(j) == 1 + let _hasOwnChilds = 1 + break + endif + endfor + if _hasOwnChilds == 1 + let self.childs[i].hasOwnChilds = 1 + endif + endfor + endif + "update opened child nodes + for i in keys(self.childs) + if self.childs[i].isopen == 1 + call self.childs[i].updateNode() + endif + endfor +endfunction + +"Toggle open/close status of one node +"the path should end with '\' such as c:\aaa\bbb\ +"example "c:\\aaa\\bbb\\" "aaa\\bbb\\" "bbb\\" +function! s:VENode.toggle(path) + if g:VEPlatform.haswin32() && !&ssl + let childPath = substitute(a:path,'^.\{-}\\','','g') + else + let childPath = substitute(a:path,'^.\{-}\/','','g') + endif + if childPath == '' + let self.isopen = !self.isopen + if self.isopen == 1 + call self.updateNode() + endif + else + if g:VEPlatform.haswin32() && !&ssl + let nodeName = matchstr(childPath,'^.\{-}\\') + else + let nodeName = matchstr(childPath,'^.\{-}\/') + endif + if !has_key(self.childs,nodeName) + echoerr "path error" + endif + let self.isopen = 1 + call self.childs[nodeName].toggle(childPath) + endif +endfunction + +"Open the giving path +"the path should end with '\' such as c:\aaa\bbb\ +"example "c:\\aaa\\bbb\\" "aaa\\bbb\\" "bbb\\" +function! s:VENode.openPath(path) + if g:VEPlatform.haswin32() && !&ssl + let childPath = substitute(a:path,'^.\{-}\\','','g') + else + let childPath = substitute(a:path,'^.\{-}\/','','g') + endif + if childPath == '' + if empty(self.childs) + call self.updateNode() + endif + return + else + if g:VEPlatform.haswin32() && !&ssl + let nodeName = matchstr(childPath,'^.\{-}\\') + else + let nodeName = matchstr(childPath,'^.\{-}\/') + endif + if !has_key(self.childs,nodeName) + call self.updateNode() + endif + if !has_key(self.childs,nodeName) "refreshed and still can not find the path. + echoerr "Path error!" + return + else + let self.isopen = 1 + call self.childs[nodeName].openPath(childPath) + endif + endif +endfunction + + +"Draw the tree, depend on the status of every tree node. +function! s:VENode.draw(tree,depth) + if self.hasOwnChilds == 0 + let name = repeat(' ',a:depth*2).' '.self.name + call add(a:tree,[name,self.path]) + return + endif + if self.isopen + let name = repeat(' ',a:depth*2).'- '.self.name + if a:depth == 0 "let the root node looks different + let name = '- [' . self.name . ']' + endif + call add(a:tree,[name,self.path]) + let keys = sort(keys(self.childs),"VEPlatform_sortCompare") + if !g:VEConf.treeSortDirection + call reverse(keys) + endif + for i in keys + call self.childs[i].draw(a:tree,a:depth+1) + endfor + else + let name = repeat(' ',a:depth*2).'+ '.self.name + if a:depth == 0 "let the root node looks different + let name = '+ [' . self.name . ']' + endif + call add(a:tree,[name,self.path]) + endif +endfunction + +" class VETree {{{1 +"============================= +let s:VETree = {} +let s:VETree.content = [] +let s:VETree.rootNodes = {} + +"Object Constructor +function! s:VETree.init() + call g:VEPlatform.getRoot(self.rootNodes) + "for i in keys(self.rootNodes) + " call self.rootNodes[i].updateNode() + "endfor +endfunction + +function! s:VETree.togglePath(path) + if g:VEPlatform.haswin32() && !&ssl + let rootNodeName = matchstr(a:path,'^.\{-}\\') + else + let rootNodeName = matchstr(a:path,'^.\{-}\/') + endif + call self.rootNodes[rootNodeName].toggle(a:path) +endfunction + +function! s:VETree.openPath(path) + if g:VEPlatform.haswin32() && !&ssl + let rootNodeName = matchstr(a:path,'^.\{-}\\') + else + let rootNodeName = matchstr(a:path,'^.\{-}\/') + endif + call self.rootNodes[rootNodeName].openPath(a:path) +endfunction + +" fill self.content +function! s:VETree.draw() + let keys = sort(keys(self.rootNodes),"VEPlatform_sortCompare") + if g:VEConf.treeSortDirection == 0 + call reverse(keys) + endif + for i in keys + call self.rootNodes[i].draw(self.content,0) + endfor +endfunction + +function! s:VETree.update(path) + call g:VEPlatform.getRoot(self.rootNodes) + "toggle twice to update current directory + call self.togglePath(a:path) + call self.togglePath(a:path) + " costs too much time. + "for i in keys(self.rootNodes) + " call self.rootNodes[i].updateNode() + "endfor +endfunction + +" class VETreePanel {{{1 +"============================= +let s:VETreePanel = {} +let s:VETreePanel.tree = {} +let s:VETreePanel.name = '' +let s:VETreePanel.path = '' +let s:VETreePanel.width = 0 +let s:VETreePanel.splitMode = '' +let s:VETreePanel.splitLocation = '' + +"Object Constructor +function! s:VETreePanel.init(name,path) + let self.name = "VETreePanel" . a:name + let self.path = a:path + let self.width = g:VEConf.treePanelWidth + let self.splitMode = g:VEConf.treePanelSplitMode + let self.splitLocation = g:VEConf.treePanelSplitLocation + let self.tree = deepcopy(s:VETree) + call self.tree.init() + call self.tree.openPath(a:path) +endfunction + +function! s:VETreePanel.setFocus() + let VETreeWinNr = bufwinnr(self.name) + if VETreeWinNr != -1 + exec VETreeWinNr . " wincmd w" + return 1 + else + let bufNr = bufnr(self.name) + if bufNr != -1 + exec "bwipeout " . bufNr + endif + return 0 + endif +endfunction + +"Sync the tree with filesystem and refresh the tree panel +function! s:VETreePanel.refresh() + if !self.setFocus() + return + endif + call self.tree.update(self.path) + call self.drawTree() +endfunction + +"Draw the dir tree but do not sync the tree with filesystem +function! s:VETreePanel.drawTree() + if !self.setFocus() + return + endif + if !empty(self.tree.content) + call remove(self.tree.content,0,-1) + endif + call add(self.tree.content,[hostname() . " (Press ? for help)",""]) + call self.tree.draw() + let tree = [] + let lineNr = line(".") + for i in self.tree.content + if i[1] == self.path + let i[0] = i[0] . " [current]" + let lineNr = index(self.tree.content,i) + 1 + endif + call add(tree,i[0]) + endfor + setlocal noreadonly + setlocal modifiable + "Let the cursor go back to right line and right position in + "the screen. + normal! H + let Hline = line(".") + silent normal! ggdG + call append(0,tree) + silent normal! Gddgg + exec "normal! " . Hline . "G" + normal! zt + exec "normal! " . lineNr . "G" + setlocal readonly + setlocal nomodifiable +endfunction + +"Show tree panel +function! s:VETreePanel.show() + if self.setFocus() + return + endif + let cmd = self.splitLocation . " " . self.splitMode . ' ' . self.width . ' new ' . self.name + silent! execute cmd + let VETreeWinNr = bufwinnr(self.name) + if VETreeWinNr != -1 + exec VETreeWinNr . " wincmd w" + setlocal winfixwidth + setlocal noswapfile + setlocal buftype=nowrite + setlocal bufhidden=delete + setlocal nowrap + setlocal foldcolumn=0 + setlocal nobuflisted + setlocal nospell + setlocal nonumber + setlocal cursorline + setlocal readonly + setlocal nomodifiable + "call self.refresh() + call self.drawTree() + call self.createActions() + call self.createSyntax() + else + echoerr "create tree window failed!" + endif +endfunction + +"Hide tree panel +function! s:VETreePanel.hide() + if !self.setFocus() + return + else + "make sure there are no more than 1 buffer has the same name + let bufNr = bufnr('%') + "exec "wincmd c" + quit + exec "bwipeout ".bufNr + endif +endfunction + +function! s:VETreePanel.getPathUnderCursor(num) + return self.tree.content[a:num][1] +endfunction + +function! s:VETreePanel.nodeClicked(num) + if self.tree.content[a:num][1] == "" + return + endif + let path = self.tree.content[a:num][1] + if self.path != path + "let self.path = path + call VE_GotoPath(path) + "Do not toggle if it is the first time switch to another tree node. + call self.setFocus() + return + endif + call self.tree.togglePath(path) + call self.drawTree() +endfunction + +function! s:VETreePanel.pathChanged(path) + if self.path == a:path + return + endif + call g:VEPlatform.cdToPath(a:path) + let self.path = g:VEPlatform.getcwd() + call self.tree.openPath(self.path) + call self.drawTree() +endfunction + +function! s:VETreePanel.createActions() + exec "nnoremap " . g:VEConf.treePanelHotkey.help . " :tab h VimExplorer" + exec "nnoremap " . g:VEConf.treePanelHotkey.toggleNode . " :call VE_OnTreeNodeClick()" + exec "nnoremap " . g:VEConf.treePanelHotkey.toggleNodeMouse. " :call VE_OnTreeNodeClick()" + exec "nnoremap " . g:VEConf.treePanelHotkey.refresh . " :call VE_TreeRefresh()" + exec "nnoremap " . g:VEConf.treePanelHotkey.toggleFilePanel ." :call VE_ToggleFilePanel()" + exec "nnoremap " . g:VEConf.treePanelHotkey.toUpperDir . " :call VE_ToUpperDir()" + exec "nnoremap " . g:VEConf.treePanelHotkey.switchPanel . " " + exec "nnoremap " . g:VEConf.treePanelHotkey.favorite . " :call VE_GotoFavorite()" + exec "nnoremap " . g:VEConf.treePanelHotkey.addToFavorite . " :call VE_AddToFavorite('treePanel')" + exec "nnoremap " . g:VEConf.treePanelHotkey.browseHistory . " :call VE_BrowseHistory()" + exec "nnoremap " . g:VEConf.treePanelHotkey.gotoPath . " :call VE_OpenPath()" + exec "nnoremap " . g:VEConf.treePanelHotkey.quitVE . " :call VEDestroy()" + " autocmd + au! * + au BufEnter call VE_SyncDir() + " Status line + setlocal statusline=%{getcwd()} +endfunction + +function! s:VETreePanel.createSyntax() + if !self.setFocus() + return + endif + call g:VEConf.treePanelSyntax() +endfunction + + +" class VEFilePanel {{{1 +"============================= +let s:VEFilePanel = {} +let s:VEFilePanel.fileList = [] +let s:VEFilePanel.displayList = [] +" displayList [ +" [ "display name", "real path" ], +" ... +" ] +let s:VEFilePanel.selectedFiles = [] +let s:VEFilePanel.leavePosition = {} +let s:VEFilePanel.name = '' +let s:VEFilePanel.path = '' +let s:VEFilePanel.width = 0 +let s:VEFilePanel.splitMode = "" +let s:VEFilePanel.splitLocation = "" + +function! s:VEFilePanel.init(name,path) + let self.name = "VEFilePanel".a:name + let self.path = a:path + let self.splitMode = g:VEConf.filePanelSplitMode + let self.splitLocation = g:VEConf.filePanelSplitLocation + let self.width = g:VEConf.filePanelWidth +endfunction + +function! s:VEFilePanel.show() + if self.setFocus() + return + endif + let cmd = self.splitLocation . " " . self.splitMode . ' ' . self.width . ' new ' . self.name + silent! exec cmd + if !self.setFocus() + echoerr "create file window failed!" + endif + setlocal winfixwidth + setlocal noswapfile + setlocal buftype=nowrite + setlocal bufhidden=delete + setlocal nowrap + setlocal foldcolumn=0 + setlocal nobuflisted + setlocal nospell + setlocal nonumber + setlocal cursorline + setlocal readonly + setlocal nomodifiable + setlocal tabstop=40 + "This is used to display file list more orderliness. + call self.refresh() + call self.createActions() + call self.createSyntax() +endfunction + +function! s:VEFilePanel.only() + if !self.setFocus() + return + endif + only +endfunction + +function! s:VEFilePanel.hide() + if !self.setFocus() + return + else + let bufNr = bufnr('%') + exec "wincmd c" + exec "bwipeout ".bufNr + endif +endfunction + +function! s:VEFilePanel.refresh() + call self.getFileListFromCwd() + call self.updateDisplayList() + call self.drawList() +endfunction + +"Draw the displayList on the screen. +function! s:VEFilePanel.drawList() + if !self.setFocus() + return + endif + "calculate window width + let VEFileWinNr = bufwinnr(self.name) + let winWidth = winwidth(VEFileWinNr) + exec "setlocal tabstop=" . ((winWidth-41)<20?20:(winWidth-41)) + setlocal noreadonly + setlocal modifiable + let curLine = line(".") + normal! H + let Hline = line(".") + silent normal! ggdG + let displayContent = [] + for i in self.displayList "here i is reference,not copy + if index(self.selectedFiles,i[1]) != -1 + let tmpi = '*' . substitute(i[0],'^.','','g') + else + let tmpi = i[0] + endif + call add(displayContent,tmpi) + endfor + call append(0,displayContent) + normal! Gddgg + exec "normal! " . Hline . "G" + normal! zt + exec "normal! " . curLine . "G" + setlocal readonly + setlocal nomodifiable +endfunction + +"Update the displayList. +function! s:VEFilePanel.updateDisplayList() + if g:VEConf.filePanelSortType == 1 + call self.sortByName() + elseif g:VEConf.filePanelSortType == 2 + call self.sortByTime() + else + call self.sortByType() + endif +endfunction + +function! s:VEFilePanel.toggleModes() + if g:VEConf.filePanelSortType < 2 + let g:VEConf.filePanelSortType = g:VEConf.filePanelSortType + 1 + else + let g:VEConf.filePanelSortType = 0 + endif + call self.updateDisplayList() + call self.drawList() +endfunction + +function! s:VEFilePanel.getFileListFromCwd() + let self.fileList = split(g:VEPlatform.globpath_file(self.path),"\n") +endfunction + +" 1 +function! s:VEFilePanel.sortByName() + let fileGroup = {} + " example + " { + " "name" : "path" + " } + for i in self.fileList + if g:VEPlatform.haswin32() && !&ssl + let name = matchstr(i,'[^\\]*$','','g') + else + let name = matchstr(i,'[^/]*$','','g') + endif + if isdirectory(i) + if g:VEPlatform.haswin32() && !&ssl + if i[-1:] != "\\" + let i = i . "\\" + endif + else + if i[-1:] != "/" + let i = i . "/" + endif + endif + " add # before directory to sort separately. + let name = '#' . name + endif + let fileGroup[name] = i + endfor + let keys = sort(keys(fileGroup),"VEPlatform_sortCompare") + if !g:VEConf.fileGroupSortDirection + call reverse(keys) + endif + let self.displayList = [] + call add(self.displayList,["Path: ".self.path,'']) + call add(self.displayList,[repeat("~",100),'']) + call add(self.displayList,['[ Sort by name ]','']) + for i in keys + call add(self.displayList,[" " . g:VEPlatform.pathToName(fileGroup[i]),fileGroup[i]]) + endfor +endfunction + +" 2 +function! s:VEFilePanel.sortByTime() + let fileGroup = {} + " example + " { + " "name" : "path" + " } + for i in self.fileList + let time = strftime("%Y-%m-%d %H:%M:%S",getftime(i)) + let time = time . i "let the key of dict unique + if isdirectory(i) + if g:VEPlatform.haswin32() && !&ssl + if i[-1:] != "\\" + let i = i . "\\" + endif + else + if i[-1:] != "/" + let i = i . "/" + endif + endif + endif + let fileGroup[time] = i + endfor + let keys = sort(keys(fileGroup),"VEPlatform_sortCompare") + if !g:VEConf.fileGroupSortDirection + call reverse(keys) + endif + let self.displayList = [] + call add(self.displayList,["Path: ".self.path,'']) + call add(self.displayList,[repeat("~",100),'']) + call add(self.displayList,['[ Sort by time ]','']) + for i in keys + call add(self.displayList,[" " . g:VEPlatform.pathToName(fileGroup[i]),fileGroup[i]]) + endfor +endfunction + +" 3 not implemented yet +"function! s:VEFilePanel.sortBySize() +" let fileGroup = {} +" " example +" " { +" " "name" : "path" +" " } +" for i in self.fileList +" let time = strftime("%Y-%m-%d %H:%M:%S",getftime(i)) +" let time = time . i "let the key of dict unique +" if isdirectory(i) +" " add # before directory to sort separately. +" " need?? +" "let time = '#' . time +" if i[-1:] != "\\" +" let i = i . "\\" +" endif +" endif +" let fileGroup[time] = i +" endfor +" let keys = sort(keys(fileGroup)) +" if !g:VEConf.fileGroupSortDirection +" call reverse(keys) +" endif +" let self.displayList = [] +" call add(self.displayList,["Path: ".self.path,'']) +" call add(self.displayList,[repeat("~",100),'']) +" call add(self.displayList,['[ Sort by time ]','']) +" for i in keys +" call add(self.displayList,[" " . g:VEPlatform.pathToName(fileGroup[i]),fileGroup[i]]) +" endfor +"endfunction + +" 0 +function! s:VEFilePanel.sortByType() + let fileGroup = {} + " example + " { + " "directory" : [ + " "c:\\aaa\\", + " "c:\\bbb\\" + " ] + " "txt" : [ + " "c:\\mm.txt", + " "c:\\nn.txt" + " ] + " } + for i in self.fileList + " i ("c:\\ddd\\eee.fff") + if isdirectory(i) + "if the group dos not exist,create it first + if !has_key(fileGroup,'#Directory') "assert file name does not contain '#' + let fileGroup['#Directory'] = [] + endif + if g:VEPlatform.haswin32() && !&ssl + if i[-1:] != "\\" + let i = i . "\\" + endif + else + if i[-1:] != "/" + let i = i . "/" + endif + endif + call add(fileGroup['#Directory'],i) + continue + endif + if g:VEPlatform.haswin32() && !&ssl + let matchStr = '\\\.[^\\]\+$' + else + let matchStr = '\/\.[^/]\+$' + endif + if matchstr(i,matchStr) != '' + if !has_key(fileGroup,'#Hidden files') + let fileGroup['#Hidden files'] = [] + endif + call add(fileGroup['#Hidden files'],i) + continue + endif + if g:VEPlatform.haswin32() && !&ssl + let fileExtension = matchstr(substitute(i,'^.*\\','','g'),'\.[^.]\{-}$') + else + let fileExtension = matchstr(substitute(i,'^.*\/','','g'),'\.[^.]\{-}$') + endif + if fileExtension == '' "files have no extensions + if !has_key(fileGroup,'#Files') + let fileGroup['#Files'] = [] + endif + call add(fileGroup['#Files'],i) + continue + else "group the file by it's ext.name + " # is always smaller than $ + " so it can keep dir in the top + if !has_key(fileGroup,"$".fileExtension) + let fileGroup["$".fileExtension] = [] + endif + call add(fileGroup["$".fileExtension],i) + endif + endfor + "update self.displayList + let self.displayList = [] + call add(self.displayList,["Path: ".self.path,'']) + call add(self.displayList,[repeat("~",100),'']) + let keys = sort(keys(fileGroup),"VEPlatform_sortCompare") + if !g:VEConf.fileGroupSortDirection + call reverse(keys) + endif + for i in keys + call add(self.displayList,['[ '.i[1:].' ]','']) + call sort(fileGroup[i],"VEPlatform_sortCompare") + if !g:VEConf.fileGroupSortDirection + call reverse(fileGroup[i]) + endif + for j in fileGroup[i] + call add(self.displayList,[" " . g:VEPlatform.pathToName(j),j]) + endfor + call add(self.displayList,[" ",'']) + endfor + if self.displayList[-1][0] == " " + call remove(self.displayList,-1) "remove last empty line + endif +endfunction + +function! s:VEFilePanel.pathChanged(path) + call self.setFocus() + if self.path == a:path + return + endif + "store the current mouse position. + let linePos = line('.') + normal! H + let topPos = line('.') + let self.leavePosition[self.path] = [topPos,linePos] + " + call g:VEPlatform.cdToPath(a:path) + let self.selectedFiles = [] "clear the selectedFile list + let self.path = g:VEPlatform.getcwd() + call self.refresh() + "restore position + if has_key(self.leavePosition,self.path) + exec "normal! " . self.leavePosition[self.path][0] . "G" + normal! zt + exec "normal! " . self.leavePosition[self.path][1] . "G" + else + normal! ggM + if line('.') < 4 "put the cursor to first dir. + normal! 4G + endif + endif +endfunction + +function! s:VEFilePanel.setFocus() + let VEFileWinNr = bufwinnr(self.name) + if VEFileWinNr != -1 + exec VEFileWinNr . " wincmd w" + return 1 + else + "If the window of buffer was closed by hand and the + "buffer still in buffer list, wipeout it. + "In case of bufnr() returns empty when there are two + "buffers have the same name. + let bufNr = bufnr(self.name) + if bufNr != -1 + exec "bwipeout " . bufNr + endif + return 0 + endif +endfunction + +function! s:VEFilePanel.itemClicked(line) + let path = self.displayList[a:line][1] + if path == '' + return + endif + if isdirectory(path) + call VE_GotoPath(path) + call self.setFocus() + return + else + call g:VEPlatform.start(path) + endif +endfunction + +function! s:VEFilePanel.itemPreview(line) + let path = self.displayList[a:line][1] + if path == '' + return + endif + exec g:VEConf.previewSplitLocation . " pedit " . g:VEPlatform.escape(path) +endfunction + +function! s:VEFilePanel.singleFileAction(line,actionName) + let path = self.displayList[a:line][1] + if path == '' + return + endif + call g:VEConf_singleFileActions[a:actionName](path) +endfunction + +function! s:VEFilePanel.normalAction(actionName) + call g:VEConf_normalActions[a:actionName]() +endfunction + +function! s:VEFilePanel.multiAction(actionName) + call g:VEConf_multiFileActions[a:actionName](self.selectedFiles) +endfunction + +function! s:VEFilePanel.deleteSingle(line,bForce) + let path = self.displayList[a:line][1] + if path == '' + return + endif + if g:VEPlatform.deleteSingle(path,a:bForce) + if index(self.selectedFiles,path) != -1 + call remove(self.selectedFiles,index(self.selectedFiles,path)) + endif + call self.refresh() + endif +endfunction + +function! s:VEFilePanel.deleteSelectedFiles(bForce) + if empty(self.selectedFiles) + return + endif + if g:VEPlatform.deleteMultiple(self.selectedFiles,a:bForce) + let self.selectedFiles = [] + call self.refresh() + endif +endfunction + +function! s:VEFilePanel.toggleSelect(direction) + if a:direction == "up" + exec "norm " . "\" + endif + let line = line(".") - 1 + let path = self.displayList[line][1] + if path != '' + let idx = index(self.selectedFiles,path) + if idx == -1 + call add(self.selectedFiles,path) + else + call remove(self.selectedFiles,idx) + endif + call self.drawList() + endif + if a:direction == "down" + exec "norm " . "\" + endif +endfunction! + +function! s:VEFilePanel.clearSelect() + let self.selectedFiles = [] + call self.drawList() +endfunction + +function! s:VEFilePanel.visualSelect(firstLine,lastLine) + for line in range(a:firstLine,(a:lastLine>=len(self.displayList)?(len(self.displayList)-1):a:lastLine)) + let path = self.displayList[line][1] + if path == '' + continue + endif + let idx = index(self.selectedFiles,path) + if idx == -1 + call add(self.selectedFiles,path) + else + call remove(self.selectedFiles,idx) + endif + endfor + call self.drawList() +endfunction + +function! s:VEFilePanel.visualDelete(firstLine,lastLine,bForce) + let displayList = [] + for line in range(a:firstLine,(a:lastLine>=len(self.displayList)?(len(self.displayList)-1):a:lastLine)) + let path = self.displayList[line][1] + if path == '' + continue + endif + call add(displayList,path) + endfor + if empty(displayList) + return + endif + if g:VEPlatform.deleteMultiple(displayList,a:bForce) + call self.refresh() + endif +endfunction + +function! s:VEFilePanel.visualYank(firstLine,lastLine,mode) + let displayList = [] + for line in range(a:firstLine,(a:lastLine>=len(self.displayList)?(len(self.displayList)-1):a:lastLine)) + let path = self.displayList[line][1] + if path == '' + continue + endif + call add(displayList,path) + endfor + if empty(displayList) + return + endif + let winName = matchstr(bufname("%"),'_[^_]*$') + let s:VEContainer.yankMode = a:mode + let s:VEContainer.clipboard = displayList + call s:VEContainer.showClipboard() +endfunction + +function! s:VEFilePanel.yankSingle(mode) + let line = line(".") - 1 + let path = self.displayList[line][1] + if path != '' + let s:VEContainer.yankMode = a:mode + let s:VEContainer.clipboard = [] + call add(s:VEContainer.clipboard,path) + endif + call s:VEContainer.showClipboard() +endfunction + +function! s:VEFilePanel.paste() + if s:VEContainer.yankMode == '' || s:VEContainer.clipboard == [] + return + endif + let retList = g:VEPlatform.copyMultiFile(s:VEContainer.clipboard,self.path) + if s:VEContainer.yankMode == 'cut' && len(retList) != 0 + "let tmpRec = g:VEConf.recyclePath " save recycle path + "let g:VEConf.recyclePath = '' + for i in retList + call g:VEPlatform.delete(i,1) "force delete + endfor + "let g:VEConf.recyclePath = tmpRec + let s:VEContainer.yankMode = '' + let s:VEContainer.clipboard = [] + endif + "if s:VEContainer.yankMode == 'cut' + " call g:VEPlatform.copyMultiFile(s:VEContainer.clipboard,self.path,1) + "else + " call g:VEPlatform.copyMultiFile(s:VEContainer.clipboard,self.path,0) + "endif + let s:VEContainer.yankMode = '' + let s:VEContainer.clipboard = [] + call self.refresh() + "call s:VEContainer.showClipboard() +endfunction! + +function! s:VEFilePanel.markViaRegexp(regexp) + if a:regexp == '' + echohl Special + let regexp = input("Mark files (regexp): ") + echohl None + else + let regexp = a:regexp + endif + let self.selectedFiles = [] + for i in self.displayList + if g:VEPlatform.haswin32() && !&ssl + let name = matchstr(i[1],'[^\\]*.$','','g') + else + let name = matchstr(i[1],'[^/]*.$','','g') + endif + if matchstr(name,regexp) != '' + call add(self.selectedFiles,i[1]) + endif + endfor + call self.drawList() +endfunction + +function! s:VEFilePanel.markExecutable() + let self.selectedFiles = [] + for i in self.displayList + if g:VEPlatform.executable(i[1]) + call add(self.selectedFiles,i[1]) + endif + endfor + call self.drawList() +endfunction + +function! s:VEFilePanel.newFile() + echohl Special + let filename = input("Create file : ",self.path,"file") + echohl None + if filename == '' + echo " " + return + endif + if g:VEPlatform.mkfile(filename) + echohl Special | echomsg "OK" | echohl None + call self.refresh() + else + echohl ErrorMsg | echomsg "Can not create file!" | echohl None + endif +endfunction + +function! s:VEFilePanel.newDirectory() + if !exists("*mkdir") + echoerr "mkdir feature not found!" + endif + echohl Special + let dirname = input("Create directory : ",self.path,"file") + echohl None + if dirname == '' + echo " " + return + endif + if findfile(dirname) == '' && g:VEPlatform.mkdir(dirname) + echohl Special | echomsg "OK" | echohl None + call self.refresh() + else + echohl ErrorMsg | echomsg "Can not create directory!" | echohl None + endif +endfunction + +function! s:VEFilePanel.rename(line) + let path = self.displayList[a:line][1] + if path == '' + return + endif + echohl Special + let name = input("Rename to: ",path,"file") + echohl None + if name == '' + echo " " + return + endif + if findfile(name) != '' + echohl ErrorMsg | echomsg "File exists!" | echohl None + return + endif + if rename(path,name) == 0 + echohl Special | echomsg "OK" | echohl None + call self.refresh() + else + echohl ErrorMsg | echomsg "Can not rename!" | echohl None + endif +endfunction + +function! s:VEFilePanel.search() + echohl Special + let filename = input("Search : ") + echohl None + if filename == '' + echo " " + return + endif + echohl Special | echomsg "Searching [" . filename . "] in " . self.path . ", please wait...(Ctrl-C to break)" | echohl None + let self.fileList = g:VEPlatform.search(filename,self.path) + call self.updateDisplayList() + call self.drawList() +endfunction + +function! s:VEFilePanel.statusFileName() + let line = line(".") - 1 + let fname = self.displayList[line][1] + "let fname = substitute(fname,self.path,'','g') + let fname = fname[len(self.path):] + return fname +endfunction + +function! s:VEFilePanel.createActions() + exec "nnoremap " . g:VEConf.filePanelHotkey.help . " :tab h VimExplorer" + exec "nnoremap " . g:VEConf.filePanelHotkey.switchPanel . " " + exec "nnoremap " . g:VEConf.filePanelHotkey.itemClicked . " :call VE_OnFileItemClick()" + exec "nnoremap " . g:VEConf.filePanelHotkey.itemClickMouse. " :call VE_OnFileItemClick()" + exec "nnoremap " . g:VEConf.filePanelHotkey.toggleTreePanel ." :call VE_ToggleTreePanel()" + exec "nnoremap " . g:VEConf.filePanelHotkey.toUpperDir . " :call VE_ToUpperDir()" + exec "nnoremap " . g:VEConf.filePanelHotkey.gotoForward . " :call VE_GotoForward()" + exec "nnoremap " . g:VEConf.filePanelHotkey.gotoBackward . " :call VE_GotoBackward()" + exec "nnoremap " . g:VEConf.filePanelHotkey.openPreview . " :call VE_OnFileOpenPreview()" + exec "nnoremap " . g:VEConf.filePanelHotkey.closePreview . " :call VE_ClosePreviewPanel()" + exec "nnoremap " . g:VEConf.filePanelHotkey.deleteSingle . " :call VE_DeleteSingle(0)" + exec "nnoremap " . g:VEConf.filePanelHotkey.deleteSingleF. " :call VE_DeleteSingle(1)" + exec "nnoremap " . g:VEConf.filePanelHotkey.rename . " :call VE_Rename()" + exec "nnoremap " . g:VEConf.filePanelHotkey.refresh . " :call VE_RefreshFilePanel()" + exec "nnoremap " . g:VEConf.filePanelHotkey.toggleSelectUp ." :call VE_ToggleSelectFile(\"up\")" + exec "nnoremap " . g:VEConf.filePanelHotkey.toggleSelectDown." :call VE_ToggleSelectFile(\"down\")" + exec "nnoremap " . g:VEConf.filePanelHotkey.clearSelect . " :call VE_ClearSelectFile()" + exec "nnoremap " . g:VEConf.filePanelHotkey.deleteSelected . " :call VE_DeleteSelectedFiles(0)" + exec "nnoremap " . g:VEConf.filePanelHotkey.deleteSelectedF. " :call VE_DeleteSelectedFiles(1)" + exec "nnoremap " . g:VEConf.filePanelHotkey.yankSelected . " :call VE_YankSelectedFiles(\"copy\")" + exec "nnoremap " . g:VEConf.filePanelHotkey.cutSelected . " :call VE_YankSelectedFiles(\"cut\")" + exec "nnoremap " . g:VEConf.filePanelHotkey.yankSingle . " :call VE_YankSingle(\"copy\")" + exec "nnoremap " . g:VEConf.filePanelHotkey.cutSingle . " :call VE_YankSingle(\"cut\")" + exec "nnoremap " . g:VEConf.filePanelHotkey.showYankList . " :call VE_ShowYankList()" + exec "nnoremap " . g:VEConf.filePanelHotkey.toggleModes . " :call VE_ToggleModes()" + exec "nnoremap " . g:VEConf.filePanelHotkey.paste . " :call VE_Paste()" + exec "nnoremap " . g:VEConf.filePanelHotkey.markViaRegexp . " :call VE_MarkViaRegexp('')" + exec "nnoremap " . g:VEConf.filePanelHotkey.markExecutable . " :call VE_MarkExecutable()" + exec "nnoremap " . g:VEConf.filePanelHotkey.markVimFiles . " :call VE_MarkViaRegexp('.*.vim$')" + exec "nnoremap " . g:VEConf.filePanelHotkey.markDirectory . " :call VE_MarkViaRegexp('.*[\\/]$')" + exec "nnoremap " . g:VEConf.filePanelHotkey.newFile . " :call VE_NewFile()" + exec "nnoremap " . g:VEConf.filePanelHotkey.newDirectory . " :call VE_NewDirectory()" + exec "nnoremap " . g:VEConf.filePanelHotkey.markViaRegexp . " :call VE_MarkViaRegexp('')" + exec "nnoremap " . g:VEConf.filePanelHotkey.favorite . " :call VE_GotoFavorite()" + exec "nnoremap " . g:VEConf.filePanelHotkey.addToFavorite . " :call VE_AddToFavorite('filePanel')" + exec "nnoremap " . g:VEConf.filePanelHotkey.browseHistory . " :call VE_BrowseHistory()" + exec "nnoremap " . g:VEConf.filePanelHotkey.gotoPath . " :call VE_OpenPath()" + exec "nnoremap " . g:VEConf.filePanelHotkey.diff2files . " :call VE_Diff()" + exec "nnoremap " . g:VEConf.filePanelHotkey.quitVE . " :call VEDestroy()" + exec "nnoremap " . g:VEConf.filePanelHotkey.toggleHidden . " :call VE_ToggleHidden()" + exec "nnoremap " . g:VEConf.filePanelHotkey.search . " :call VE_FileSearch()" + exec "nnoremap " . g:VEConf.filePanelHotkey.toggleSelMouse . " :call VE_ToggleSelectFile(\"\")" + exec "nnoremap " . g:VEConf.filePanelHotkey.contextMenuN . " :popup ]FilePanelPopup" + + let letter = char2nr('a') + while letter <= char2nr('z') + exec "nnoremap " . g:VEConf.filePanelHotkey.markPlace . nr2char(letter) . + \" :call VE_MarkPlace(\"" . nr2char(letter) . "\")" + exec "nnoremap " . g:VEConf.filePanelHotkey.gotoPlace . nr2char(letter) . + \" :call VE_MarkSwitchTo(\"" . nr2char(letter) . "\")" + let letter = letter + 1 + endwhile + exec "nnoremap " . g:VEConf.filePanelHotkey.viewMarks . " :call VE_MarkList()" + + " visual mode map + exec "vnoremap " . g:VEConf.filePanelHotkey.visualSelect . " :call VE_VisualSelect()" + exec "vnoremap " . g:VEConf.filePanelHotkey.visualDelete . " :call VE_VisualDelete(0)" + exec "vnoremap " . g:VEConf.filePanelHotkey.visualDeleteF. " :call VE_VisualDelete(1)" + exec "vnoremap " . g:VEConf.filePanelHotkey.visualYank . " :call VE_VisualYank(\"copy\")" + exec "vnoremap " . g:VEConf.filePanelHotkey.visualCut . " :call VE_VisualYank(\"cut\")" + + " User defined map + for i in keys(g:VEConf_normalHotKeys) + exec "nnoremap " . g:VEConf_normalHotKeys[i] . + \" :call VE_NormalAction(\"" . i . "\")" + endfor + for i in keys(g:VEConf_singleFileHotKeys) + exec "nnoremap " . g:VEConf_singleFileHotKeys[i] . + \" :call VE_SingleFileAction(\"" . i . "\")" + endfor + for i in keys(g:VEConf_multiFileHotKeys) + exec "nnoremap " . g:VEConf_multiFileHotKeys[i] . + \" :call VE_MultiFileAction(\"" . i . "\")" + endfor + " Auto commands + au! * + au BufEnter call VE_SyncDir() + " Status line + setlocal statusline=%{VE_GetStatusFileName()}%=[%{getcwd()}]\ %{strftime(\"\%Y-\%m-\%d\ \%H:\%M\")} +endfunction + +function! s:VEFilePanel.createSyntax() + let VEFileWinNr = bufwinnr(self.name) + if VEFileWinNr != -1 + exec VEFileWinNr . " wincmd w" + else + return + endif + call g:VEConf.filePanelSyntax() +endfunction + +function! s:VEFilePanel.getPathUnderCursor(num) + return self.displayList[a:num][1] +endfunction + +" class VEPreviewPanel {{{1 +"============================= +"let s:VEPreviewPanel = {} +"let s:VEPreviewPanel.name = '' +"let s:VEPreviewPanel.width = 0 +"let s:VEPreviewPanel.splitMode = '' +"let s:VEPreviewPanel.splitLocation = '' +" +"function! s:VEPreviewPanel.init(name) +" let self.name = "VEPreviewPanel" . a:name +" let self.width = g:VEConf.previewPanelWidth +" let self.splitMode = g:VEConf.previewPanelSplitMode +" let self.splitLocation = g:VEConf.previewPanelSplitLocation +"endfunction + +"function! s:VEPreviewPanel.show() +" if self.setFocus() +" return +" endif +" let cmd = self.splitLocation . " " . self.splitMode . self.width . ' new ' +" exec cmd +" if !self.setFocus() +" echoerr "create file window failed!" +" else +" edit self.name +" endif +"endfunction + +"function! s:VEPreviewPanel.setFocus() +" let VEPreviewWinNr = bufwinnr(self.name) +" if VEPreviewWinNr != -1 +" exec VEPreviewWinNr . " wincmd w" +" return 1 +" else +" "If the window of buffer was closed by hand and the +" "buffer still in buffer list, wipeout it. +" "In case of bufnr() returns empty when there are two +" "buffers have the same name. +" let bufNr = bufnr(self.name) +" if bufNr != -1 +" exec "bwipeout " . bufNr +" endif +" return 0 +" endif +"endfunction +" +"function! s:VEPreviewPanel.hide() +" if !self.setFocus() +" return +" else +" let bufNr = bufnr('%') +"" exec "wincmd c" +" exec "bwipeout ".bufNr +" endif +"endfunction +" +"function! s:VEPreviewPanel.preview(path) +" if !self.setFocus() +" let self.name = a:path +" let cmd = self.splitLocation . " " . self.splitMode . self.width . ' new' +" exec cmd +" exec "edit " . self.name +" return +" else +" let self.name = a:path +" exec "edit " . self.name +" endif +"endfunction + + + +" class VEFrameWork {{{1 +"============================= +let s:VEFrameWork = {} +let s:VEFrameWork.name = '' +let s:VEFrameWork.treePanel = {} +let s:VEFrameWork.filePanel = {} +"let s:VEFrameWork.previewPanel = {} +let s:VEFrameWork.pathHistory = [] +let s:VEFrameWork.pathPosition = -1 + +"Object Constructor +function! s:VEFrameWork.init(name,path) + let self.name = "VEFrameWork".a:name + let self.filePanel = deepcopy(s:VEFilePanel) + let self.treePanel = deepcopy(s:VETreePanel) + "let self.previewPanel = deepcopy(s:VEPreviewPanel) + call self.filePanel.init(a:name,a:path) + call self.treePanel.init(a:name,a:path) + "call self.previewPanel.init(a:name) + call add(self.pathHistory,a:path) + let self.pathPosition += 1 +endfunction + +function! s:VEFrameWork.show() + tabnew + call self.filePanel.show() + call self.filePanel.only() "so,here it means filePanel should be displayed first + call self.treePanel.show() + call self.filePanel.setFocus() + call self.filePanel.refresh() + normal! M +endfunction + +"Switch to another path, it will change the forward/backward +"history. +function! s:VEFrameWork.gotoPath(path) + call self.treePanel.pathChanged(a:path) + call self.filePanel.pathChanged(a:path) + if len(self.pathHistory) > self.pathPosition+1 + call remove(self.pathHistory,self.pathPosition+1,-1) + endif + call add(self.pathHistory,a:path) + if len(self.pathHistory) > g:VEConf.browseHistory + call remove(self.pathHistory,0) + else + let self.pathPosition += 1 + endif +endfunction + +"Forward and backward +function! s:VEFrameWork.gotoForward() + if self.pathPosition >= len(self.pathHistory) || + \ self.pathPosition < 0 || + \ empty(self.pathHistory) + return + endif + if self.pathPosition+1 == len(self.pathHistory) "Can not forward + return + endif + let self.pathPosition += 1 + "Do not call VE_GotoPath here! It will change pathHistory. + "Call the follows instead. + call self.treePanel.pathChanged(self.pathHistory[self.pathPosition]) + call self.filePanel.pathChanged(self.pathHistory[self.pathPosition]) +endfunction + +function! s:VEFrameWork.gotoBackward() + if self.pathPosition >= len(self.pathHistory) || + \ self.pathPosition < 0 || + \ empty(self.pathHistory) + return + endif + if self.pathPosition == 0 "Can not go back. + return + endif + let self.pathPosition -= 1 + "Do not call VE_GotoPath here! It will change pathHistory. + "Call the follows instead. + call self.treePanel.pathChanged(self.pathHistory[self.pathPosition]) + call self.filePanel.pathChanged(self.pathHistory[self.pathPosition]) +endfunction + +"Object destructor +function! s:VEFrameWork.destroy() + call self.filePanel.hide() + call self.treePanel.hide() +endfunction + + + + + + +"#################################################### +"global variables and functions {{{1 + +let s:VEContainer = {} "contains all VEFrameWorks +let s:VEContainer.clipboard = [] "shared clipboard +let s:VEContainer.yankMode = '' "cut or yank +let s:VEContainer.markPlaces = {} + +function! s:VECreatePopMenu() + silent! unmenu ]FilePanelPopup + menu ]FilePanelPopup.&Open :call VE_OnFileItemClick() + menu ]FilePanelPopup.-sep0- : + menu ]FilePanelPopup.&Copy :call VE_YankSingle("copy") + menu ]FilePanelPopup.C&ut :call VE_YankSingle("cut") + menu ]FilePanelPopup.-sep1- : + menu ]FilePanelPopup.&Rename :call VE_Rename() + menu ]FilePanelPopup.&Delete :call VE_DeleteSingle(0) + menu ]FilePanelPopup.Pre&view :call VE_OnFileOpenPreview() + menu ]FilePanelPopup.&Mark :call VE_ToggleSelectFile("") + menu ]FilePanelPopup.-sep2- : + menu ]FilePanelPopup.&Paste :call VE_Paste() + menu ]FilePanelPopup.&New.&File :call VE_NewFile() + menu ]FilePanelPopup.&New.&Directory :call VE_NewDirectory() + menu ]FilePanelPopup.-sep3- : + menu ]FilePanelPopup.Re&fresh :call VE_RefreshFilePanel() +endfunction + +function! VENew(path) + call s:VECreatePopMenu() + let frameName = '_' . substitute(reltimestr(reltime()),'\.','','g') + if a:path == '' + echohl Special + let workPath = input("VimExplorer (directory): ",g:VEPlatform.getcwd(),"file") + echohl None + if workPath == '' + return + endif + else + let workPath = a:path + endif + call g:VEPlatform.cdToPath(workPath) + let workPath = g:VEPlatform.getcwd() "Conversions capitalisations + "does not work here. + if !isdirectory(workPath) + echohl ErrorMsg | echomsg "Directory not exist!" | echohl None + return + endif + let s:VEContainer[frameName] = deepcopy(s:VEFrameWork) + call s:VEContainer[frameName].init(frameName,workPath) + call s:VEContainer[frameName].show() + let letter = char2nr('a') + while letter <= char2nr('z') + let s:VEContainer.markPlaces[nr2char(letter)] = '' + let letter = letter + 1 + endwhile +endfunction + +function! VEDestroy() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].destroy() + call remove(s:VEContainer,winName) + endif +endfunction + +function! s:VEContainer.showClipboard() + echohl Special + let msg = len(self.clipboard) . " files in clipboard, Mode: " . self.yankMode . ", " + let msg = msg . '(press ' . g:VEConf.filePanelHotkey.showYankList . ' to show file list)' + echomsg msg + echohl None +endfunction + +" Get path name under cursor +function! VE_getPathUnderCursor(where) + let winName = matchstr(bufname("%"),'_[^_]*$') + let path = '' + if has_key(s:VEContainer,winName) + if a:where == 'treePanel' + let path = s:VEContainer[winName].treePanel.getPathUnderCursor(line(".")-1) + elseif a:where == 'filePanel' + let path = s:VEContainer[winName].filePanel.getPathUnderCursor(line(".")-1) + endif + endif + + if !isdirectory(path) + return '' + else + return path + endif +endfunction + + +"Command handlers +"=================================== + +"TreePanel command handlers +"---------------------------- +"Node click event +function! VE_OnTreeNodeClick() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].treePanel.nodeClicked(line(".")-1) + endif +endfunction + +"Refresh tree command +function! VE_TreeRefresh() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].treePanel.refresh() + endif +endfunction + +"FilePanel command handlers +"---------------------------- +"Item click event. +function! VE_OnFileItemClick() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.itemClicked(line(".")-1) + endif +endfunction + +"Open preview. +function! VE_OnFileOpenPreview() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.itemPreview(line(".")-1) + endif +endfunction + +"Refresh the panel. +function! VE_RefreshFilePanel() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.refresh() + endif +endfunction + +"User defined single file actions. +function! VE_SingleFileAction(actionName) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.singleFileAction((line(".")-1),a:actionName) + endif +endfunction + +"User defined normal actions. +function! VE_NormalAction(actionName) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.normalAction(a:actionName) + endif +endfunction + +"Multiple file actions. +function! VE_MultiFileAction(actionName) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.multiAction(a:actionName) + endif +endfunction + +"Delete single file or directory. +function! VE_DeleteSingle(bForce) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.deleteSingle(line(".")-1,a:bForce) + endif +endfunction + +"Rename file or dir +function! VE_Rename() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.rename(line(".")-1) + endif +endfunction + +"Toggle select a file in file panel. +function! VE_ToggleSelectFile(direction) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.toggleSelect(a:direction) + endif +endfunction + +"Clear selection. +function! VE_ClearSelectFile() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.clearSelect() + endif +endfunction + +"Toggle sort mode +function! VE_ToggleModes() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.toggleModes() + endif +endfunction + +"Mark via regexp +function! VE_MarkViaRegexp(regexp) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.markViaRegexp(a:regexp) + endif +endfunction + +"Mark executable files. +function! VE_MarkExecutable() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.markExecutable() + endif +endfunction + +"create file +function! VE_NewFile() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.newFile() + endif +endfunction + +"create directory +function! VE_NewDirectory() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.newDirectory() + endif +endfunction + +"delete selected files. +function! VE_DeleteSelectedFiles(bForce) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.deleteSelectedFiles(a:bForce) + endif +endfunction + +"delete selected files. +function! VE_YankSelectedFiles(mode) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + let s:VEContainer.clipboard = s:VEContainer[winName].filePanel.selectedFiles + let s:VEContainer.yankMode = a:mode + endif + call s:VEContainer.showClipboard() +endfunction + +function! VE_YankSingle(mode) + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.yankSingle(a:mode) + endif +endfunction + +function! VE_Paste() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.paste() + endif +endfunction + +function! VE_FileSearch() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.search() + endif +endfunction + + +"visual mode functions. +"visual select +function! VE_VisualSelect() range + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.visualSelect(a:firstline-1,a:lastline-1) + endif +endfunction + +"visual delete +function! VE_VisualDelete(bForce) range + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.visualDelete(a:firstline-1,a:lastline-1,a:bForce) + endif +endfunction + +"visual yank +function! VE_VisualYank(mode) range + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].filePanel.visualYank(a:firstline-1,a:lastline-1,a:mode) + endif +endfunction + +function! VE_ShowYankList() + if s:VEContainer.clipboard == [] + return + endif + for i in s:VEContainer.clipboard + echo i + endfor +endfunction + +"Common command handlers +"-------------------------- +"get file name for status line. +function! VE_GetStatusFileName() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + return s:VEContainer[winName].filePanel.statusFileName() + else + return '' + endif +endfunction + +"mark palce +function! VE_MarkPlace(char) + let s:VEContainer.markPlaces[a:char] = g:VEPlatform.getcwd() +endfunction + +"goto marked place +function! VE_MarkSwitchTo(char) + call VE_GotoPath(s:VEContainer.markPlaces[a:char]) +endfunction + +function! VE_MarkList() + let list = [] + let letter = char2nr('a') + while letter <= char2nr('z') + if s:VEContainer.markPlaces[nr2char(letter)] != '' + echo nr2char(letter) . " " . s:VEContainer.markPlaces[nr2char(letter)] + endif + let letter = letter + 1 + endwhile +endfunction + +"Toggle tree panel. +function! VE_ToggleTreePanel() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + if s:VEContainer[winName].treePanel.setFocus() + call s:VEContainer[winName].treePanel.hide() + else + call s:VEContainer[winName].treePanel.show() + endif + endif + exec "wincmd p" +endfunction + +"Toggle file panel. +function! VE_ToggleFilePanel() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + if s:VEContainer[winName].filePanel.setFocus() + call s:VEContainer[winName].filePanel.hide() + else + call s:VEContainer[winName].filePanel.show() + endif + endif + call s:VEContainer[winName].treePanel.setFocus() + exec g:VEConf.treePanelWidth . " wincmd |" +endfunction + +function! VE_ClosePreviewPanel() + pclose +endfunction + + +"Go to upper directory. +function! VE_ToUpperDir() + let winNr = bufwinnr('%') + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + let path = s:VEContainer[winName].filePanel.path + " Assert filePanel.path == treePanel.path + let upperPath = g:VEPlatform.getUpperDir(path) + if upperPath == path + return + endif + call VE_GotoPath(upperPath) + let dir = split(path,'/') + call search(" " . dir[-1] . "/\t") + endif + exec winNr . "wincmd w" +endfunction + +"Path change event +function! VE_GotoPath(path) + if !isdirectory(a:path) + return + endif + call g:VEPlatform.cdToPath(a:path) + let path = g:VEPlatform.getcwd() + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].gotoPath(path) + endif +endfunction + +"Used in +function! VE_OpenPath() + echohl Special + let workPath = input("Change path to (directory): ",'',"file") + echohl None + if workPath == '' + return + endif + call g:VEPlatform.cdToPath(workPath) + let workPath = g:VEPlatform.getcwd() + call VE_GotoPath(workPath) +endfunction + +"Goto forward +function! VE_GotoForward() + let winNr = bufwinnr('%') + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].gotoForward() + endif + exec winNr . "wincmd w" +endfunction + +"Goto backward +function! VE_GotoBackward() + let winNr = bufwinnr('%') + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + call s:VEContainer[winName].gotoBackward() + endif + exec winNr . "wincmd w" +endfunction + +"Favorite +function! VE_GotoFavorite() + let fav_filename = g:VEPlatform.getHome() . g:VEConf.favorite + if findfile(fav_filename)=='' || !filereadable(fav_filename) + return + endif + let fav = readfile(fav_filename) + let result = g:VEPlatform.select(fav,"Favorite folder list:") + if result == -1 + return + endif + call VE_GotoPath(fav[result]) +endfunction + +function! VE_AddToFavorite(where) + let winNr = bufwinnr('%') + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + let cwd = s:VEContainer[winName].filePanel.path + else + return + endif + let pathUnderCursor = VE_getPathUnderCursor(a:where) + if pathUnderCursor != '' + " if no path name under cursor, use current working path + let cwd = pathUnderCursor + endif + let fav_filename = g:VEPlatform.getHome() . g:VEConf.favorite + let fav = [] + if findfile(fav_filename) != '' + if !filereadable(fav_filename) + echoerr "Can not read favorite folder list!" + return + endif + if !filewritable(fav_filename) + echoerr "Can not write favorite folder list to file!" + return + endif + let fav = readfile(fav_filename) + endif + if index(fav,cwd) != -1 + "echohl WarningMsg | echomsg "Current directory already in the favorite list." | echohl None + echohl WarningMsg | echomsg "[ ".cwd." ] already in the favorite!" | echohl None + return + endif + call add(fav,cwd) + if writefile(fav,fav_filename) == 0 + echohl Special | echomsg "[ ".cwd." ] added to favorite." | echohl None + else + echoerr "Can not write favorite folder list to file!" + endif +endfunction + +"forward and backward history +function! VE_BrowseHistory() + let winNr = bufwinnr('%') + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + let pathlist = s:VEContainer[winName].pathHistory + let result = g:VEPlatform.select(pathlist,"Browse history:") + if result == -1 + return + else + call s:VEContainer[winName].treePanel.pathChanged(pathlist[result]) + call s:VEContainer[winName].filePanel.pathChanged(pathlist[result]) + let s:VEContainer[winName].pathPosition = result + endif + endif +endfunction + +"sync directory +function! VE_SyncDir() + let winNr = bufwinnr('%') + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + let path = s:VEContainer[winName].filePanel.path + call g:VEPlatform.cdToPath(path) + endif +endfunction + +"diff 2 files +function! VE_Diff() + let winNr = bufwinnr('%') + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + let diffFiles = s:VEContainer[winName].filePanel.selectedFiles + if len(diffFiles) != 2 || isdirectory(diffFiles[0]) || isdirectory(diffFiles[1]) + echohl WarningMsg | echo "Please select 2 files to diff!" | echohl None + return + endif + exec "tabe " . g:VEPlatform.escape(diffFiles[0]) + exec "vertical diffsplit " . g:VEPlatform.escape(diffFiles[1]) + endif +endfunction + +"toggle show hidden files +function! VE_ToggleHidden() + let winNr = bufwinnr('%') + let winName = matchstr(bufname("%"),'_[^_]*$') + if has_key(s:VEContainer,winName) + let g:VEConf.showHiddenFiles = !g:VEConf.showHiddenFiles + call s:VEContainer[winName].treePanel.refresh() + call s:VEContainer[winName].filePanel.refresh() + endif +endfunction + +command! -nargs=? -complete=file VE call VENew('') +command! -nargs=0 -complete=file VEC call VEDestroy() + + +"==================================================================== +" +" Function: s:InstallDocumentation(full_name, revision) +" Install help documentation. +" Arguments: +" full_name: Full name of this vim plugin script, including path name. +" revision: Revision of the vim script. #version# mark in the document file +" will be replaced with this string with 'v' prefix. +" Return: +" 1 if new document installed, 0 otherwise. +" Note: Cleaned and generalized by guo-peng Wen. +" +" Note about authorship: this function was taken from the vimspell plugin +" which can be found at http://www.vim.org/scripts/script.php?script_id=465 +" +function! s:InstallDocumentation(full_name, revision) + " Name of the document path based on the system we use: + if has("vms") + " No chance that this script will work with + " VMS - to much pathname juggling here. + return 1 + elseif (has("unix")) + " On UNIX like system, using forward slash: + let l:slash_char = '/' + let l:mkdir_cmd = ':silent !mkdir -p ' + else + " On M$ system, use backslash. Also mkdir syntax is different. + " This should only work on W2K and up. + let l:slash_char = '\' + let l:mkdir_cmd = ':silent !mkdir ' + endif + + let l:doc_path = l:slash_char . 'doc' + let l:doc_home = l:slash_char . '.vim' . l:slash_char . 'doc' + + " Figure out document path based on full name of this script: + let l:vim_plugin_path = fnamemodify(a:full_name, ':h') + let l:vim_doc_path = fnamemodify(a:full_name, ':h:h') . l:doc_path + if (!(filewritable(l:vim_doc_path) == 2)) + "Doc path: " . l:vim_doc_path + echo "Doc path: " . l:vim_doc_path + execute l:mkdir_cmd . '"' . l:vim_doc_path . '"' + if (!(filewritable(l:vim_doc_path) == 2)) + " Try a default configuration in user home: + let l:vim_doc_path = expand("~") . l:doc_home + if (!(filewritable(l:vim_doc_path) == 2)) + execute l:mkdir_cmd . '"' . l:vim_doc_path . '"' + if (!(filewritable(l:vim_doc_path) == 2)) + " Put a warning: + echo "Unable to open documentation directory" + echo "type :help add-local-help for more information." + echo l:vim_doc_path + return 0 + endif + endif + endif + endif + + " Exit if we have problem to access the document directory: + if (!isdirectory(l:vim_plugin_path) || !isdirectory(l:vim_doc_path) || filewritable(l:vim_doc_path) != 2) + return 0 + endif + + " Full name of script and documentation file: + let l:script_name = fnamemodify(a:full_name, ':t') + let l:doc_name = fnamemodify(a:full_name, ':t:r') . '.txt' + let l:plugin_file = l:vim_plugin_path . l:slash_char . l:script_name + let l:doc_file = l:vim_doc_path . l:slash_char . l:doc_name + + " Bail out if document file is still up to date: + if (filereadable(l:doc_file) && getftime(l:plugin_file) < getftime(l:doc_file)) + return 0 + endif + + " Prepare window position restoring command: + if (strlen(@%)) + let l:go_back = 'b ' . bufnr("%") + else + let l:go_back = 'enew!' + endif + + " Create a new buffer & read in the plugin file (me): + setl nomodeline + exe 'enew!' + exe 'r ' . l:plugin_file + + setl modeline + let l:buf = bufnr("%") + setl noswapfile modifiable + + norm zR + norm gg + + " Delete from first line to a line starts with + " === START_DOC + 1,/^=\{3,}\s\+START_DOC\C/ d + + " Delete from a line starts with + " === END_DOC + " to the end of the documents: + /^=\{3,}\s\+END_DOC\C/,$ d + + " Add modeline for help doc: the modeline string is mangled intentionally + " to avoid it be recognized by VIM: + call append(line('$'), '') + call append(line('$'), ' v' . 'im:tw=78:ts=8:ft=help:norl:') + + " Replace revision: + "exe "normal :1s/#version#/ v" . a:revision . "/\" + exe "normal :%s/#version#/ v" . a:revision . "/\" + + " Save the help document: + exe 'w! ' . l:doc_file + exe l:go_back + exe 'bw ' . l:buf + + " Build help tags: + exe 'helptags ' . l:vim_doc_path + + return 1 +endfunction + +" Doc installation call {{{1 +silent call s:InstallDocumentation(expand(':p'),"0.99") +"============================================================ +finish + +"Manual {{{1 +=== START_DOC +*VimExplorer* A powerful file manager #version# + + + VimExplorer Reference Manual + by Ming Bai (mbbill AT gmail.com) + + +============================================================================== +CONTENTS *VimExplorer-contents* + +1. Intro.......................................|VimExplorer-start| +2. Functionality...............................|VimExplorer-functionality| + 2.1 Tree Panel Hotkeys.....................|VimExplorer-treehotkey| + 2.2 File Panel Hotkeys.....................|VimExplorer-filehotkey| + 2.3 Commands...............................|VimExplorer-commands| +3. Directory Browsing..........................|VimExplorer-browse| + 3.1 Tree Browsing..........................|VimExplorer-treebrowse| + 3.2 File Browsing..........................|VimExplorer-filebrowse| + 3.3 Forward and Backward...................|VimExplorer-forbackward| + 3.4 Favorites..............................|VimExplorer-favorite| + 3.5 Temp Marks.............................|VimExplorer-tempmark| +4. Marks.......................................|VimExplorer-mark| + 4.1 Single File Marks......................|VimExplorer-marksingle| + 4.2 Visual Marks...........................|VimExplorer-markvisual| + 4.3 Regexp Marks...........................|VimExplorer-markregexp| +5. File operations.............................|VimExplorer-fileoperation| + 5.1 Create.................................|VimExplorer-new| + 5.2 Move...................................|VimExplorer-move| + 5.3 Delete.................................|VimExplorer-delete| + 5.4 Diff...................................|VimExplorer-diff| + 5.5 Search.................................|VimExplorer-search| + 5.6 Other Operations.......................|VimExplorer-otherfileopt| +6. Other Functionalities.......................|VimExplorer-otherfuncs| +7. Customization...............................|VimExplorer-customize| + 7.1 Normal Options.........................|VimExplorer-custnormal| + 7.2 Hotkey Customization...................|VimExplorer-custhotkey| + 7.3 Command Customization..................|VimExplorer-custcommand| +8. The Author..................................|VimExplorer-author| +9. Problems and Fixes..........................|VimExplorer-problems| +10. Changelog...................................|VimExplorer-changelog| +11. TODO........................................|VimExplorer-todo| + + +============================================================================== +1. Intro *VimExplorer-start* + +What is VimExplorer ? +VimExplorer is a file manager, it can do a lot of file operations such as +copy, delete, move, preview, search and so on. Also it has a variety of other +capacities and customization abilities. + +You can start VimExplorer by the following command: +> + :VE +< +Then it will ask you for the starting directory, default is the current path. +> + VimExplorer (directory): /home/username/ +< +You can change it to some other directories or just push "Enter" to start it. + +The second approach to start VimExplorer: +> + :VE [directory] +< +Example: +> + :VE /usr/src/ +< +Now, VimExplorer will start using the path '/usr/src/'. When you are typing +the path, and will help you to complete the path automatically. +After all of these operations, you can see a new tab which has two panels +within it, one is the "Tree Panel" and the other is "File Panel". From now you +will have a happy journey using the powerful file manager. + + +============================================================================== +2. Functionality *VimExplorer-functionality* + +2.1 Tree Panel Hotkeys *VimExplorer-treehotkey* + +Member of |VEConf_treeHotkey|, refer to section 7.2 . + +Mapping Key Description~ +help ? Help. +toggleNode Open/Close/Switch to current node. +toggleNodeMouse <2-LeftMouse> Open/Close/Switch to current node. +refresh r Refresh the tree panel. +favorite f View favorite folder list. +addToFavorite F Add the folder under cursor to + favorite list. If no path under + cursor, use current working path. +browseHistory b View browse history. +toggleFilePanel t Toggle the file panel. +toUpperDir Go to upper directory. +switchPanel Switch to File Panel. +gotoPath Change to another path. +quitVE Q Quit VimExplorer. + +2.2 File Panel Hotkeys *VimExplorer-filehotkey* + +Member of |VEConf_fileHotkey|, refer to section 7.2 . + +Mapping Default Description~ +help ? Help. +itemClicked Enter the directory or open the file + by default association. +itemClickMouse <2-LeftMouse> Enter the directory or open the file + by default association. +refresh r Refresh. +toggleTreePanel t Toggle the Tree Panel. +toggleModes i Toggle file sort mode (type/data/file + extension). +newFile +f Create a new file. +newDirectory +d Create a new directory. +switchPanel Switch to the Tree Panel. +quitVE Q Quit VimExplorer. +toggleHidden H Toggle show hidden files.(files start + with '.') +search g/ Search. +markPlace m{a-z} Put current path to register(a-z). +gotoPlace '{a-z} Jump to path in register(a-z). +viewMarks J View path in register. +contextMenuN File panel context menu in normal mode. +toUpperDir Go to upper directory. +gotoForward Forward. +gotoBackward Backward. +favorite f View favorite folder list. +addToFavorite F Add the folder under cursor to + favorite list. If no path under + cursor, use current working path. +browseHistory b View browse history. +gotoPath Change to another path. +rename R Rename the file under cursor. +yankSingle yy Copy file under cursor. +cutSingle xx Cut file under cursor. +showYankList yl Show clipboard. +deleteSingle dd Delete file under cursor to recycle bin. +deleteSingle DD Force delete file under cursor. +openPreview u Preview. +closePreview U Close the preview panel. +toggleSelectUp Move the cursor up and mark/unmark the + file under cursor. +toggleSelectDown Mark/unmark the file under cursor and + move the cursor down. +toggleSelMouse Mark/unmark the file under cursor. +markViaRegexp Mr Mark via regular expression. +markVimFiles Mv Mark all vim files. +markDirectory Md Mark all directories. +markExecutable Me Mark all executable files. +clearSelect Mc Clear all marks. +deleteSelected sd Delete marked files to recycle bin. +deleteSelected sD Force delete marked files. +yankSelected sy Copy marked files. +cutSelected sx Cut marked files. +tabViewMulti se Edit every marked file in separate + tabs. +paste p Paste. +diff2files = Diff two files. +tabView e Edit file in new tab. +openRenamer ;r Open Renamer (Note 1) +startShell ;c Start a shell from current path. +startExplorer ;e Start another file + manager(nautilus,konquer,explorer.exe). + +Visual Mode Hotkeys~ +visualSelect Mark files. +visualDelete d Delete files to recycle bin. +visualDelete D Force delete files. +visualYank y Copy files. +visualCut x Cut files. +tabView e View files in new tabs. + +2.3 Commands *VimExplorer-commands* +> + VE +< +Start VimExplorer. + +> + VEC +< +Close VimExplorer, Hotkey |Q| has the same ability. + +============================================================================== +3. Directory Browsing *VimExplorer-browse* + +3.1 Tree Browsing *VimExplorer-treebrowse* + +Press "Enter" on one tree node will change the path and add the new path to +browse history. By default, if a directory has it's own child directories, |+| +will be displayed before it's name, and It will cause a little performance +lost. If you don't need this feature ,set the following variable to zero can +disable it. +> + let VEConf_showFolderStatus = 0 +< +There are some differences between win32 and other platforms. In win32, there +are several root nodes (such as C:\,D:\), but one root node (/) in other +platforms. + +3.2 File Browsing *VimExplorer-filebrowse* + +The file panel consist of two parts: the path in the top and the following +file list. Every line of the file list consist from the following regions: + +[*] {file-name} [file-size] {permission} {modify-time} + +The file panel can sort by type, file name and date. Hotkey |i| is used to +cycle between these modes. Default sort mode controlled by following variable: +> + VEConf_filePanelSortType + +< +See Customization section for more details. + +3.3 Forward and Backward *VimExplorer-forbackward* + +When using "Enter" switch to an new folder, the path will be add to browse +history. Then you can use || and || to go backward and forward. +Hotkey |b| is used to list all browse history, select by number or mouse can +take you directory to that path. + +By default, the depth of browse history is 100. Controled by this variable: +> + VEConf_browseHistory +< +VimExplorer can remember the cursor position every time leaving a directory, +so it can restore the cursor when return to it. If a directory is newly +entered, the cursor will be put in the middle of the screen. + +3.4 Favorites *VimExplorer-favorite* + +The favorite folder list is saved to the file $HOME/.ve_favorite . It will be +updated when new folder is added to favorite by hotkey |F|. The format of +".ve_favorite" is very simple: every line is a path, so edit it is quite +easy. + +3.5 Temp Marks *VimExplorer-tempmark* + +Just like the favorites, |ma| put current path into register 'a', and |'a| can +jump to the path. |J| is used to list every non empty register. All paths in +register will disappear after VimExplorer exists. + +============================================================================== +4. Marks *VimExplorer-mark* + +The simplest way is to press upon a file. There will be a '*' before +marked files and also be displayed in a different color. +There are three way to mark files: + +4.1 Single File Marks *VimExplorer-marksingle* + + Invert selection, move the cursor down. + Move the cursor up, then invert selection. +Just like most of vim commands, 5 will mark 5 files start from current +cursor. + +4.2 Visual Marks *VimExplorer-markvisual* + + in visual mode will invert selected these files. + +4.3 Regexp Marks *VimExplorer-markregexp* + +Hotkey: |Mr| +Only the file name is the target of regexp match. Example: +> + Mark file (regexp): ^abc.*\.vim$ +< +It will mark all vim scripts start with abc. The following functionalities is +derived from this feature: +|Mv| mark all vim scripts. +|Me| mark all executable files. +|Md| mark all directories. +and |Mc| to clear all marks. + +============================================================================== +5. File Operations *VimExplorer-fileoperation* + +5.1 Create *VimExplorer-new* + +|+f| and |+d| is used to create new files and directories. + +5.2 Move *VimExplorer-move* + +There are several hotkey used to copy/cut files: +|yy| and |sy| in normal mode ,|y| in visual mode is to copy file. +|xx| and |sx| in normal mode ,|x| in visual mode is to cut file. +|p| paste file. +Note that the clipboard is shared between all VimExplorers ,you can cut in one +VE tab and paste in another. +If you want to view the clipboard, |yl| can be help. + +5.3 Delete *VimExplorer-delete* + +|dd|,|sd| in normal mode and |d| in visual mode can delete file(s) to recycle bin. +Corresponding |DD|,|sD| and |D| are used to force delete file(s). + +5.4 Diff *VimExplorer-diff* + +|=| is used to diff 2 files, so make sure you have selected 2 files before +using this command. + +5.5 Search *VimExplorer-search* + +Just like / ,but the pattern here is not the regexp in vim, it will be +expended by shell. + +5.6 Other Operations *VimExplorer-otherfileopt* + +|e| |R| |u| and so on ... Refer to section 2.2 + +============================================================================== +6. Other Functionalities *VimExplorer-otherfuncs* + +|;r| |;c| |;e| and so on ...Rever to section 2.2 + +============================================================================== +7. Customization *VimExplorer-customize* + +7.1 Normal Options *VimExplorer-custnormal* + +Common Options~ + +|g:VEConf_systemEncoding| It controls the encoding of vim calling + function system(). If your system encoding + is different from '&encoding', set this + value to system encoding. Example: let + g:VEConf_systemEncoding = 'utf-8' + ,Default: '' (empty) + +|g:VEConf_win32Disks| The default value is all 26 volumes. Set this + value to fit your system can increase the + startup speed. If you are not using + Microsoft Windows, ignore it. Example: + let VEConf_win32Disks = + ["A:","B:","C:","D:"] + +|g:VEConf_browseHistory| Depth of browse history. Default: 100 + +|g:VEConf_previewSplitLocation| Split location of preview panel. Optional + parameters are: + "belowright","topleft","leftabove","botright". + Default: "belowright" + +|g:VEConf_showHiddenFiles| Show hidden files, 1: show,0: hide. Default: 1 + +|g:VEConf_externalExplorer| Name of the external file explorer. You can + set this value according to you system. + Default: "explorer.exe"(win32) "nautilus" + (gnome) + +|g:VEConf_sortCaseSensitive| 0: not case sensitive 1: case sensitive + Default: 1 + +|g:VEConf_favorite| Favorite folder file name. Always stored in + $HOME. Default: ".ve_favorite" + +|g:VEConf_overWriteExisting| Ask when over write existing files. + 0: ask 1: always over write 2: always + not over write Default: 0 + +|g:VEConf_usingKDE| If set to 1, use "kfmclient" +|g:VEConf_usingGnome| If set to 1, use "gnome-open" + +|g:VEConf_recyclePath| Recycle path. Example: + let g:VEConf_recyclePath = 'C:\VErecycle\' + +Tree Panel Options~ + +|g:VEConf_showFolderStatus| It controls whether show '+' before the + folders which have their own child + folders. If it is set to 1, every folder + will have a '+'. Default: 1 + +|g:VEConf_treePanelWidth| Width of tree panel. Default: 30 + +|g:VEConf_treePanelSplitMode| Split mode of tree panel. Default: "vertical" + +|g:VEConf_treePanelSplitLocation| Split location of tree panel, Optional + parameters: "belowright" , "topleft" , + "leftabove" , "botright", Default: + "leftabove" + +|g:VEConf_treeSortDirection| Sort direction. 1: A-Z 0: Z-A. Default: 1 + +File Panel Options~ + +|g:VEConf_fileGroupSortDirection| Sort direction. 1: A-Z 0: Z-A, Default: 1 + +|g:VEConf_fileDeleteConfirm| Confirm when deleting a file. 1: confirm 2: + no confirm. Default: 1 + +|g:VEConf_filePanelWidth| Width of file panel. Default: 40 + +|g:VEConf_filePanelSplitMode| Split mode of file panel. Default: "vertical" + +|g:VEConf_filePanelSplitLocation| Split location of file panel, Optional + parameters: "belowright" , "topleft" , + "leftabove" , "botright" ,Default: + "leftabove" + +|g:VEConf_filePanelSortType| File sort type. 1: sort by name 2: sort by + time 3: sort by type, Default: 3 + +|g:VEConf_showFileSizeInMKB| 1: Show file size in MKB format. 0: always + show file size in byte. + +|g:VEConf_filePanelFilter| Filter of the file panel, which will be + passed to glob() function. Example: + let g:VEConf_filePanelFilter = '*.txt' + +7.2 Hotkey Customization *VimExplorer-custhotkey* + +All user defined hotkeys are controlled by the two dicts: +|g:VEConf_treeHotkey| and |g:VEConf_fileHotkey| +Example: +> + let g:VEConf_treeHotkey = {} + let g:VEConf_treeHotkey.help = '??' + let g:VEConf_treeHotkey.quitVE = 'qq' + let g:VEConf_treeHotkey.switchPanel = '' +< +All definable hotkeys and their default bindings refer to section 2 . + +7.3. Command Customization *VimExplorer-custcommand* + +VimExplorer supports three types of command interface: +single file hotkeys and actions, multi file hotkeys and actions and normal +hotkeys and actions. +They are controlled by these variables: + + |g:VEConf_singleFileActions| |g:VEConf_singleFileHotKeys| + + |g:VEConf_multiFileActions| |g:VEConf_multiFileHotKeys| + + |g:VEConf_normalActions| |g:VEConf_normalHotKeys| + +All of them are dicts. Example: +> + let g:VEConf_normalActions = {} + let g:VEConf_normalHotKeys = {} + let g:VEConf_normalHotKeys['test1'] = 'T1' + function! VEConf_normalActions['test1']() + Renamer + endfunction +< +"test1" is the key. VimExplorer will bind the hotkey and corresponding actions +automatically. +> + let g:VEConf_singleFileActions = {} + let g:VEConf_singleFileHotKeys = {} + let g:VEConf_singleFileHotKeys['test2'] = 'T2' + function! VEConf_singleFileActions['test2'](path) + call g:VEPlatform.system("notepad.exe " . g:VEPlatform.escape(a:path)) + endfunction +< +Here, parameter "path" is the path of file under cursor. +> + let g:VEConf_multiFileActions = {} + let g:VEConf_multiFileHotKeys = {} + let g:VEConf_multiFileHotKeys['test3'] = 'T3' + function! VEConf_multiFileActions['test3'](fileList) + for i in a:fileList + call g:VEPlatform.start("nautilus " . i) + endfor + endfunction +< +Parameter "fileList" consists of all paths of marked files. +In addition, VimExplorer provides some platform independent functions: +> + g:VEPlatform.start(path) + g:VEPlatform.system(cmd) + g:VEPlatform.copyfile(filename,topath) + g:VEPlatform.search(filename,path) + g:VEPlatform.deleteSingle(path) +< +These functions can be used in user defined actions. + + + + +============================================================================== +8. The Author *VimExplorer-author* + +If you have find a bug, or have some suggestions , mail me. + +mail: mbbillgmailcom + +============================================================================== +9. Problems and Fixes *VimExplorer-problems* + + *VimExplorer-p1* +P1. Case sensitive in Win32. + At present, the path in win32 is case sensitive. Pay attention to this + when starting VE, editing the favorite list or using to change + path. A good suggestion is using or to complete path + automatically. + + *VimExplorer-p2* +P2. 'wildignre' option cause some files disappeared. + If 'wildignore' is not empty, glob() function will not return files + matching the file pattern listed in it, then you may find some files + disappeared in the file panel. + + + +============================================================================== +10. Changelog *VimExplorer-changelog* + +0.95 + - Initial release. + +0.96 + - BUG: VE_normalAction not found. + +0.97 + - NEW: Add options |g:VEConf_usingKDE| and |g:VEConf_usingGnome| for + starting program in *nix environment. + - NEW: Check if the script is already loaded, thanks to Dennis Hostetler. + - BUG: Escape ' %#' for path. + - BUG: Favorite selection out of range. + - CHG: Change the behaviour of hotkey 'F', now it adds the path under + cursor to favorite list. If no path under cursor, use current + working path instead.(Thanks to Vincent Wang) + - CHG: Change default g:VEConf_systemEncoding to '' (empty). +0.98 + - NEW: Add option VEConf_filePanelFilter. + - BUG: Escape in command 'e' 'se' 'u' and '='. + - BUG: 'Cut' and 'Paste' command causes file lost. + - CHG: Change the default hotkey 'M' and 'B' to 'm','J'. + - CHG: Change forward and backward hotkey to || and ||(). + - CHG: Change hotkey || to ||. + - CHG: Change hotkey |mr| |mv| |md| |me| |mc| to |Mr| |Mv| |Md| |Me| |Mc|. + - CHG: When GUI is running, use confirm() to pop a dialog instead of input(). +0.99 + - NEW: Add toggle selection hotkey . + - NEW: Add a context menu in file panel, right click on a file to popup it. + - NEW: Add "delete to recycle",hotkey |dd|,|sd| and |d| in visual mode + are used to delete file(s) to recycle bin.The curresponding + |DD|,|sD|,|D| hotkey are used to force delete files. + - NEW: Now VE can remember the cursor position when reenter a directory. + - BUG: All files are put to "Hidden Files" group in a hidden directory. + - BUG: 'sd' twice after selection will cause an error. + +============================================================================== +11. TODO *VimExplorer-todo* + - More clipboard. + - Diff files in different directories. + - Two panel mode, just like TotalCommand. + - Diff directories. + - Browse via e.g. FTP, SCP ... directorys on a server. + - Rename file when file exsits in copy operation. + - Compress file. + - Send to. + + +============================================================================== +Note 1: +Renamer is a good plugin, which is used to rename group of files. The author +is John Orr. It can be found here: +http://www.vim.org/scripts/script.php?script_id=1721 + + +=== END_DOC +" vim: set et fdm=marker sts=4 sw=4 tw=78: diff --git a/.vim/plugin/cscope_maps.vim b/.vim/plugin/cscope_maps.vim new file mode 100644 index 0000000..c577b45 --- /dev/null +++ b/.vim/plugin/cscope_maps.vim @@ -0,0 +1,165 @@ +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" CSCOPE settings for vim +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" +" This file contains some boilerplate settings for vim's cscope interface, +" plus some keyboard mappings that I've found useful. +" +" USAGE: +" -- vim 6: Stick this file in your ~/.vim/plugin directory (or in a +" 'plugin' directory in some other directory that is in your +" 'runtimepath'. +" +" -- vim 5: Stick this file somewhere and 'source cscope.vim' it from +" your ~/.vimrc file (or cut and paste it into your .vimrc). +" +" NOTE: +" These key maps use multiple keystrokes (2 or 3 keys). If you find that vim +" keeps timing you out before you can complete them, try changing your timeout +" settings, as explained below. +" +" Happy cscoping, +" +" Jason Duell jduell@alumni.princeton.edu 2002/3/7 +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + +" This tests to see if vim was configured with the '--enable-cscope' option +" when it was compiled. If it wasn't, time to recompile vim... +if has("cscope") + + """"""""""""" Standard cscope/vim boilerplate + + " use both cscope and ctag for 'ctrl-]', ':ta', and 'vim -t' + set cscopetag + + " check cscope for definition of a symbol before checking ctags: set to 1 + " if you want the reverse search order. + set csto=0 + + " add any cscope database in current directory + if filereadable("cscope.out") + cs add cscope.out + " else add the database pointed to by environment variable + elseif $CSCOPE_DB != "" + cs add $CSCOPE_DB + endif + + " show msg when any other cscope db added + set cscopeverbose + + + """"""""""""" My cscope/vim key mappings + " + " The following maps all invoke one of the following cscope search types: + " + " 's' symbol: find all references to the token under cursor + " 'g' global: find global definition(s) of the token under cursor + " 'c' calls: find all calls to the function name under cursor + " 't' text: find all instances of the text under cursor + " 'e' egrep: egrep search for the word under cursor + " 'f' file: open the filename under cursor + " 'i' includes: find files that include the filename under cursor + " 'd' called: find functions that function under cursor calls + " + " Below are three sets of the maps: one set that just jumps to your + " search result, one that splits the existing vim window horizontally and + " diplays your search result in the new window, and one that does the same + " thing, but does a vertical split instead (vim 6 only). + " + " I've used CTRL-\ and CTRL-@ as the starting keys for these maps, as it's + " unlikely that you need their default mappings (CTRL-\'s default use is + " as part of CTRL-\ CTRL-N typemap, which basically just does the same + " thing as hitting 'escape': CTRL-@ doesn't seem to have any default use). + " If you don't like using 'CTRL-@' or CTRL-\, , you can change some or all + " of these maps to use other keys. One likely candidate is 'CTRL-_' + " (which also maps to CTRL-/, which is easier to type). By default it is + " used to switch between Hebrew and English keyboard mode. + " + " All of the maps involving the macro use '^$': this is so + " that searches over '#include " return only references to + " 'time.h', and not 'sys/time.h', etc. (by default cscope will return all + " files that contain 'time.h' as part of their name). + + + " To do the first type of search, hit 'CTRL-\', followed by one of the + " cscope search types above (s,g,c,t,e,f,i,d). The result of your cscope + " search will be displayed in the current window. You can use CTRL-T to + " go back to where you were before the search. + " + + nmap s :cs find s =expand("") + nmap g :cs find g =expand("") + nmap c :cs find c =expand("") + nmap t :cs find t =expand("") + nmap e :cs find e =expand("") + nmap f :cs find f =expand("") + nmap i :cs find i ^=expand("")$ + nmap d :cs find d =expand("") + + + " Using 'CTRL-spacebar' (intepreted as CTRL-@ by vim) then a search type + " makes the vim window split horizontally, with search result displayed in + " the new window. + " + " (Note: earlier versions of vim may not have the :scs command, but it + " can be simulated roughly via: + " nmap s :cs find s =expand("") + + nmap s :scs find s =expand("") + nmap g :scs find g =expand("") + nmap c :scs find c =expand("") + nmap t :scs find t =expand("") + nmap e :scs find e =expand("") + nmap f :scs find f =expand("") + nmap i :scs find i ^=expand("")$ + nmap d :scs find d =expand("") + + + " Hitting CTRL-space *twice* before the search type does a vertical + " split instead of a horizontal one (vim 6 and up only) + " + " (Note: you may wish to put a 'set splitright' in your .vimrc + " if you prefer the new window on the right instead of the left + + nmap s :vert scs find s =expand("") + nmap g :vert scs find g =expand("") + nmap c :vert scs find c =expand("") + nmap t :vert scs find t =expand("") + nmap e :vert scs find e =expand("") + nmap f :vert scs find f =expand("") + nmap i :vert scs find i ^=expand("")$ + nmap d :vert scs find d =expand("") + + + """"""""""""" key map timeouts + " + " By default Vim will only wait 1 second for each keystroke in a mapping. + " You may find that too short with the above typemaps. If so, you should + " either turn off mapping timeouts via 'notimeout'. + " + "set notimeout + " + " Or, you can keep timeouts, by uncommenting the timeoutlen line below, + " with your own personal favorite value (in milliseconds): + " + "set timeoutlen=4000 + " + " Either way, since mapping timeout settings by default also set the + " timeouts for multicharacter 'keys codes' (like ), you should also + " set ttimeout and ttimeoutlen: otherwise, you will experience strange + " delays as vim waits for a keystroke after you hit ESC (it will be + " waiting to see if the ESC is actually part of a key code like ). + " + "set ttimeout + " + " personally, I find a tenth of a second to work well for key code + " timeouts. If you experience problems and have a slow terminal or network + " connection, set it higher. If you don't set ttimeoutlen, the value for + " timeoutlent (default: 1000 = 1 second, which is sluggish) is used. + " + "set ttimeoutlen=100 + +endif + + diff --git a/.xinitrc b/.xinitrc new file mode 100644 index 0000000..1baa27a --- /dev/null +++ b/.xinitrc @@ -0,0 +1,21 @@ +DEFAULT_SESSION=urxvt + +case $1 in +fvwm-crystal) + exec fvwm-crystal + ;; +fvwm) exec fvwm + ;; +kde) + exec startkde + ;; +xfce4) + exec startxfce4 + ;; +fluxbox) + exec startfluxbox + ;; +*) + exec $DEFAULT_SESSION + ;; +esac diff --git a/.xprofile b/.xprofile new file mode 100644 index 0000000..796b05a --- /dev/null +++ b/.xprofile @@ -0,0 +1 @@ +[[ -f ~/.bashrc ]] && . ~/.bashrc \ No newline at end of file diff --git a/.xscreensaver b/.xscreensaver new file mode 100644 index 0000000..1aaa1a6 --- /dev/null +++ b/.xscreensaver @@ -0,0 +1,257 @@ +# XScreenSaver Preferences File +# Written by xscreensaver-demo 5.15 for kolan on Mon Feb 6 13:30:55 2012. +# http://www.jwz.org/xscreensaver/ + +timeout: 0:05:00 +cycle: 0:01:00 +lock: True +lockTimeout: 0:16:00 +passwdTimeout: 0:00:30 +visualID: default +installColormap: True +verbose: False +timestamp: True +splash: False +splashDuration: 0:00:05 +demoCommand: xscreensaver-demo +prefsCommand: xscreensaver-demo -prefs +nice: 10 +memoryLimit: 0 +fade: True +unfade: False +fadeSeconds: 0:00:03 +fadeTicks: 20 +captureStderr: True +ignoreUninstalledPrograms:False +font: *-medium-r-*-140-*-m-* +dpmsEnabled: True +dpmsQuickOff: True +dpmsStandby: 0:08:00 +dpmsSuspend: 0:08:00 +dpmsOff: 0:08:00 +grabDesktopImages: True +grabVideoFrames: False +chooseRandomImages: True +imageDirectory: /home/kolan/wallpapers + +mode: random +selected: 109 + +textMode: date +textLiteral: XScreenSaver +textFile: /etc/gentoo-release +textProgram: fortune +textURL: http://planet.gentoo.org/rss20.xml + +programs: \ + maze -root \n\ +- GL: superquadrics -root \n\ + attraction -root \n\ +- blitspin -root \n\ + greynetic -root \n\ + helix -root \n\ + hopalong -root \n\ +- imsmap -root \n\ +- noseguy -root \n\ + pyro -root \n\ + qix -root \n\ + rocks -root \n\ + rorschach -root \n\ + decayscreen -root \n\ + flame -root \n\ + halo -root \n\ +- slidescreen -root \n\ + pedal -root \n\ + bouboule -root \n\ +- braid -root \n\ + coral -root \n\ + deco -root \n\ +- drift -root \n\ + fadeplot -root \n\ + galaxy -root \n\ +- goop -root \n\ + grav -root \n\ + ifs -root \n\ +- GL: jigsaw -root \n\ + julia -root \n\ + kaleidescope -root \n\ +- GL: moebius -root \n\ + moire -root \n\ +- GL: morph3d -root \n\ + mountain -root \n\ + munch -root \n\ + penrose -root \n\ + GL: pipes -root \n\ + rd-bomb -root \n\ +- GL: rubik -root \n\ + sierpinski -root \n\ +- slip -root \n\ +- GL: sproingies -root \n\ + starfish -root \n\ + strange -root \n\ + swirl -root \n\ + triangle -root \n\ +- xjack -root \n\ +- xlyap -root \n\ +- GL: atlantis -root \n\ + bsod -root \n\ +- GL: bubble3d -root \n\ +- GL: cage -root \n\ + crystal -root \n\ + cynosure -root \n\ +- discrete -root \n\ +- distort -root \n\ + epicycle -root \n\ +- flow -root \n\ +- GL: glplanet -root \n\ +- interference -root \n\ +- kumppa -root \n\ +- GL: lament -root \n\ + moire2 -root \n\ + GL: sonar -root \n\ +- GL: stairs -root \n\ + truchet -root \n\ +- vidwhacker -root \n\ + blaster -root \n\ +- bumps -root \n\ + ccurve -root \n\ + compass -root \n\ +- deluxe -root \n\ + demon -root \n\ +- GL: extrusion -root \n\ + loop -root \n\ +- penetrate -root \n\ + petri -root \n\ +- phosphor -root \n\ + GL: pulsar -root \n\ +- ripples -root \n\ + shadebobs -root \n\ + GL: sierpinski3d -root \n\ +- spotlight -root \n\ + squiral -root \n\ + wander -root \n\ +- webcollage -root \n\ +- xflame -root \n\ + xmatrix -root \n\ +- GL: gflux -root \n\ + nerverot -root \n\ + xrayswarm -root \n\ + xspirograph -root \n\ +- GL: circuit -root \n\ + GL: dangerball -root \n\ +- GL: dnalogo -root \n\ +- GL: engine -root \n\ +- GL: flipscreen3d -root \n\ +- GL: gltext -root \n\ + GL: menger -root \n\ +- GL: molecule -root \n\ +- rotzoomer -root \n\ +- speedmine -root \n\ + GL: starwars -root \n\ + GL: stonerview -root \n\ + vermiculate -root \n\ +- whirlwindwarp -root \n\ +- zoom -root \n\ + anemone -root \n\ + apollonian -root \n\ +- GL: boxed -root \n\ +- GL: cubenetic -root \n\ +- GL: endgame -root \n\ +- euler2d -root \n\ +- fluidballs -root \n\ +- GL: flurry -root \n\ +- GL: glblur -root \n\ + GL: glsnake -root \n\ +- halftone -root \n\ +- GL: juggler3d -root \n\ +- GL: lavalite -root \n\ + polyominoes -root \n\ +- GL: queens -root \n\ +- GL: sballs -root \n\ +- GL: spheremonics -root \n\ + thornbird -root \n\ +- twang -root \n\ +- GL: antspotlight -root \n\ +- apple2 -root \n\ +- GL: atunnel -root \n\ + barcode -root \n\ +- GL: blinkbox -root \n\ +- GL: blocktube -root \n\ +- GL: bouncingcow -root \n\ + cloudlife -root \n\ + GL: cubestorm -root \n\ +- eruption -root \n\ +- GL: flipflop -root \n\ +- GL: flyingtoasters -root \n\ +- fontglide -root \n\ + GL: gleidescope -root \n\ +- GL: glknots -root \n\ + GL: glmatrix -root \n\ +- GL: glslideshow -root \n\ +- GL: hypertorus -root \n\ +- GL: jigglypuff -root \n\ +- metaballs -root \n\ +- GL: mirrorblob -root \n\ +- piecewise -root \n\ + GL: polytopes -root \n\ +- pong -root \n\ + popsquares -root \n\ + GL: surfaces -root \n\ +- xanalogtv -root \n\ + abstractile -root \n\ + anemotaxis -root \n\ +- GL: antinspect -root \n\ +- fireworkx -root \n\ +- fuzzyflakes -root \n\ +- interaggregate -root \n\ + intermomentary -root \n\ + memscroller -root \n\ +- GL: noof -root \n\ + pacman -root \n\ +- GL: pinion -root \n\ +- GL: polyhedra -root \n\ +- GL: providence -root \n\ + substrate -root \n\ +- wormhole -root \n\ +- GL: antmaze -root \n\ +- GL: boing -root \n\ + boxfit -root \n\ +- GL: carousel -root \n\ + celtic -root \n\ +- GL: crackberg -root \n\ + GL: cube21 -root \n\ +- fiberlamp -root \n\ +- GL: fliptext -root \n\ +- GL: glhanoi -root \n\ + GL: tangram -root \n\ +- GL: timetunnel -root \n\ +- GL: glschool -root \n\ +- GL: topblock -root \n\ + GL: cubicgrid -root \n\ + cwaves -root \n\ +- GL: gears -root \n\ + GL: glcells -root \n\ + GL: lockward -root \n\ +- m6502 -root \n\ +- GL: moebiusgears -root \n\ + GL: voronoi -root \n\ +- GL: hypnowheel -root \n\ +- GL: klein -root \n\ + lcdscrub -root \n\ +- GL: photopile -root \n\ +- GL: skytentacles -root \n\ +- GL: rubikblocks -root \n\ +- GL: companioncube -root \n\ +- GL: hilbert -root \n\ + GL: tronbit -root \n\ + + +pointerPollTime: 0:00:05 +pointerHysteresis: 10 +windowCreationTimeout:0:00:30 +initialDelay: 0:00:00 +GetViewPortIsFullOfLies:False +procInterrupts: True +xinputExtensionDev: False +overlayStderr: True +