diff --git a/.netrwhist b/.netrwhist deleted file mode 100644 index 19edcd6..0000000 --- a/.netrwhist +++ /dev/null @@ -1,4 +0,0 @@ -let g:netrw_dirhistmax =10 -let g:netrw_dirhist_cnt =2 -let g:netrw_dirhist_1='/boot/grub' -let g:netrw_dirhist_2='/home/ffourc/.vim/autoload' diff --git a/bundle/dokuvimki b/bundle/dokuvimki new file mode 160000 index 0000000..529d876 --- /dev/null +++ b/bundle/dokuvimki @@ -0,0 +1 @@ +Subproject commit 529d8765d17c82ee6b4ba119000f69cbb760d1f6 diff --git a/bundle/dokuvimki/COPYING b/bundle/dokuvimki/COPYING deleted file mode 100644 index d60c31a..0000000 --- a/bundle/dokuvimki/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/bundle/dokuvimki/doc/dokuvimki.txt b/bundle/dokuvimki/doc/dokuvimki.txt deleted file mode 100644 index 8c22371..0000000 --- a/bundle/dokuvimki/doc/dokuvimki.txt +++ /dev/null @@ -1,197 +0,0 @@ -*dokuvimki* Plugin for editing DokuWiki pages via XML-RPC for Vim > 6.0 - For Vim > 7.0 - - By Michael Klier - - *dokuvimki-plugin* - ------------------------------------------------------------------------------- -OVERVIEW *dokuvimki-overview* - -|dokuvimki-installation| Installation instructions - -|dokuvimki-configuration| How to configure dokuvimki - -|dokuvimki-commands| Brief description of the available commands - -|dokuvimki-buffer-mappings| Description of the mappings available in the - special buffers - -|dokuvimki-bugs| Bug reports are always welcome ;-) - ------------------------------------------------------------------------------- -UPDATES *dokuvimki-updates* - -The official releases can be found at: - - git: http://github.com/chimeric/dokuvimki - ------------------------------------------------------------------------------- -INSTALLATION *dokuvimki-installation* - -Just unpack the tarball in your ~/.vim/ directory. Then edit your .vimrc and -add your settings (see CONFIGURATION). You'll also need to install the python -xmlrpclib module and the dokuwikixmlrpc module in order to use this plugin! -For details about installing those please refer to the documentation specific -for your OS. - ------------------------------------------------------------------------------- -CONFIGURATION *dokuvimki-configuration* - -The following variables have to be present in your ~/.vimrc in order to get -DokuVimKi working. - -g:DokuVimKi_USER The username used to login into the remote wiki. - -g:DokuVimKi_PASS The password used to login into the remote wiki. - -g:DokuVimKi_URL The URL of the remote wiki (no trailing slash!). - -g:DokuVimKi_INDEX_WINWIDTH The width of the index window (default 30). - -g:DokuVimKi_DEFAULT_SUM Default summary used if no summary is given on - save. Defaults to [xmlrpc dokuvimki edit]. - If you save pages using :w this is used as well - and will result in a minor edit. - ------------------------------------------------------------------------------- -COMMANDS *dokuvimki-commands* - -:DWedit Opens the given wiki page in the edit buffer. If - the page does not exist on the remote wiki it will - be created once you issue :DWSave. You can use - to autocomplete pages. If the page doesn't - contain any ':' the page will be created in the - current namespace the index is showing. - -:DWcd Change into a given namespace. - -:DWsave Save the wiki page in the edit buffer to the - remote wiki. If no edit summary is given it - will be saved as minor edit. You can also use :w - but it will not allow to specify a edit summary. - -:DWbackLinks Loads a list of pages which link back to the given - wiki page into the edit buffer. If you are already - editing a page you can use the command without - supplying a wiki page and it will load a list of - backlinks to the page loaded in the edit buffer. - You can use to autocomplete pages. - -:DWrevisions N Lists the available revisions of a wiki page. You - can use an offset (integer) to view earlier - revisions. The number of shown revisions depends - on the $conf['recent'] setting of the remote wiki. - You can use to autocomplete pages. - -:DWsearch Searches for matching pages. You can use regular - expressions! - -:DWmediasearch Searches for matching media files. You can use - regular expressions. - -:DWchanges Lists the recent changes of the remote wiki. - You can specify a timeframe: - - Nd show changes of the last N days - Nw show changes of the last N weeks - -:DWclose Closes the current edit buffer (removing edit -:DWclose! locks on the remote wiki etc.) - if the buffer - contains changes which haven't been synced back - to the remote wiki this command will issue a - warning. You can also use :close which is setup - as abbreviation. - -:DWdiffclose Closes diff mode - -:DWupload Allows to upload a file in the current namespace. -:DWupload! - -:DWquit Quits the current session and quits vim. This will -:DWquit! fail if there are unsaved changes. - -:DWhelp Displays the DokuVimKi help. - ------------------------------------------------------------------------------- -EDIT-MAPPINGS *dokuvimki-edit-mappings* - -DokuVimKi mimics the functionality of DokuWikis edit toolbar to make it easier -to insert/edit wiki syntax. Unless otherwise noted all those mappings work -only in insert mode. - - inserts bold syntax - - inserts italic syntax - - inserts underline syntax - - inserts link syntax - - inserts media syntax - - inserts code block syntax - - inserts file block syntax - - inserts a headline - - increases the current headline level by one - - decreases the current headline level by one - - e opens a link under the current cursor position for editing - (this mappings only works in normal mode) - ------------------------------------------------------------------------------- -BUFFER-MAPPINGS *dokuvimki-buffer-mappings* - -DokuVimKi comes with some specials mappings you can use in the special buffers -like the index or the recent changes view. - - -INDEX - - Opens the page for editing, or lists the contents of the - namespace under the cursor. - - b Shows a list of the page linking back to the page under the - cursor. - - r Shows the revisions of page under the cursor. - - -REVISIONS - - Opens the page revision for editing. - - d Opens the diff view for the page and the revision under the - cursor. - - -CHANGES - - Opens the page revision under the cursor for editing. - - -SEARCH - - Opens the page under the cursor for editing. - - -BACKLINKS - - Opens the page under the cursor for editing. - ------------------------------------------------------------------------------- -BUGS *dokuvimki-bugs* - -Please use the official bug tracker for feature requests of bug reports: -> - http://github.com/chimeric/dokuvimki/issus - - -If the bug is reproducible, then it will be of great help if a short -description of the events leading to the bug are also given ;-). - -vim:tw=78:et:ts=4:ft=help:norl: diff --git a/bundle/dokuvimki/doc/tags b/bundle/dokuvimki/doc/tags deleted file mode 100644 index 56834f9..0000000 --- a/bundle/dokuvimki/doc/tags +++ /dev/null @@ -1,10 +0,0 @@ -dokuvimki dokuvimki.txt /*dokuvimki* -dokuvimki-buffer-mappings dokuvimki.txt /*dokuvimki-buffer-mappings* -dokuvimki-bugs dokuvimki.txt /*dokuvimki-bugs* -dokuvimki-commands dokuvimki.txt /*dokuvimki-commands* -dokuvimki-configuration dokuvimki.txt /*dokuvimki-configuration* -dokuvimki-edit-mappings dokuvimki.txt /*dokuvimki-edit-mappings* -dokuvimki-installation dokuvimki.txt /*dokuvimki-installation* -dokuvimki-overview dokuvimki.txt /*dokuvimki-overview* -dokuvimki-plugin dokuvimki.txt /*dokuvimki-plugin* -dokuvimki-updates dokuvimki.txt /*dokuvimki-updates* diff --git a/bundle/dokuvimki/plugin/dokuvimki.vim b/bundle/dokuvimki/plugin/dokuvimki.vim deleted file mode 100644 index c6a0aad..0000000 --- a/bundle/dokuvimki/plugin/dokuvimki.vim +++ /dev/null @@ -1,1088 +0,0 @@ -"----------------------------------------------------------------------------- -" Copyright (C) 2010 Michael Klier -" -" This program is free software; you can redistribute it and/or modify -" it under the terms of the GNU General Public License as published by -" the Free Software Foundation; either version 2, or (at your option) -" any later version. -" -" This program is distributed in the hope that it will be useful, -" but WITHOUT ANY WARRANTY; without even the implied warranty of -" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -" GNU General Public License for more details. -" -" You should have received a copy of the GNU General Public License -" along with this program; if not, write to the Free Software Foundation, -" Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -" -" Maintainer: Michael Klier -" URL: http://www.chimeric.de/projects/dokuwiki/dokuvimki -"----------------------------------------------------------------------------- - -if has('python') && version > 700 - command! -nargs=0 DokuVimKi exec('py dokuvimki()') - - if !exists('g:DokuVimKi_INDEX_WINWIDTH') - let g:DokuVimKi_INDEX_WINWIDTH=30 - endif - - if !exists('g:DokuVimKi_DEFAULT_SUM') - let g:DokuVimKi_DEFAULT_SUM = '[xmlrpc dokuvimki edit]' - endif - - " Custom autocompletion function for wiki pages and media files - " the global g:pages g:media variables are set/refreshed - " when the index is loaded - fun! InsertModeComplete(findstart, base) - if a:findstart - " locate the start of the page/media link - let line = getline('.') - let start = col('.') - 1 - while start > 0 && line[start - 1] !~ '\([\|{\)' - let start -= 1 - endwhile - if line[start - 1] =~ "[" - let g:comp = "pages" - elseif line[start - 1] =~ "{" - let g:comp = "media" - endif - return start - else - " find matching pages/media - let res = [] - if g:comp =~ "pages" - for m in split(g:pages) - if m =~ '^' . a:base - call add(res, m) - endif - endfor - elseif g:comp =~ "media" - for m in split(g:media) - if m =~ '^' . a:base - call add(res, m) - endif - endfor - endif - return res - endif - endfun - set completefunc=InsertModeComplete - set omnifunc=InsertModeComplete - - " Custom autocompletion function for namespaces and pages in - " normal mode. Used with DWedit - fun! CmdModeComplete(ArgLead, CmdLine, CursorPos) - let res = [] - for m in split(g:pages) - if m =~ '^' . a:ArgLead - call add(res, m) - endif - endfor - return res - endfun - - " Inserts a headline - let g:headlines = ["====== ======", "===== =====", "==== ====", "=== ===", "== =="] - fun! Headline() - return g:headlines[g:lvl] - endfun - - " Sets indentation/headline level - let g:lvl = 0 - fun! SetLvl(lvl) - let nlvl = g:lvl + a:lvl - if nlvl >= 1 && nlvl <= 4 - let g:lvl = nlvl - endif - return '' - endfun - -python <>sys.stderr, 'DokuVimKi Error: The dokuwikixmlrpc python module is missing!' - has_dokuwikixmlrpc = False - - - -class DokuVimKi: - """ - Provides all necessary functionality to interface between the DokuWiki - XMLRPC API and vim. - """ - - - def __init__(self): - """ - Instantiates special buffers, setup the xmlrpc connection and loads the - page index and displays the recent changes of the last 7 days. - """ - - if sys.version_info < (2,4): - print >>sys.stderr, "DokuVimKi requires at least python Version 2.4 or greater!" - return - - if not has_dokuwikixmlrpc: - print >>sys.stderr, "dokuwikixmlrpc python module missing!" - return - - if self.xmlrpc_init(): - - vim.command("command! -complete=customlist,CmdModeComplete -nargs=1 DWedit exec('py dokuvimki.edit()')") - vim.command("command! -complete=customlist,CmdModeComplete -nargs=* DWcd exec('py dokuvimki.cd()')") - vim.command("command! -nargs=? DWsave exec('py dokuvimki.save()')") - vim.command("command! -nargs=? DWsearch exec('py dokuvimki.search(\"page\", )')") - vim.command("command! -nargs=? DWmediasearch exec('py dokuvimki.search(\"media\", )')") - vim.command("command! -complete=customlist,CmdModeComplete -nargs=* DWrevisions exec('py dokuvimki.revisions()')") - vim.command("command! -complete=customlist,CmdModeComplete -nargs=? DWbacklinks exec('py dokuvimki.backlinks()')") - vim.command("command! -nargs=? DWchanges exec('py dokuvimki.changes()')") - vim.command("command! -nargs=0 -bang DWclose exec('py dokuvimki.close(\"\")')") - vim.command("command! -nargs=0 DWdiffclose exec('py dokuvimki.diff_close()')") - vim.command("command! -complete=file -bang -nargs=1 DWupload exec('py dokuvimki.upload(,\"\")')") - vim.command("command! -nargs=0 DWhelp exec('py dokuvimki.help()')") - vim.command("command! -nargs=0 -bang DWquit exec('py dokuvimki.quit(\"\")')") - - self.buffers = {} - self.buffers['search'] = Buffer('search', 'nofile') - self.buffers['backlinks'] = Buffer('backlinks', 'nofile') - self.buffers['revisions'] = Buffer('revisions', 'nofile') - self.buffers['changes'] = Buffer('changes', 'nofile') - self.buffers['index'] = Buffer('index', 'nofile') - self.buffers['media'] = Buffer('media', 'nofile') - self.buffers['help'] = Buffer('help', 'nofile') - - self.needs_refresh = False - self.diffmode = False - - self.cur_ns = '' - self.pages = [] - - self.default_sum = vim.eval('g:DokuVimKi_DEFAULT_SUM') - - self.index_winwith = vim.eval('g:DokuVimKi_INDEX_WINWIDTH') - self.index(self.cur_ns, True) - - vim.command('set laststatus=2') - vim.command('silent! ' + self.index_winwith + 'vsplit') - self.help() - - vim.command("command! -nargs=0 DokuVimKi echo 'DokuVimKi is already running!'") - - - def xmlrpc_init(self): - """ - Establishes the xmlrpc connection to the remote wiki. - """ - - try: - self.dw_user = vim.eval('g:DokuVimKi_USER') - self.dw_pass = vim.eval('g:DokuVimKi_PASS') - self.dw_url = vim.eval('g:DokuVimKi_URL') - except vim.error, err: - print >>sys.stderr, "Something went wrong during initialization. Please check your configuration settings." - return False - - try: - self.xmlrpc = dokuwikixmlrpc.DokuWikiClient(self.dw_url, self.dw_user, self.dw_pass) - print >>sys.stdout, 'Connection to ' + vim.eval('g:DokuVimKi_URL') + ' established!' - return True - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stderr, err - return False - except dokuwikixmlrpc.DokuWikiURLError, err: - print >>sys.stderr, err - return False - - - def edit(self, wp, rev=''): - """ - Opens a given wiki page, or a given revision of a wiki page for - editing or switches to the correct buffer if the is open already. - """ - - wp = wp.strip() - if wp.find(' ') != -1: - print >>sys.stderr, "Pagenames cannot contain whitespace. Please use valid pagenames only!\nSee http://dokuwiki.org/pagename" - return - - if self.diffmode: - self.diff_close() - - self.focus(2) - - if wp.find(':') == -1: - wp = self.cur_ns + wp - - if not self.buffers.has_key(wp): - - perm = int(self.xmlrpc.acl_check(wp)) - - if perm >= 1: - try: - if rev: - text = self.xmlrpc.page(wp, int(rev)) - else: - text = self.xmlrpc.page(wp) - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stdout, err - - if text: - if perm == 1: - print >>sys.stderr, "You don't have permission to edit %s. Opening readonly!" % wp - self.buffers[wp] = Buffer(wp, 'nowrite', True) - lines = text.split("\n") - self.buffers[wp].buf[:] = map(lambda x: x.encode('utf-8'), lines) - vim.command('setlocal nomodifiable') - vim.command('setlocal readonly') - - if perm >= 2: - if not self.lock(wp): - return - - print >>sys.stdout, "Opening %s for editing ..." % wp - self.buffers[wp] = Buffer(wp, 'acwrite', True) - lines = text.split("\n") - self.buffers[wp].page[:] = map(lambda x: x.encode('utf-8'), lines) - self.buffers[wp].buf[:] = self.buffers[wp].page - - vim.command('set nomodified') - vim.command('autocmd! BufWriteCmd py dokuvimki.save()') - vim.command('autocmd! FileWriteCmd py dokuvimki.save()') - vim.command('autocmd! FileAppendCmd py dokuvimki.save()') - - if not text and perm >= 4: - print >>sys.stdout, "Creating new page: %s" % wp - self.buffers[wp] = Buffer(wp, 'acwrite', True) - self.needs_refresh = True - - vim.command('set nomodified') - vim.command('autocmd! BufWriteCmd py dokuvimki.save()') - vim.command('autocmd! FileWriteCmd py dokuvimki.save()') - vim.command('autocmd! FileAppendCmd py dokuvimki.save()') - - self.buffer_setup() - - else: - print >>sys.stderr, "You don't have permissions to read/edit/create %s" % wp - return - - else: - self.needs_refresh = False - vim.command('silent! buffer! ' + self.buffers[wp].num) - - - def diff(self, revline): - """ - Opens a page and a given revision in diff mode. - """ - - data = revline.split() - wp = data[0] - rev = data[2] - date = time.strftime('%Y-%m-%d@%Hh%mm%Ss', time.localtime(float(rev))) - - if not self.buffers.has_key(wp): - self.edit(wp) - - if not self.buffers[wp].diff.has_key(rev): - text = self.xmlrpc.page(wp, int(rev)) - if text: - self.buffers[wp].diff[rev] = Buffer(wp + '_' + date, 'nofile') - lines = text.split("\n") - self.buffers[wp].diff[rev].page[:] = map(lambda x: x.encode('utf-8'), lines) - else: - print >>sys.stdout, "Error, couldn't load revision for diffing." - return - - self.focus(2) - vim.command('silent! buffer! ' + self.buffers[wp].num) - vim.command('vertical diffsplit') - self.focus(3) - vim.command('silent! buffer! ' + self.buffers[wp].diff[rev].num) - vim.command('setlocal modifiable') - vim.command('abbr close DWdiffclose') - vim.command('abbr DWclose DWdiffclose') - self.buffers[wp].diff[rev].buf[:] = self.buffers[wp].diff[rev].page - vim.command('setlocal nomodifiable') - self.buffer_setup() - vim.command('diffthis') - self.focus(2) - self.diffmode = True - - - def diff_close(self): - """ - Closes the diff window. - """ - - self.focus(3) - vim.command('diffoff') - vim.command('close') - self.diffmode = False - self.focus(2) - vim.command('vertical resize') - - - def save(self, sum='', minor=0): - """ - Saves the current buffer. Works only if the buffer is a wiki page. - Deleting wiki pages works like using the web interface, just delete all - text and save. - """ - - wp = vim.current.buffer.name.rsplit('/', 1)[1] - try: - if not self.buffers[wp].iswp: - print >>sys.stderr, "Error: Current buffer %s is not a wiki page or not writeable!" % wp - elif self.buffers[wp].type == 'nowrite': - print >>sys.stderr, "Error: Current buffer %s is readonly!" % wp - else: - text = "\n".join(self.buffers[wp].buf) - if text and not self.ismodified(wp): - print >>sys.stdout, "No unsaved changes in current buffer." - elif not text and not wp in self.pages: - print >>sys.stdout, "Can't save new empty page %s." % wp - else: - if not sum and text: - sum = self.default_sum - minor = 1 - - try: - self.xmlrpc.put_page(wp, text, sum, minor) - self.buffers[wp].page[:] = self.buffers[wp].buf - self.buffers[wp].need_save = False - - if text: - vim.command('silent! buffer! ' + self.buffers[wp].num) - vim.command('set nomodified') - print >>sys.stdout, 'Page %s written!' % wp - - if self.needs_refresh: - self.index(self.cur_ns, True) - self.needs_refresh = False - self.focus(2) - else: - print >>sys.stdout, 'Page %s removed!' % wp - self.close(False) - self.index(self.cur_ns, True) - self.focus(2) - - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stderr, 'DokuVimKi Error: %s' % err - except KeyError, err: - print >>sys.stderr, "Error: Current buffer %s is not handled by DWsave!" % wp - - - def upload(self, file, overwrite=False): - """ - Uploads a file to the remote wiki. - """ - - path = os.path.realpath(file) - fname = os.path.basename(path) - - if os.path.isfile(path): - try: - fh = open(path, 'r') - data = fh.read() - file_id = self.cur_ns + fname - try: - self.xmlrpc.put_file(file_id, data, overwrite) - print >>sys.stdout, "Uploaded %s successfully." % fname - self.refresh() - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stderr, err - except IOError, err: - print >>sys.stderr, err - else: - print >>sys.stderr, '%s is not a file' % path - - - def cd(self, query=''): - """ - Changes into the given namespace. - """ - - if query and query[-1] != ':': - query += ':' - - self.index(query) - - - def index(self, query='', refresh=False): - """ - Build the index used to navigate the remote wiki. - """ - - index = [] - pages = [] - dirs = [] - - self.focus(1) - vim.command('set winwidth=' + self.index_winwith) - vim.command('set winminwidth=' + self.index_winwith) - - vim.command('silent! buffer! ' + self.buffers['index'].num) - vim.command('setlocal modifiable') - vim.command('setlocal nonumber') - vim.command('syn match DokuVimKi_NS /^.*\//') - vim.command('syn match DokuVimKi_CURNS /^ns:/') - - vim.command('hi DokuVimKi_NS term=bold cterm=bold ctermfg=LightBlue gui=bold guifg=LightBlue') - vim.command('hi DokuVimKi_CURNS term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Yellow') - - if refresh: - self.refresh() - - if query and query[-1] != ':': - self.edit(query) - return - else: - self.cur_ns = query - - if self.pages: - for page in self.pages: - if not query: - if page.find(':', 0) == -1: - pages.append(page) - else: - ns = page.split(':', 1)[0] + '/' - if ns not in dirs: - dirs.append(ns) - else: - if re.search('^' + query, page): - page = page.replace(query, '') - if page.find(':') == -1: - if page not in index: - pages.append(page) - else: - ns = page.split(':', 1)[0] + '/' - if ns not in dirs: - dirs.append(ns) - - - index.append('ns: ' + self.cur_ns) - - if query: - index.append('.. (up a namespace)') - - index.append('') - - pages.sort() - dirs.sort() - index = index + dirs + pages - - self.buffers['index'].buf[:] = index - - vim.command('map :py dokuvimki.cmd("index")') - vim.command('map r :py dokuvimki.cmd("revisions")') - vim.command('map b :py dokuvimki.cmd("backlinks")') - - vim.command('setlocal nomodifiable') - vim.command('2') - - - def changes(self, timeframe=False): - """ - Shows the last changes on the remote wiki. - """ - - if self.diffmode: - self.diff_close() - - self.focus(2) - - vim.command('silent! buffer! ' + self.buffers['changes'].num) - vim.command('setlocal modifiable') - - if not timeframe: - timestamp = int(time.time()) - (60*60*24*7) - else: - m = re.match(r'(?P\d+)(?P[dw]{1})', timeframe) - if m: - argv = m.groupdict() - - if argv['type'] == 'd': - timestamp = int(time.time()) - (60*60*24*int(argv['num'])) - elif argv['type'] == 'w': - timestamp = int(time.time()) - (60*60*24*(int(argv['num'])*7)) - else: - print >>sys.stderr, "Wrong timeframe format %s." % timeframe - return - else: - print >>sys.stderr, "Wrong timeframe format %s." % timeframe - return - - try: - changes = self.xmlrpc.recent_changes(timestamp) - lines = [] - if len(changes) > 0: - maxlen = 0; - for change in changes: - changelen = len(change['name']) - if changelen > maxlen: - maxlen = changelen - - for change in changes: - change['name'] = change['name'] + ' ' * (maxlen - len(change['name'])) - line = "\t".join(map(lambda x: str(change[x]), ['name', 'lastModified', 'version', 'author'])) - lines.append(line) - - lines.reverse() - self.buffers['changes'].buf[:] = lines - vim.command('syn match DokuVimKi_REV_PAGE /^\(\w\|:\)*/') - vim.command('syn match DokuVimKi_REV_TS /\s\d*\s/') - - vim.command('hi DokuVimKi_REV_PAGE cterm=bold ctermfg=Yellow gui=bold guifg=Yellow') - vim.command('hi DokuVimKi_REV_TS cterm=bold ctermfg=Yellow gui=bold guifg=Yellow') - - vim.command('setlocal nomodifiable') - vim.command('map :py dokuvimki.rev_edit()') - - else: - print >>sys.stderr, 'DokuVimKi Error: No changes' - - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stderr, err - - - def revisions(self, wp='', first=0): - """ - Display revisions for a certain page if any. - """ - - if self.diffmode: - self.diff_close() - - if not wp or wp[-1] == ':': - return - - try: - self.focus(2) - - vim.command('silent! buffer! ' + self.buffers['revisions'].num) - vim.command('setlocal modifiable') - - revs = self.xmlrpc.page_versions(wp, int(first)) - lines = [] - if len(revs) > 0: - for rev in revs: - line = wp + "\t" + "\t".join(map(lambda x: str(rev[x]), ['modified', 'version', 'ip', 'type', 'user', 'sum'])) - lines.append(line) - - self.buffers['revisions'].buf[:] = lines - print >>sys.stdout, "loaded revisions for :%s" % wp - vim.command('map :py dokuvimki.rev_edit()') - - vim.command('syn match DokuVimKi_REV_PAGE /^\(\w\|:\)*/') - vim.command('syn match DokuVimKi_REV_TS /\s\d*\s/') - vim.command('syn match DokuVimKi_REV_CHANGE /\s\w\{1}\s/') - - vim.command('hi DokuVimKi_REV_PAGE term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Yellow') - vim.command('hi DokuVimKi_REV_TS term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Yellow') - vim.command('hi DokuVimKi_REV_CHANGE term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Yellow') - - vim.command('setlocal nomodifiable') - vim.command('map d :py dokuvimki.cmd("diff")') - - else: - print >>sys.stderr, 'DokuVimKi Error: No revisions found for page: %s' % wp - - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stderr, 'DokuVimKi XML-RPC Error: %s' % err - - - def backlinks(self, wp=''): - """ - Display backlinks for a certain page if any. - """ - - if self.diffmode: - self.diff_close() - - if not wp or wp[-1] == ':': - return - - try: - self.focus(2) - - vim.command('silent! buffer! ' + self.buffers['backlinks'].num) - vim.command('setlocal modifiable') - - blinks = self.xmlrpc.backlinks(wp) - - if len(blinks) > 0: - for link in blinks: - self.buffers['backlinks'].buf[:] = map(str, blinks) - vim.command('map :py dokuvimki.cmd("edit")') - else: - print >>sys.stderr, 'DokuVimKi Error: No backlinks found for page: %s' % wp - - vim.command('setlocal nomodifiable') - - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stderr, 'DokuVimKi XML-RPC Error: %s' % err - - - def search(self, type='', pattern=''): - """ - Search the page list for matching pages and display them for editing. - """ - - if self.diffmode: - self.diff_close() - - self.focus(2) - - try: - if type == 'page': - vim.command('silent! buffer! ' + self.buffers['search'].num) - vim.command('setlocal modifiable') - - if pattern: - p = re.compile(pattern) - result = filter(p.search, self.pages) - else: - result = self.pages - - if len(result) > 0: - self.buffers['search'].buf[:] = result - vim.command('map :py dokuvimki.cmd("edit")') - else: - print >>sys.stderr, 'DokuVimKi Error: No matching pages found!' - - elif type == 'media': - vim.command('silent! buffer! ' + self.buffers['media'].num) - vim.command('setlocal modifiable') - - if pattern: - p = re.compile(pattern) - result = filter(p.search, self.media) - else: - result = self.media - - if len(result) > 0: - self.buffers['media'].buf[:] = result - else: - print >>sys.stderr, 'DokuVimKi Error: No matching media files found!' - - vim.command('setlocal nomodifiable') - - except: - pass - - - def close(self, bang): - """ - Closes the current buffer. Works only if the current buffer is a wiki - page. The buffer is also removed from the buffer stack. - """ - - if self.diffmode: - self.diff_close() - return - - try: - buffer = vim.current.buffer.name.rsplit('/', 1)[1] - if self.buffers[buffer].iswp: - if not bang and self.ismodified(buffer): - print >>sys.stderr, "Warning: %s contains unsaved changes! Use DWclose!." % buffer - return - - vim.command('bp!') - vim.command('bdel! ' + self.buffers[buffer].num) - if self.buffers[buffer].type == 'acwrite': - self.unlock(buffer) - del self.buffers[buffer] - else: - print >>sys.stderr, 'You cannot close special buffer "%s"!' % buffer - - except KeyError, err: - print >>sys.stderr, 'You cannot use DWclose on non wiki page "%s"!' % buffer - - - def quit(self, bang): - """ - Quits the current session. - """ - - unsaved = [] - - for buffer in self.buffers.keys(): - if self.buffers[buffer].iswp: - if not self.ismodified(buffer): - vim.command('silent! buffer! ' + self.buffers[buffer].num) - self.close(False) - elif self.ismodified(buffer) and bang: - vim.command('silent! buffer! ' + self.buffers[buffer].num) - self.close(True) - else: - unsaved.append(buffer) - - if len(unsaved) == 0: - vim.command('silent! quitall') - else: - print >>sys.stderr, "Some buffers contain unsaved changes. Use DWquit! if you really want to quit." - - - def help(self): - """ - Shows the plugin help. - """ - - if self.diffmode: - self.diff_close() - - self.focus(2) - vim.command('silent! buffer! ' + self.buffers['help'].num) - vim.command('silent! set buftype=help') - - # generate help tags just in case - vim.command('helptags ~/.vim/bundle/dokuvimki/doc') - vim.command('help dokuvimki') - vim.command("setlocal statusline=%{'[help]'}") - - - def ismodified(self, buffer): - """ - Checks whether the current buffer or a given buffer is modified or not. - """ - - if self.buffers[buffer].need_save: - return True - elif "\n".join(self.buffers[buffer].page).strip() != "\n".join(self.buffers[buffer].buf).strip(): - return True - else: - return False - - - def rev_edit(self): - """ - Special mapping for editing revisions from the revisions listing. - """ - - row, col = vim.current.window.cursor - wp = vim.current.buffer[row-1].split("\t")[0].strip() - rev = vim.current.buffer[row-1].split("\t")[2].strip() - self.edit(wp, rev) - - - def focus(self, winnr): - """ - Convenience function to switch the current window focus. - """ - - if int(vim.eval('winnr()')) != winnr: - vim.command(str(winnr) + 'wincmd w') - - - def refresh(self): - """ - Refreshes the page index by retrieving a fresh list of all pages on the - remote server and updating the completion dictionary. - """ - - self.pages = [] - self.media = [] - - try: - print >>sys.stdout, "Refreshing page index!" - data = self.xmlrpc.all_pages() - - if data: - for page in data: - page = page['id'].encode('utf-8') - ns = page.rsplit(':', 1)[0] + ':' - self.pages.append(page) - if not ns in self.pages: - self.pages.append(ns) - self.media.append(ns) - - - self.pages.sort() - vim.command('let g:pages = "' + " ".join(self.pages) + '"') - - print >>sys.stdout, "Refreshing media index!" - data = self.xmlrpc.list_files(':', True) - - if data: - for media in data: - self.media.append(media['id'].encode('utf-8')) - - self.media.sort() - vim.command('let g:media = "' + " ".join(self.media) + '"') - - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stderr, "Failed to fetch page list. Please check your configuration\n%s" % err - - - def lock(self, wp): - """ - Tries to obtain a lock given wiki page. - """ - - locks = {} - locks['lock'] = [ wp ] - locks['unlock'] = [] - - result = self.set_locks(locks) - - if locks['lock'] == result['locked']: - print >>sys.stdout, "Locked page %s for editing." % wp - return True - else: - print >>sys.stderr, 'The page "%s" appears to be locked for editing. You have to wait until the lock expires.' % wp - return False - - - def unlock(self, wp): - """ - Tries to unlock a given wiki page. - """ - - locks = {} - locks['lock'] = [] - locks['unlock'] = [ wp ] - - result = self.set_locks(locks) - if locks['unlock'] == result['unlocked']: - return True - else: - return False - - - def set_locks(self, locks): - """ - Locks unlocks a given set of pages. - """ - - try: - return self.xmlrpc.set_locks(locks) - except dokuwikixmlrpc.DokuWikiXMLRPCError, err: - print >>sys.stderr, err - - - def id_lookup(self): - """ - When editing pages, hiting enter while over a wiki link will open the - page. This functions tries to guess the correct wiki page. - """ - line = vim.current.line - row, col = vim.current.window.cursor - - # get namespace from current page - wp = vim.current.buffer.name.rsplit('/', 1)[1] - ns = wp.rsplit(':', 1)[0] - if ns == wp: - ns = '' - - # look for link syntax on the left and right from the current curser position - reL = re.compile('\[{2}[^]]*$') # opening link syntax - reR = re.compile('^[^\[]*]{2}') # closing link syntax - - L = reL.search(line[:col]) - R = reR.search(line[col:]) - - # if both matched we probably have a link - if L and R: - - # sanitize match remove anchors and everything after '|' - id = (L.group() + R.group()).strip('[]').split('|')[0].split('#')[0] - - # check if it's not and external/interwiki/share link - if id.find('>') == -1 and id.find('://') == -1 and id.find('\\') == -1: - - # check if useshlash is used - if id.find('/'): - id = id.replace('/', ':') - - # this is _almost_ a rip off of DokuWikis resolve_id() function - if id[0] == '.': - re_sanitize = re.compile('(\.(?=[^:\.]))') - id = re_sanitize.sub('.:', id) - id = ns + ':' + id - path = id.split(':') - - result = [] - for dir in path: - if dir == '..': - try: - if result[-1] == '..': - result.append('..') - elif not result.pop(): - result.append('..') - except IndexError: - pass - elif dir and dir != '.' and not len(dir.split('.')) > 2: - result.append(dir) - - id = ':'.join(result) - - elif ns and id[0] != ':' and id.find(':', 0) == -1: - id = ns + ':' + id - - # we're done, open the page for editing - print >>sys.stdout, id - self.edit(id) - - - def cmd(self, cmd): - """ - Callback function to provides various functionality for the page index - (like open namespaces or triggering edit showing backlinks etc). - """ - - row, col = vim.current.window.cursor - line = vim.current.buffer[row-1] - - # first line triggers nothing in index buffer - if row == 1 and line.find('ns: ') != -1: - return - - if line.find('..') == -1: - if line.find('/') == -1: - if not line: - print >>sys.stdout, "meh" - else: - line = self.cur_ns + line - else: - line = self.cur_ns + line.replace('/', ':') - else: - line = self.cur_ns.rsplit(':', 2)[0] + ':' - if line == ":" or line == self.cur_ns: - line = '' - - callback = getattr(self, cmd) - callback(line) - - - def buffer_enter(self, wp): - """ - Loads the buffer on enter. - """ - - self.buffers[wp].buf[:] = self.buffers[wp].page - vim.command('setlocal nomodified') - self.buffer_setup() - - - def buffer_leave(self, wp): - if "\n".join(self.buffers[wp].buf).strip() != "\n".join(self.buffers[wp].page).strip(): - self.buffers[wp].page[:] = self.buffers[wp].buf - self.buffers[wp].need_save = True - - - def buffer_setup(self): - """ - Setup edit environment. - """ - - vim.command('setlocal textwidth=0') - vim.command('setlocal wrap') - vim.command('setlocal linebreak') - vim.command('setlocal syntax=dokuwiki') - vim.command('setlocal filetype=dokuwiki') - vim.command('setlocal tabstop=2') - vim.command('setlocal expandtab') - vim.command('setlocal shiftwidth=2') - vim.command('setlocal encoding=utf-8') - vim.command('map e :py dokuvimki.id_lookup()') - vim.command('imap ****1hi') - vim.command('imap ////1hi') - vim.command('imap ____1hi') - vim.command('imap [[]]1hi') - vim.command('imap {{}}1hi') - vim.command('imap ki') - vim.command('imap ki') - vim.command('imap Headline()') - vim.command('imap SetLvl(+1)') - vim.command('imap SetLvl(-1)') - - - -class Buffer: - """ - Representates a vim buffer object. Used to manage keep track of all opened - pages and to handle the dokuvimki special buffers. - - self.num = buffer number (starts at 1) - self.id = buffer id (starts at 0) - self.buf = vim buffer object - self.name = buffer name - self.iswp = True if buffer represents a wiki page - """ - - id = None - num = None - name = None - buf = None - - def __init__(self, name, type, iswp=False): - """ - Instanziates a new buffer. - """ - vim.command('badd ' + name) - self.num = vim.eval('bufnr("' + name + '")') - self.id = int(self.num) - 1 - self.buf = vim.buffers[self.id] - self.name = name - self.iswp = iswp - self.type = type - self.page = [] - vim.command('silent! buffer! ' + self.num) - vim.command('setlocal buftype=' + type) - vim.command('abbr close DWclose') - vim.command('abbr close! DWclose!') - vim.command('abbr quit DWquit') - vim.command('abbr quit! DWquit!') - vim.command('abbr q DWquit') - vim.command('abbr q! DWquit!') - vim.command('abbr qa DWquit') - vim.command('abbr qa! DWquit!') - - - if type == 'nofile': - vim.command('setlocal nobuflisted') - vim.command('setlocal nomodifiable') - vim.command('setlocal noswapfile') - vim.command("setlocal statusline=%{'[" + self.name + "]'}") - - if type == 'acwrite': - self.diff = {} - self.need_save = False - vim.command('autocmd! BufEnter py dokuvimki.buffer_enter("' + self.name + '")') - vim.command('autocmd! BufLeave py dokuvimki.buffer_leave("' + self.name + '")') - vim.command("setlocal statusline=%{'[wp]\ " + self.name + "'}\ %r\ [%c,%l][%p]") - - if type == 'nowrite': - self.diff = {} - vim.command("setlocal statusline=%{'[wp]\ " + self.name + "'}\ %r\ [%c,%l][%p%%]") - - - -def dokuvimki(): - """ - Creates the global dokuvimki instance. - """ - global dokuvimki - dokuvimki = DokuVimKi() - - -EOF - else - command! -nargs=0 DokuVimKi echoerr "DokuVimKi disabled! Python support missing or vim version not supported." -endif -" vim:ts=4:sw=4:et:enc=utf-8: diff --git a/bundle/dokuvimki/syntax/dokuwiki.vim b/bundle/dokuvimki/syntax/dokuwiki.vim deleted file mode 100644 index 43a5433..0000000 --- a/bundle/dokuvimki/syntax/dokuwiki.vim +++ /dev/null @@ -1,220 +0,0 @@ -" DokuWiki Vim Syntaxfile -" Language: DokuWiki Pages (http://wiki.splitbrain.org/wiki:dokuwiki) -" Maintainer: Michael Klier -" URL: http://www.chimeric.de/projects/dokuwiki/dokuvimki - -if !exists("main_syntax") - if version < 600 - syntax clear - elseif exists("b:current_syntax") - finish - endif - let main_syntax = "dokuwiki" -endif - -syn case ignore -syn spell toplevel -syn sync linebreaks=1 - -syn match DokuHeadline #^ \=\(=\{2,6}\)\(=\)\@!.\+\1 *$# -syn match DokuRule #^ \=-\{4,} *$# -syn match DokuMonospaced #''[^'[\]]\+''# -syn match DokuNewLine #\\\\\( \{1,}\|$\)# -syn match DokuSmileys #8-)\|8-O\|:-(\|:-)\|=)\|:-/\|:-\\\|:-?\|:-D\|:-P\|:-O\|:-X\|:-|\|;-)\|:?:\|:!:\|\^_\^\|LOL\|FIXME\|DELETEME# -syn match DokuList #^\( \{2}\| \{4}\| \{6}\| \{8}\| \{10}\| \{12}\| \{14}\| \{16}\| \{18}\| \{20}\| \{22}\| \{24}\)\(\-\|\*\)# -syn match DokuNoWiki #%%[^%]\+%%# -syn match DokuQuote #^>\+# -syn match DokuLinkInterwiki #[a-z]\+># contained -syn match DokuLinkExternal #\(http\|https\)\=\(://\)\=\(www\.\)\(\a\|-\)\+\(\.\{1}\l\{2,3}\)\=[^| \]]*# -syn match DokuLinkMail #<[^@]\+@[^>]\+># -syn match DokuLinkTitle #|\zs[^|\]{}]\+# contained -syn match DokuImageMode #?[^}]\+# contained -syn match DokuTableTH #\^# contained -syn match DokuTableTD #|# contained - -syn region DokuLink start=#\[\[# end=#\]\]# contains=DokuLinkInterwiki,DokuLinkExternal,DokuLinkTitle,DokuMedia oneline -syn region DokuMedia start=#{{# end=#}}# contains=DokuLinkExternal,DokuImageMode,DokuLinkTitle oneline - -syn region DokuSub start=## end=## keepend -syn region DokuSup start=## end=## keepend -syn region DokuDel start=## end=## keepend -syn region DokuFootnote matchgroup=DokuFootnoteMatch start=#((# end=#))# contains=DokuLink,DokuLinkInterwiki,DokuLinkExternal,DokuLinkTitle,DokuMedia,DokuBold,DokuMonospaced,DokuItalic,DokuUnderlined,DokuSmileys,DokuSub,DokuSup,DokuDel keepend - -syn region DokuFileGeneric matchgroup=DokuFileMatch start=## end=## keepend -syn region DokuCodeGeneric matchgroup=DokuCodeMatch start=## end=## keepend - -syn region DokuBold start=#\*\*# end=#\*\*# contains=DokuItalic,DokuUnderlined,DokuLink oneline -syn region DokuItalic start=#//# end=#//# skip=#://# contains=DokuBold,DokuUnderlined,DokuLink oneline -syn region DokuUnderlined start=#__# end=#__# contains=DokuBold,DokuItalic,DokuLink oneline -syn region DokuTableTH start=#\^# end=#\^\|# contains=DokuTableTH,DokuLink,DokuMedia,DokuBold,DokuItalic,DokuUnderlined,DokuMonospaced,DokuSmileys,DokuNewLine oneline -syn region DokuTableTD start=#|# end=#|\|# contains=DokuTableTD,DokuLink,DokuMedia,DokuBold,DokuItalic,DokuUnderlined,DokuMonospaced,DokuSmileys,DokuNewLine oneline - -"syn include @abap syntax/abap.vim -"syn region Dokuabap matchgroup=DokuCodeMatch start=## end=## contains=@abap -"syn include @ada syntax/ada.vim -"syn region Dokuada matchgroup=DokuCodeMatch start=## end=## contains=@ada -"syn include @apache syntax/apache.vim -"syn region Dokuapache matchgroup=DokuCodeMatch start=## end=## contains=@apache -"syn include @asm syntax/asm.vim -"syn region Dokuasm matchgroup=DokuCodeMatch start=## end=## contains=@asm -"syn include @autohotkey syntax/autohotkey.vim -"syn region Dokuautohotkey matchgroup=DokuCodeMatch start=## end=## contains=@autohotkey -"syn include @autoit syntax/autoit.vim -"syn region Dokuautoit matchgroup=DokuCodeMatch start=## end=## contains=@autoit -"syn include @awk syntax/awk.vim -"syn region Dokuawk matchgroup=DokuCodeMatch start=## end=## contains=@awk -"syn include @cmake syntax/cmake.vim -"syn region Dokucmake matchgroup=DokuCodeMatch start=## end=## contains=@cmake -"syn include @cobol syntax/cobol.vim -"syn region Dokucobol matchgroup=DokuCodeMatch start=## end=## contains=@cobol -"syn include @c syntax/c.vim -"syn region Dokuc matchgroup=DokuCodeMatch start=## end=## contains=@c -"syn include @cpp syntax/cpp.vim -"syn region Dokucpp matchgroup=DokuCodeMatch start=## end=## contains=@cpp -"syn include @css syntax/css.vim -"syn region Dokucss matchgroup=DokuCodeMatch start=## end=## contains=@css -"syn include @diff syntax/diff.vim -"syn region Dokudiff matchgroup=DokuCodeMatch start=## end=## contains=@diff -"syn include @dot syntax/dot.vim -"syn region Dokudot matchgroup=DokuCodeMatch start=## end=## contains=@dot -"syn include @d syntax/d.vim -"syn region Dokud matchgroup=DokuCodeMatch start=## end=## contains=@d -"syn include @eiffel syntax/eiffel.vim -"syn region Dokueiffel matchgroup=DokuCodeMatch start=## end=## contains=@eiffel -"syn include @erlang syntax/erlang.vim -"syn region Dokuerlang matchgroup=DokuCodeMatch start=## end=## contains=@erlang -"syn include @fortran syntax/fortran.vim -"syn region Dokufortran matchgroup=DokuCodeMatch start=## end=## contains=@fortran -"syn include @freebasic syntax/freebasic.vim -"syn region Dokufreebasic matchgroup=DokuCodeMatch start=## end=## contains=@freebasic -"syn include @gdb syntax/gdb.vim -"syn region Dokugdb matchgroup=DokuCodeMatch start=## end=## contains=@gdb -"syn include @gnuplot syntax/gnuplot.vim -"syn region Dokugnuplot matchgroup=DokuCodeMatch start=## end=## contains=@gnuplot -"syn include @groovy syntax/groovy.vim -"syn region Dokugroovy matchgroup=DokuCodeMatch start=## end=## contains=@groovy -"syn include @haskell syntax/haskell.vim -"syn region Dokuhaskell matchgroup=DokuCodeMatch start=## end=## contains=@haskell -"syn include @idl syntax/idl.vim -"syn region Dokuidl matchgroup=DokuCodeMatch start=## end=## contains=@idl -"syn include @java syntax/java.vim -"syn region Dokujava matchgroup=DokuCodeMatch start=## end=## contains=@java -"syn include @javascript syntax/javascript.vim -"syn region Dokujavascript matchgroup=DokuCodeMatch start=## end=## contains=@javascript -"syn include @lisp syntax/lisp.vim -"syn region Dokulisp matchgroup=DokuCodeMatch start=## end=## contains=@lisp -"syn include @logtalk syntax/logtalk.vim -"syn region Dokulogtalk matchgroup=DokuCodeMatch start=## end=## contains=@logtalk -"syn include @lscript syntax/lscript.vim -"syn region Dokulscript matchgroup=DokuCodeMatch start=## end=## contains=@lscript -"syn include @lua syntax/lua.vim -"syn region Dokulua matchgroup=DokuCodeMatch start=## end=## contains=@lua -"syn include @make syntax/make.vim -"syn region Dokumake matchgroup=DokuCodeMatch start=## end=## contains=@make -"syn include @matlab syntax/matlab.vim -"syn region Dokumatlab matchgroup=DokuCodeMatch start=## end=## contains=@matlab -"syn include @mmix syntax/mmix.vim -"syn region Dokummix matchgroup=DokuCodeMatch start=## end=## contains=@mmix -"syn include @modula3 syntax/modula3.vim -"syn region Dokumodula3 matchgroup=DokuCodeMatch start=## end=## contains=@modula3 -"syn include @mysql syntax/mysql.vim -"syn region Dokumysql matchgroup=DokuCodeMatch start=## end=## contains=@mysql -"syn include @nsis syntax/nsis.vim -"syn region Dokunsis matchgroup=DokuCodeMatch start=## end=## contains=@nsis -"syn include @objc syntax/objc.vim -"syn region Dokuobjc matchgroup=DokuCodeMatch start=## end=## contains=@objc -"syn include @ocaml syntax/ocaml.vim -"syn region Dokuocaml matchgroup=DokuCodeMatch start=## end=## contains=@ocaml -"syn include @pascal syntax/pascal.vim -"syn region Dokupascal matchgroup=DokuCodeMatch start=## end=## contains=@pascal -"syn include @perl syntax/perl.vim -"syn region Dokuperl matchgroup=DokuCodeMatch start=## end=## contains=@perl -"syn include @php syntax/php.vim -"syn region Dokuphp matchgroup=DokuCodeMatch start=## end=## contains=@php -"syn include @pike syntax/pike.vim -"syn region Dokupike matchgroup=DokuCodeMatch start=## end=## contains=@pike -"syn include @plsql syntax/plsql.vim -"syn region Dokuplsql matchgroup=DokuCodeMatch start=## end=## contains=@plsql -"syn include @progress syntax/progress.vim -"syn region Dokuprogress matchgroup=DokuCodeMatch start=## end=## contains=@progress -"syn include @prolog syntax/prolog.vim -"syn region Dokuprolog matchgroup=DokuCodeMatch start=## end=## contains=@prolog -"syn include @python syntax/python.vim -"syn region Dokupython matchgroup=DokuCodeMatch start=## end=## contains=@python -"syn include @rebol syntax/rebol.vim -"syn region Dokurebol matchgroup=DokuCodeMatch start=## end=## contains=@rebol -"syn include @robots syntax/robots.vim -"syn region Dokurobots matchgroup=DokuCodeMatch start=## end=## contains=@robots -"syn include @ruby syntax/ruby.vim -"syn region Dokuruby matchgroup=DokuCodeMatch start=## end=## contains=@ruby -"syn include @sas syntax/sas.vim -"syn region Dokusas matchgroup=DokuCodeMatch start=## end=## contains=@sas -"syn include @scheme syntax/scheme.vim -"syn region Dokuscheme matchgroup=DokuCodeMatch start=## end=## contains=@scheme -"syn include @scilab syntax/scilab.vim -"syn region Dokuscilab matchgroup=DokuCodeMatch start=## end=## contains=@scilab -"syn include @smarty syntax/smarty.vim -"syn region Dokusmarty matchgroup=DokuCodeMatch start=## end=## contains=@smarty -"syn include @sql syntax/sql.vim -"syn region Dokusql matchgroup=DokuCodeMatch start=## end=## contains=@sql -"syn include @tcl syntax/tcl.vim -"syn region Dokutcl matchgroup=DokuCodeMatch start=## end=## contains=@tcl -"syn include @vb syntax/vb.vim -"syn region Dokuvb matchgroup=DokuCodeMatch start=## end=## contains=@vb -"syn include @verilog syntax/verilog.vim -"syn region Dokuverilog matchgroup=DokuCodeMatch start=## end=## contains=@verilog -"syn include @vhdl syntax/vhdl.vim -"syn region Dokuvhdl matchgroup=DokuCodeMatch start=## end=## contains=@vhdl -"syn include @vim syntax/vim.vim -"syn region Dokuvim matchgroup=DokuCodeMatch start=## end=## contains=@vim -"syn include @whitespace syntax/whitespace.vim -"syn region Dokuwhitespace matchgroup=DokuCodeMatch start=## end=## contains=@whitespace -"syn include @winbatch syntax/winbatch.vim -"syn region Dokuwinbatch matchgroup=DokuCodeMatch start=## end=## contains=@winbatch -"syn include @xml syntax/xml.vim -"syn region Dokuxml matchgroup=DokuCodeMatch start=## end=## contains=@xml - -" costum color groups -hi DokuHeadline term=bold,underline cterm=bold,underline gui=bold,underline -hi DokuNewLine term=bold cterm=bold ctermfg=Red gui=bold guifg=Red -hi DokuRule term=bold cterm=bold ctermfg=Red gui=bold guifg=Red -hi DokuQuote term=bold cterm=bold ctermfg=Red gui=bold guifg=Red -hi DokuLink term=bold cterm=bold ctermfg=Green gui=bold guifg=Green -hi DokuMedia term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Darkyellow -hi DokuLinkInterwiki term=bold cterm=bold ctermfg=Red gui=bold guifg=Red -hi DokuImageMode term=bold cterm=bold ctermfg=Red gui=bold guifg=Red -hi DokuLinkExternal term=bold cterm=bold ctermfg=Magenta gui=bold guifg=Magenta -hi DokuLinkMail term=bold cterm=bold ctermfg=Magenta gui=bold guifg=Magenta -hi DokuLinkTitle term=bold cterm=bold ctermfg=Blue gui=bold guifg=Blue -hi DokuSmileys term=bold ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black -hi DokuItalic term=italic cterm=italic gui=italic -hi DokuBold term=bold cterm=bold gui=bold -hi DokuUnderlined term=underline cterm=underline gui=underline -hi DokuSub term=bold ctermbg=LightBlue ctermfg=Black guibg=LightBlue guifg=Black -hi DokuSup term=bold ctermbg=LightBlue ctermfg=Black guibg=LightBlue guifg=Black -hi DokuDel term=bold ctermbg=LightRed ctermfg=Black guibg=LightRed guifg=Black -hi DokuList term=bold cterm=bold ctermfg=Green gui=bold guifg=Green -hi DokuTableTH term=bold cterm=bold ctermfg=Blue gui=bold guifg=Blue -hi DokuTableTD term=bold cterm=bold ctermfg=Blue gui=bold guifg=Blue -hi DokuNoWiki ctermbg=Gray ctermfg=Black guibg=Gray guifg=Black - -" color groups -hi DokuBlockColor ctermbg=Gray ctermfg=Black guibg=Gray guifg=Black -hi DokuFormatColor cterm=bold ctermfg=Gray gui=bold guifg=Gray - -" link to groups -hi link DokuMonospaced DokuFormatColor -hi link DokuFile DokuBlockColor -hi link DokuCode DokuBlockColor -hi link DokuCodeMatch DokuBlockColor -hi link DokuFileMatch DokuBlockColor -hi link DokuNoWiki DokuBlockColor -hi link DokuFootnoteMatch DokuBlockColor - -let b:current_syntax = "dokuwiki" - -if main_syntax == 'dokuwiki' - unlet main_syntax -endif - -" vim:ts=2:sw=2:et:enc=utf-8: diff --git a/plugin/vimchat.vim b/plugin/vimchat.vim new file mode 100644 index 0000000..e05caad --- /dev/null +++ b/plugin/vimchat.vim @@ -0,0 +1,1667 @@ +" VImChat Plugin for vim +" This plugin allows you to connect to jabber servers and chat with +" multiple people. +" +" It does not currently support other IM networks or group chat, +" but these are on the list to be added. +" +" It is also worth noting that you can use aim/yahoo via jabber transports, +" but the transports must be set up on another client as vimchat does not +" support setting them up yet +" +" This branchh supports multiple versions at a time, but probably still +" has a decent amount of bugs! +" +" Note: The vimchat_jid and vimchat_password variables have been *changed* +" into the vimchat_accounts dictionary. This version of vimchat will not +" work unless you make this change! +" +" Supported ~/.vimrc Variables: +" g:vimchat_accounts = {'jabber id':'password',...} +" g:vimchat_buddylistwidth = width of buddy list +" g:vimchat_libnotify = (0 or 1) default is 1 +" g:vimchat_logpath = path to store log files +" g:vimchat_logchats = (0 or 1) default is 1 +" g:vimchat_otr = (0 or 1) default is 0 +" g:vimchat_logotr = (0 or 1) default is 1 +" g:vimchat_statusicon = (0 or 1) default is 1 + + +python < ~/.vimchat/vimchat.debug') + vim.command('nnoremap B :py VimChat.toggleBuddyList()') + vim.command('let s:hasVars = VimChatCheckVars()') + self.setupLeaderMappings() + hasVars = int(vim.eval('s:hasVars')) + + if hasVars < 1: + print "Could not start VimChat!" + return 0 + + #Libnotify + libnotify = int(vim.eval('g:vimchat_libnotify')) + if libnotify == 1: + pynotify_enabled = True + else: + pynotify_enabled = False + + otr_enabled = int(vim.eval('g:vimchat_otr')) + otr_logging = int(vim.eval('g:vimchat_logotr')) + if otr_enabled == 1: + if otr_logging == 1: + pyotr_logging = True + else: + pyotr_logging = False + else: + pyotr_enabled = False + pyotr_logging = False + + isStatusIcon = int(vim.eval('g:vimchat_statusicon')) + if isStatusIcon != 1: + self.gtk_enabled = False + + if self.gtk_enabled: + self.statusIcon = self.StatusIcon() + self.statusIcon.start() + + # Signon to accounts listed in .vimrc + if vim.eval("exists('g:vimchat_accounts')") == '1': + vimChatAccounts = vim.eval('g:vimchat_accounts') + for jid,password in vimChatAccounts.items(): + self._signOn(jid,password) + + # Signon to accounts listed in .vimchat/config + if os.path.exists(self.configFilePath): + config = RawConfigParser(); + config.read(self.configFilePath) + if config.has_section('accounts'): + for jid in config.options('accounts'): + password = config.get('accounts', jid) + self._signOn(jid, password) + + #}}} + + #CLASSES + #{{{ class OtrOps + class OtrOps: + #{{{ __init__ + def __init__(self,parent=None): + self.parent = parent + #}}} + + #{{{ policy + def policy(self, opdata=None, context=None): + """ checks for the contacts username in policylist and returns it + if available, otherwise checks for a default entry and returns it + if available, otherwise just return python-otr's default """ + return otr.OTRL_POLICY_DEFAULT + #}}} + #{{{ create_privkey + def create_privkey(self, opdata=None, accountname=None, protocol=None): + # should give the user some visual feedback here, generating can take some time! + # the private key MUST be available when this method returned + print "Need OTR key for: " + accountname + ". :VimChatGenerateKey to create one" + #TODO + #VimChat.otrGenerateKey() + #}}} + #{{{ is_logged_in + def is_logged_in(self, opdata=None, accountname=None, protocol=None, recipient=None): + if accountname in VimChat.accounts.keys(): + if recipient: + priority = VimChat.accounts[accountname]._roster.getPriority(recipient) + if priority: + return True + return False + else: + return False + else: + return False + #}}} + #{{{ inject_message + def inject_message(self, opdata=None, accountname=None, protocol=None, recipient=None, message=None): + if accountname in VimChat.accounts.keys(): + if recipient and message: + VimChat.accounts[accountname].jabberSendMessage(recipient, message) + else: + print "Error in inject_message" + #}}} + #{{{ notify + def notify(sef, opdata=None, level=None, accountname=None, protocol=None, username=None, title=None, primary=None, secondary=None): + # show a small dialog or something like that + # level is otr.OTRL_NOTIFY_ERROR, otr.OTRL_NOTIFY_WARNING or otr.OTRL_NOTIFY_INFO + # primary and secondary are the messages that should be displayed + print "Notify: title: " + title + " primary: " + primary + \ + " secondary: " + secondary + #}}} + #{{{ display_otr_message + def display_otr_message(self, opdata=None, accountname=None, protocol=None, username=None, msg=None): + # this usually logs to the conversation window + + #write_message(our_account=accountname, proto=protocol, contact=username, message=msg) + # NOTE: this function MUST return 0 if it processed the message + # OR non-zero, the message will then be passed to notify() by OTR + print "Got OTR Message" + return 0 + #}}} + #{{{ update_context_list + def update_context_list(self, opdata=None): + # this method may provide some visual feedback when the context list was updated + # this may be useful if you have a central way of setting fingerprints' trusts + # and you want to update the list of contexts to consider in this way + pass + #}}} + #{{{ protocol_name + def protocol_name(self, opdata=None, protocol=None): + """ returns a "human-readable" version of the given protocol """ + if protocol == "xmpp": + return "XMPP (eXtensible Messaging and Presence Protocol)" + #}}} + #{{{ new_fingerprint + def new_fingerprint( + self, opdata=None, userstate=None, accountname=None, + protocol=None, username=None, fingerprint=None): + + human_fingerprint = "" + try: + human_fingerprint = otr.otrl_privkey_hash_to_human(fingerprint) + #write_message(our_account=accountname, proto=protocol, contact=username, + # message="New fingerprint: %s"%human_fingerprint) + return human_fingerprint + except: + pass + #}}} + #{{{ write_fingerprints + def write_fingerprints(self, opdata=None): + fpath = os.path.expanduser( + VimChat.otr_basedir + '/' + VimChat.otr_fingerprints) + for jid,account in VimChat.accounts.items(): + otr.otrl_privkey_write_fingerprints( + account._otr_userstate, fpath) + else: + print "User: " + str(account) + " not connected" + #}}} + #{{{ gone_secure + def gone_secure(self, opdata=None, context=None): + trust = context.active_fingerprint.trust + if trust: + trust = "V" + else: + trust = "U" + + buf = VimChat.beginChat(context.accountname, context.username) + if buf: + VimChat.appendStatusMessage(context.accountname, + buf,"[OTR]","-- " + trust + " OTR Connection Started") + print trust+" OTR Connection Started with "+str(context.username) + #}}} + #{{{ gone_insecure + def gone_insecure(self, opdata=None, context=None): + connection = VimChat.accounts[context.accountname] + buf = self.getBufByName(connection._chats[context.username]) + if buf: + VimChat.appendStatusMessage(context.accountname, + buf,"[OTR]","-- Secured OTR Connection Ended") + print "Secure OTR Connection Ended with " + context.username + #}}} + #{{{ still_secure + def still_secure(self, opdata=None, context=None, is_reply=0): + # this is called when the OTR session was refreshed + # (ie. new session keys have been created) + # is_reply will be 0 when we started we started that refresh, + # 1 when the contact started it + try: + connection = VimChat.accounts[context.accountname] + buf = self.getBufByName(connection._chats[context.username]) + if buf: + jid = "[OTR]" + VimChat.appendStatusMessage(context.accountname, + buf,"[OTR]","-- Secured OTR Connection Refreshed") + print "Secure OTR Connection Refreshed with "+str(context.username) + except Exception, e: + print "Error in still_secure: " + str(e) + #}}} + #{{{ log_message + def log_message(self, opdata=None, message=None): + # log message to a logfile or something + pass + #}}} + #{{{ max_message_size + def max_message_size(self, opdata=None, context=None): + """ looks up the max_message_size for the relevant protocol """ + # return 0 when no limit is defined + #return msg_size[context.protocol] + return 0 + #}}} + #{{{ account_name + def account_name( + self, opdata=None, account=None, context=None, protocol=None): + + #return find_account(accountname=account, protocol).name + if account in VimChat.accounts.keys(): + jid = VimChat.accounts[account]._jid.split('/')[0] + print "accountname: " + jid + return jid + else: + print "Could not get account name" + #}}} + #}}} + #{{{ class JabberConnection + class JabberConnection(threading.Thread): + + #{{{ class Variables + _roster = {} + _chats = {} + #}}} + + #Init Stuff + #{{{ __init__ + def __init__(self, parent, jid, jabberClient, roster): + self._parent = parent + self._jid = jid + self._jids = jid.split('/')[0] + self._roster = roster + threading.Thread.__init__ ( self ) + self.jabber = jabberClient + self._protocol = 'xmpp' + #}}} + #{{{ run + def run(self): + self.jabber.RegisterHandler('message',self.jabberMessageReceive) + self.jabber.RegisterHandler('presence',self.jabberPresenceReceive) + self.jabberPresenceUpdate() + + #Socket stuff + RECV_BUF = 4096 + self.xmppS = self.jabber.Connection._sock + socketlist = [self.xmppS] + online = 1 + + #set up otr + self.otrSetup() + + while online: + (i , o, e) = select.select(socketlist,[],[],1) + for each in i: + if each == self.xmppS: + self.jabber.Process(1) + else: + pass + #}}} + + #From Jabber Functions + #{{{ jabberMessageReceive + def jabberMessageReceive(self, conn, msg): + if msg.getBody(): + fromJid = str(msg.getFrom()) + type = str(msg.getType()).lower() + jid = fromJid.split('/')[0] + body = unicode(msg.getBody()) + body = str(body.encode('utf8')) + + if pyotr_enabled and type != "groupchat": + #OTR Stuff + #{{{ Check for verification stuff + is_internal, message, tlvs = otr.otrl_message_receiving( + self._otr_userstate, ( + VimChat.OtrOps(),None),self._jids,self._protocol,jid, body) + + context = otr.otrl_context_find( + self._otr_userstate,jid,self._jids,self._protocol,1)[0] + + + + if otr.otrl_tlv_find(tlvs, otr.OTRL_TLV_SMP_ABORT) is not None: + self.otrAbortVerify(context) + elif otr.otrl_tlv_find(tlvs, otr.OTRL_TLV_SMP1) is not None: + if context.smstate.nextExpected != otr.OTRL_SMP_EXPECT1: + self.otrAbortVerify(context) + else: + #TODO: prompt user for secret + pass + elif otr.otrl_tlv_find(tlvs, otr.OTRL_TLV_SMP1Q) is not None: + if context.smstate.nextExpected != otr.OTRL_SMP_EXPECT1: + self.otrAbortVerify(context) + else: + tlv = otr.otrl_tlv_find(tlvs, otr.OTRL_TLV_SMP1Q) + VimChat.otrSMPRequestNotify( + context.accountname, context.username,tlv.data) + elif otr.otrl_tlv_find(tlvs, otr.OTRL_TLV_SMP2) is not None: + if context.smstate.nextExpected != otr.OTRL_SMP_EXPECT2: + self.otrAbortVerify(context) + else: + context.smstate.nextExpected = otr.OTRL_SMP_EXPECT4 + elif otr.otrl_tlv_find(tlvs, otr.OTRL_TLV_SMP3) is not None: + if context.smstate.nextExpected != otr.OTRL_SMP_EXPECT3: + self.otrAbortVerify(context) + else: + if context.smstate.sm_prog_state == \ + otr.OTRL_SMP_PROG_SUCCEEDED: + self.otrSMPVerifySuccess(context) + print "Successfully verified " + context.username + else: + self.otrSMPVerifyFailed(context) + print "Failed to verify " + context.username + elif otr.otrl_tlv_find(tlvs, otr.OTRL_TLV_SMP4) is not None: + if context.smstate.nextExpected != otr.OTRL_SMP_EXPECT4: + self.otrAbortVerify(context) + else: + context.smstate.nextExpected = otr.OTRL_SMP_EXPECT1 + if context.smstate.sm_prog_state == \ + otr.OTRL_SMP_PROG_SUCCEEDED: + self.otrSMPVerifySuccess(context) + print "Successfully verified " + context.username + else: + self.otrSMPVerifyFailed(context) + print "Failed to verify " + context.username + #}}} + + secure = False + type = otr.otrl_proto_message_type(body) + if type == otr.OTRL_MSGTYPE_DATA \ + and type != otr.OTRL_MSGTYPE_NOTOTR \ + and type != otr.OTRL_MSGTYPE_TAGGEDPLAINTEXT: + + if context.active_fingerprint: + trust = context.active_fingerprint.trust + if trust: + secure = "V" + else: + secure = "U" + + if not is_internal: + VimChat.messageReceived(self._jids, fromJid, message.strip(),secure) + + elif type == "groupchat": + parts = fromJid.split('/') + chatroom = parts[0] + if len(parts) > 1: + user = parts[1] + else: + user = "--" + VimChat.messageReceived( + self._jids, user, body.strip(), False, chatroom) + else: + VimChat.messageReceived(self._jids, fromJid,body.strip()) + #}}} + #{{{ jabberPresenceReceive + def jabberPresenceReceive(self, conn, msg): + #TODO: figure out better way than this try/except block + try: + fromJid = msg.getFrom() + type = str(msg.getType()).lower() + show = str(unicode(msg.getShow()).encode('utf-8')) + status = str(unicode(msg.getStatus()).encode('utf-8')) + priority = str(unicode(msg.getPriority()).encode('utf-8')) + #print fromJid, ' jid: ', msg.getJid(), ' status: ', status, ' reason: ', msg.getReason(), ' stat code: ', msg.getStatusCode() + + if show == "None": + if priority != "None": + show = 'online' + else: + show = 'offline' + + if type == "groupchat": + parts = fromJid.split('/') + chatroom = parts[0] + user = "" + if len(parts) > 1: + user = parts[1] + + VimChat.presenceUpdate(self._jids, + str(chatroom), str(user), show,status,priority) + else: + VimChat.presenceUpdate(self._jids, + str(fromJid), fromJid,show,status,priority) + except: + pass + #}}} + + #To Jabber Functions + #{{{ jabberOnSendMessage + def jabberOnSendMessage(self, tojid, msg): + msg = msg.strip() + if not pyotr_enabled: + self.jabberSendMessage(tojid,msg) + return 0 + + #only if otr is enabled + new_message = otr.otrl_message_sending( + self._otr_userstate,(VimChat.OtrOps(),None), + self._jids,self._protocol,tojid,msg,None) + + context = otr.otrl_context_find( + self._otr_userstate,tojid,self._jids,self._protocol,1)[0] + + #if context.msgstate == otr.OTRL_MSGSTATE_ENCRYPTED + otr.otrl_message_fragment_and_send( + (VimChat.OtrOps(),None),context,new_message,otr.OTRL_FRAGMENT_SEND_ALL) + #}}} + #{{{ jabberSendMessage + def jabberSendMessage(self, tojid, msg): + msg = msg.strip() + m = xmpp.protocol.Message(to=tojid,body=msg,typ='chat') + self.jabber.send(m) + #}}} + #{{{ jabberSendGroupChatMessage + def jabberSendGroupChatMessage(self, room, msg): + msg = msg.strip() + m = xmpp.protocol.Message(to=room,body=msg,typ='groupchat') + self.jabber.send(m) + #}}} + #{{{ jabberJoinGroupChat + def jabberJoinGroupChat(self, room, name): + roomStr = room + '/' + name + self.jabber.send(xmpp.Presence(to=roomStr)) + #}}} + #{{{ jabberLeaveGroupChat + def jabberLeaveGroupChat(self, room): + self.jabber.send(xmpp.Presence(to=room,typ='unavailable')) + #}}} + #{{{ jabberPresenceUpdate + def jabberPresenceUpdate(self, show='', status='', priority=5): + m = xmpp.protocol.Presence( + None, + show=show, + priority=priority, + status=status) + self._presence = m + self.jabber.send(m) + #}}} + #{{{ jabberGetPresence + def jabberGetPresence(self): + show = self._presence.getShow() + status = self._presence.getStatus() + return [show,status] + #}}} + #{{{ disconnect + def disconnect(self): + try: + self.jabber.disconnect() + except: + pass + #}}} + #{{{ isConnected + def isConnected(self): + return self.jabber.isConnected() + #}}} + + #Roster Functions + #{{{ getRosterItems + def getRosterItems(self): + if self._roster: + return self._roster.getItems() + else: + return None + #}}} + + #OTR Functions + #{{{ otrSetup + def otrSetup(self): + #Set Up OTR Stuff If Available + if not pyotr_enabled: + return 0 + + self._otr_userstate = otr.otrl_userstate_create() + + keypath = os.path.expanduser( + VimChat.otr_basedir + '/' + VimChat.otr_keyfile) + + #Make the otr directory + basedir = os.path.expanduser(VimChat.otr_basedir) + if not os.path.exists(basedir): + os.makedirs(basedir) + + if not os.path.isfile(keypath): + #Create it if it doesn't exist + file(keypath,'w') + jid = self._jid.split('/')[0] + + print "No OTR Key found for " + self._jids + \ + ". :VimChatOtrGenerateKey to make one." + else: + pass + if os.access(keypath, os.R_OK): + try: + otr.otrl_privkey_read(self._otr_userstate,keypath) + except: + pass + + + fprintPath = os.path.expanduser( + VimChat.otr_basedir + '/' + VimChat.otr_fingerprints) + if not os.path.isfile(fprintPath): + #Create it if it doesn't exist + file(fprintPath,'w') + else: + if os.access(fprintPath, os.R_OK): + try: + otr.otrl_privkey_read_fingerprints( + self._otr_userstate,fprintPath) + except: + pass + #}}} + #{{{ otrDisconnectChat + def otrDisconnectChat(self, jid): + context = otr.otrl_context_find( + self._otr_userstate,jid,self._jids,self._protocol,1)[0] + + if context.msgstate == otr.OTRL_MSGSTATE_ENCRYPTED: + otr.otrl_message_disconnect( + self._otr_userstate,(VimChat.OtrOps(),None), + self._jids,self._protocol,jid) + #}}} + #{{{ otrManualVerifyBuddy + def otrManualVerifyBuddy(self, jid): + self.otrSetTrust(jid,"manual") + buf = VimChat.beginChat(self._jids, jid) + if buf: + VimChat.appendStatusMessage( self._jids, + buf,"[OTR]","-- Verified Fingerprint of " + jid) + print "Verified "+jid + #}}} + #{{{ otrSMPVerifyBuddy + def otrSMPVerifyBuddy(self, jid, question, secret): + context = otr.otrl_context_find( + self._otr_userstate,jid,self._jids,self._protocol,1)[0] + + otr.otrl_message_initiate_smp_q( + self._otr_userstate,(VimChat.OtrOps(), None),context,question,secret) + + buf = VimChat.beginChat(self._jids, jid) + if buf: + VimChat.appendMessage(context.accountname, + buf,"-- Sent Question to "+ jid +" for verification.") + print "Sent Question for verification to "+str(context.username) + #}}} + #{{{ otrSMPVerifySuccess + def otrSMPVerifySuccess(self,context): + jid = context.username + self.otrSetTrust(jid,"smp") + buf = VimChat.beginChat(context.accountname, jid) + if buf: + VimChat.appendStatusMessage(context.accountname, + buf,"[OTR]", + "-- Secret answered! "+ jid +" is verified.") + print jid + " Gave correct secret -- verified!" + #}}} + #{{{ otrSMPVerifyFailed + def otrSMPVerifyFailed(self,context): + jid = context.username + self.otrSetTrust(jid,"") + buf = VimChat.beginChat(context.accountname, jid) + if buf: + VimChat.appendStatusMessage(context.accountname, + buf,"[OTR]", + "-- Secret response Failed! "+ jid + " is NOT verified.") + print jid + " Failed to answer secret, NOT verified!" + #}}} + #{{{ otrSMPRespond + def otrSMPRespond(self,jid,secret): + context = otr.otrl_context_find( + self._otr_userstate,jid,self._jids,self._protocol,1)[0] + + otr.otrl_message_respond_smp( + self._otr_userstate,(VimChat.OtrOps(),None),context,secret) + buf = VimChat.beginChat(self._jids, jid) + if buf: + VimChat.appendStatusMessage(context.accountname, + buf,"[OTR]","-- Sent Secret to "+ jid +"") + print "Sent secret response to " + jid + #}}} + #{{{ otrGeneratePrivateKey + def otrGeneratePrivateKey(self): + keypath = os.path.expanduser( + VimChat.otr_basedir + '/' + VimChat.otr_keyfile) + jid = self._jid.split('/')[0] + otr.otrl_privkey_generate( + self._otr_userstate, keypath, jid, self._protocol) + #}}} + #{{{ otrAbortVerify + def otrAbortVerify(self,context): + otr.otrl_message_abort_smp( + self._otr_userstate, (VimChat.OtrOps(), None), context) + #}}} + #{{{ otrSetTrust + def otrSetTrust(self, jid, trust): + context = otr.otrl_context_find( + self._otr_userstate,jid,self._jids,self._protocol,1)[0] + otr.otrl_context_set_trust(context.active_fingerprint,trust) + #}}} + #{{{ otrIsChatEncrypted + def otrIsChatEncrypted(self, account, jid): + context = otr.otrl_context_find( + VimChat.accounts[account]._otr_userstate,jid, + VimChat.accounts[account]._jids, + VimChat.accounts[account]._protocol,1)[0] + + if context.msgstate == otr.OTRL_MSGSTATE_ENCRYPTED: + return True + else: + return False + #}}} + #}}} + #{{{ class StatusIcon + class StatusIcon(threading.Thread): + def run(self): + # GTK StausIcon + gtk.gdk.threads_init() + self.status_icon = StatusIcon() + self.status_icon.set_from_file(os.path.expanduser( + '~/.vimchat/icon.gif')) + self.status_icon.set_tooltip("VimChat") + self.status_icon.set_visible(True) + gtk.main() + def blink(self, value): + self.status_icon.set_blinking(value) + #}}} + + #CONNECTION FUNCTIONS + #{{{ signOn + def signOn(self): + accounts = self.getAccountsFromConfig() + if len(accounts) == 0: + print 'No acounts found in the vimchat config %s.'\ + % (self.configFilePath) + return + for account in accounts: + print account + account = vim.eval( + 'input("Enter the account from the above list: ")') + if account in accounts: + password = accounts[account] + self._signOn(account, password) + else: + print 'Error: [%s] is an invalid account.' % (account) + #}}} + #{{{ _signOn + def _signOn(self, jid, password): + if not password: + password = vim.eval('inputsecret("' + jid + ' password: ")') + [jidSmall,user,resource] = self.getJidParts(jid) + print "Connecting user " + jid + "..." + if jidSmall in self.accounts: + try: self.accounts[jidSmall].disconnect() + except: pass + + JID=xmpp.protocol.JID(jid) + jabberClient = xmpp.Client(JID.getDomain(),debug=[]) + + con = jabberClient.connect() + if not con: + print 'could not connect!\n' + return 0 + + auth=jabberClient.auth( + JID.getNode(), password, resource=JID.getResource()) + if not auth: + print 'could not authenticate!\n' + return 0 + + jabberClient.sendInitPresence(requestRoster=1) + roster = jabberClient.getRoster() + + [accountJid,user,resource] = self.getJidParts(jid) + if accountJid in self.accounts: + try: + self.accounts[accountJid].disconnect() + except: pass + self.accounts[accountJid] = self.JabberConnection( + self, jid, jabberClient, roster) + self.accounts[accountJid].start() + + print "Connected with " + jid + #}}} + #{{{ signOff + def signOff(self): + accounts = self.accounts + if len(accounts) == 0: + print 'No acounts found' + return + for account in accounts: + print account + account = vim.eval( + 'input("Enter the account from the above list: ")') + self._signOff(account) + #}}} + #{{{ _signOff + def _signOff(self, account): + accounts = self.accounts + if account in accounts: + try: + accounts[account].disconnect() + del accounts[account] + print "Signed Off VimChat!" + except: + print "Error signing off %s VimChat!" % (account) + print sys.exc_info()[0:2] + else: + print 'Error: [%s] is an invalid account.' % (account) + #}}} + #{{{ showStatus + def showStatus(self): + print self.accounts[self.accounts.keys()[0]].jabberGetPresence() + #}}} + + #HELPER FUNCTIONS + #{{{ formatPresenceUpdateLine + def formatPresenceUpdateLine(self, fromJid, show, status): + tstamp = self.getTimestamp() + return tstamp + " -- " + str(fromJid) + \ + " is " + str(show) + ": " + str(status) + #}}} + #{{{ getJidParts + def getJidParts(self, jid): + jidParts = str(jid).split('/') + # jid: bob@foo.com + jid = jidParts[0] + # user: bob + user = jid.split('@')[0] + + #Get A Resource if exists + if len(jidParts) > 1: + resource = jidParts[1] + else: + resource = '' + + return [jid,user,resource] + #}}} + #{{{ getTimestamp + def getTimestamp(self): + return time.strftime("[%H:%M]") + #}}} + #{{{ getBufByName + def getBufByName(self, name): + for buf in vim.buffers: + if buf.name and buf.name.split('/')[-1] == name: + return buf + return None + #}}} + #{{{ isGroupChat + def isGroupChat(self): + try: + groupchat = int(vim.eval('b:groupchat')) + if groupchat == 1: + return True + except: + pass + + return False + #}}} + + #BUDDY LIST + #{{{ toggleBuddyList + def toggleBuddyList(self): + # godlygeek's way to determine if a buffer is hidden in one line: + #:echo len(filter(map(range(1, tabpagenr('$')), 'tabpagebuflist(v:val)'), 'index(v:val, 4) == 0')) + + if not self.accounts: + print "Not Connected! Please connect first." + return 0 + + if self.buddyListBuffer: + bufferList = vim.eval('tabpagebuflist()') + if str(self.buddyListBuffer.number) in bufferList: + vim.command('sbuffer ' + str(self.buddyListBuffer.number)) + vim.command('hide') + return + + #Write buddy list to file + self.writeBuddyList() + + buddyListWidth = vim.eval('g:vimchat_buddylistwidth') + + try: + vim.command("silent vertical sview " + self.rosterFile) + vim.command("silent wincmd H") + vim.command("silent vertical resize " + buddyListWidth) + vim.command("silent e!") + vim.command("setlocal noswapfile") + vim.command("setlocal nomodifiable") + vim.command("setlocal buftype=nowrite") + except Exception, e: + print e + vim.command("new " + self.rosterFile) + + + commands = """ + setlocal foldtext=VimChatFoldText() + setlocal nowrap + setlocal foldmethod=marker + nmap :py VimChat.beginChatFromBuddyList() + nnoremap l :py VimChat.openLogFromBuddyList() + nnoremap B :py VimChat.toggleBuddyList() + nnoremap q :py VimChat.toggleBuddyList() + nnoremap c :py VimChat.openGroupChat() + nnoremap ss :py VimChat.setStatus() + nnoremap :silent exec 'vertical resize ' . (winwidth('.') > g:vimchat_buddylistwidth ? (g:vimchat_buddylistwidth) : '') + """ + + vim.command(commands) + self.setupLeaderMappings() + + self.buddyListBuffer = vim.current.buffer + #}}} + #{{{ getBuddyListItem + def getBuddyListItem(self, item): + if item == 'jid': + vim.command("normal zo") + vim.command("normal ]z") + vim.command("normal [z") + vim.command("normal j") + + toJid = vim.current.line + toJid = toJid.strip() + + vim.command("normal zc") + vim.command("normal [z") + + account = str(vim.current.line).split(' ')[2] + + return account, toJid + #}}} + #{{{ beginChatFromBuddyList + def beginChatFromBuddyList(self): + account, toJid = self.getBuddyListItem('jid') + [jid,user,resource] = self.getJidParts(toJid) + + buf = VimChat.beginChat(account, jid) + if not buf: + #print "Error getting buddy info: " + jid + return 0 + + + vim.command('sbuffer ' + str(buf.number)) + VimChat.toggleBuddyList() + vim.command('wincmd K') + #}}} + #{{{ writeBuddyList + def writeBuddyList(self): + #write roster to file + import codecs + rF = codecs.open(self.rosterFile,'w','utf-16') + + for curJid, account in self.accounts.items(): + if not account.isConnected(): + rF.write( +u""" +****************************** +ERROR: %s IS NOT CONNECTED!!! +You can type \on to reconnect. +****************************** +""" % (curJid)) + continue + accountText = u"{{{ [+] %s\n"%(curJid) + rF.write(accountText) + + roster = account._roster + rosterItems = roster.getItems() + rosterItems.sort() + for item in rosterItems: + name = roster.getName(item) + status = roster.getStatus(item) + show = roster.getShow(item) + priority = roster.getPriority(item) + groups = roster.getGroups(item) + + if not name: + name = item + if not status: + status = u'' + if not show: + if priority: + show = u'on' + else: + show = u'off' + if not priority: + priority = u'' + if not groups: + groups = u'' + + if show != u'off': + buddyText =\ + u"{{{ (%s) %s\n\t%s \n\tGroups: %s\n\t%s:\n%s\n}}}\n" %\ + (show, name, item, groups, show, status) + rF.write(buddyText) + + rF.write("}}}\n") + + rF.close() + #}}} + + #CHAT BUFFERS + #{{{ beginChat + def beginChat(self, fromAccount, toJid, groupChat = False): + #return 0 + #Set the ChatFile + connection = self.accounts[fromAccount] + if toJid in connection._chats.keys(): + chatFile = connection._chats[toJid] + else: + if groupChat: + chatFile = 'groupchat:' + toJid + else: + chatFile = 'chat:' + toJid + + connection._chats[toJid] = chatFile + + bExists = int(vim.eval('buflisted("' + chatFile + '")')) + if bExists: + #TODO: Need to call sbuffer only if buffer is hidden. + #vim.command('sbuffer ' + chatFile) + return self.getBufByName(chatFile) + else: + vim.command("split " + chatFile.replace('%', r'\%')) + #Only do this stuff if its a new buffer + if groupChat: + vim.command('let b:groupchat=1') + else: + vim.command('let b:groupchat=0') + + vim.command("let b:buddyId = '" + toJid + "'") + vim.command("let b:account = '" + fromAccount + "'") + self.setupChatBuffer(groupChat); + return vim.current.buffer + + #}}} + #{{{ setupChatBuffer + def setupChatBuffer(self, isGroupChat=False): + commands = """ + setlocal noswapfile + setlocal buftype=nowrite + setlocal noai + setlocal nocin + setlocal nosi + setlocal filetype=vimchat + setlocal syntax=vimchat + setlocal wrap + setlocal foldmethod=marker + nnoremap i :py VimChat.sendBufferShow() + nnoremap o :py VimChat.sendBufferShow() + nnoremap a :py VimChat.sendBufferShow() + nnoremap B :py VimChat.toggleBuddyList() + nnoremap q :py VimChat.deleteChat() + au CursorMoved exe 'py VimChat.clearNotify()' + """ + vim.command(commands) + self.setupLeaderMappings() + if isGroupChat: + vim.command('setlocal foldmethod=syntax') + #}}} + #{{{ setupLeaderMappings + def setupLeaderMappings(self): + commands = """ + nnoremap l :py VimChat.openLogFromChat() + nnoremap ov :py VimChat.otrVerifyBuddy() + nnoremap or :py VimChat.otrSmpRespond() + nnoremap c :py VimChat.openGroupChat() + nnoremap j :py VimChat.joinChatroom() + nnoremap on :py VimChat.signOn() + nnoremap off :py VimChat.signOff() + """ + vim.command(commands) + #}}} + #{{{ sendBufferShow + def sendBufferShow(self): + toJid = vim.eval('b:buddyId') + account = vim.eval('b:account') + groupChat = vim.eval('b:groupchat') + + #Create sending buffer + sendBuffer = "sendTo:" + toJid + vim.command("silent bo new " + sendBuffer) + vim.command("silent let b:buddyId = '" + toJid + "'") + vim.command("silent let b:account = '" + account + "'") + vim.command("setlocal filetype=vimchat") + + commands = """\ + resize 4 + setlocal noswapfile + setlocal nocin + setlocal noai + setlocal nosi + setlocal buftype=nowrite + setlocal wrap + setlocal foldmethod=marker + noremap :py VimChat.sendMessage() + inoremap :py VimChat.sendMessage() + nnoremap q :hide + """ + vim.command(commands) + vim.command('normal G') + vim.command('normal o') + vim.command('normal zt') + vim.command('star') + vim.command('let b:groupchat=' + str(groupChat)) + + #}}} + #{{{ appendMessage + def appendMessage( + self, account, buf, message, showJid='Me',secure=False): + + if not buf: + print "VimChat: Invalid Buffer to append to!" + return 0 + + lines = message.split("\n") + tstamp = self.getTimestamp() + + jid,user,resource = self.getJidParts(showJid) + logJid = buf.name.split('/')[-1].split(':')[1] + + secureString = "" + if secure: + secureString = "(*" + secure + "*)" + + #Get the first line + if resource: + line = tstamp + secureString + \ + user + "/" + resource + ": " + lines.pop(0); + else: + line = tstamp + secureString + user + ": " + lines.pop(0); + + buf.append(line) + #TODO: remove these lines + #line = line.replace("'", "''") + #vim.command("call append(line('$'),'" + line + "')") + if not secure or pyotr_logging: + VimChat.log(account, logJid, line) + + for line in lines: + line = '\t' + line + buf.append(line) + #line = line.replace("'", "''") + #vim.command("call append(line('$'),'" + line + "')") + #if message is not secure, or if otr logging is on + if not secure or pyotr_logging: + VimChat.log(account, logJid, line) + + #move cursor to bottom of buffer + self.moveCursorToBufBottom(buf) + #}}} + #{{{ appendStatusMessage + def appendStatusMessage(self, account, buf, prefix, message): + if not buf: + print "VimChat: Invalid Buffer to append to!" + return 0 + + jid = buf.name.split('/')[-1].split(':')[1] + jid,user,resource = self.getJidParts(jid) + + lines = message.split("\n") + tstamp = self.getTimestamp() + + #Get the first line + line = tstamp + prefix + ": " + lines.pop(0); + + buf.append(line) + VimChat.log(account, jid, line) + + for line in lines: + line = '\t' + line + buf.append(line) + VimChat.log(account, jid, line) + + #move cursor to bottom of buffer + #self.moveCursorToBufBottom(buf) + #}}} + #{{{ deleteChat + def deleteChat(self): + #remove it from chats list + jid = vim.eval('b:buddyId') + account = vim.eval('b:account') + + if pyotr_enabled: + self.accounts[account].otrDisconnectChat(jid) + + del self.accounts[account]._chats[jid] + + #Check if it was a groupchat + if self.isGroupChat(): + self.accounts[account].jabberLeaveGroupChat(jid) + vim.command('bdelete!') + #}}} + #{{{ openGroupChat + def openGroupChat(self): + accounts = self.showAccountList() + + input = vim.eval( + 'input("Account (enter the number from the above list): ")') + if not re.match(r'\d+$', input): + vim.command('echohl ErrorMsg') + vim.command('echo "\\nYou must enter an integer corresponding' + + ' to an account."') + vim.command('echohl None') + return + index = int(input) + if index < 0 or index >= len(accounts): + vim.command('echohl ErrorMsg') + vim.command(r'echo "\nInvalid account number. Try again."') + vim.command('echohl None') + return + + account = accounts[index] + chatroom = vim.eval('input("Chat Room to join: ")') + name = vim.eval('input("Name to Use: ")') + self._openGroupChat(account, chatroom, name) + #}}} + #{{{ _openGroupChat + def _openGroupChat(self, account, chatroom, name): + self.groupChatNames.append(name) + buf = VimChat.beginChat(account._jids, chatroom, True) + vim.command('sbuffer ' + str(buf.number)) + account.jabberJoinGroupChat(chatroom, name) + #}}} + #{{{ echoError + def echoError(self, msg): + vim.command('echohl ErrorMsg') + vim.command(r'echo "\n"') + vim.command("echo '" + msg.replace("'", "''") + "'") + vim.command('echohl None') + #}}} + #{{{ joinChatroom + def joinChatroom(self): + if not os.path.exists(self.configFilePath): + print 'Error: Config file %s does not exist' % (self.configFilePath) + return + + chatrooms = {} + try: + config = RawConfigParser() + config.read(self.configFilePath) + for section in config.sections(): + if not section.startswith('chatroom:'): + continue + tokens = section.split(':') + if len(tokens) < 2: + continue + roomAlias = tokens[1] + data = {} + data['account'] = config.get(section, 'account') + data['room'] = config.get(section, 'room') + data['username'] = config.get(section, 'username') + chatrooms[roomAlias] = data + except: + print 'Error: Problems reading the vimchat config %s.'\ + % (self.configFilePath) + print sys.exc_info()[0], sys.exc_info()[1] + return + + for room in chatrooms: + print room + input = vim.eval( + 'input("Enter the room name from the above list: ")') + if input in chatrooms: + self._openGroupChat(self.accounts[chatrooms[input]['account']], + chatrooms[input]['room'], chatrooms[input]['username']) + else: + print 'Error: [%s] is an invalid chatroom.' % (input) + #}}} + #{{{ moveCursorToBufBottom + def moveCursorToBufBottom(self, buf): + # TODO: Need to make sure this only happens if this buffer doesn't + # have focus. Otherwise, this hijacks the users cursor. + return + for w in vim.windows: + if w.buffer == buf: + w.cursor = (len(buf), 0) + #}}} + + #ACCOUNT + #{{{ showAccountList + def showAccountList(self): + accounts = [] + i = 0 + for jid,account in self.accounts.items(): + accounts.append(account) + print str(i) + ": " + jid + i = i + 1 + + return accounts + #}}} + #{{{ getAccountsFromConfig + def getAccountsFromConfig(self): + accounts = {} + if not os.path.exists(self.configFilePath): + print 'Error: Config file %s does not exist' % (self.configFilePath) + return {} + try: + config = RawConfigParser() + config.read(self.configFilePath) + for account in config.options('accounts'): + accounts[account] = config.get('accounts', account) + except: + print 'Error reading accounts from the vimchat config %s.'\ + % (self.configFilePath), sys.exc_info()[0:2] + return {} + return accounts + #}}} + + #LOGGING + #{{{ log + def log(self, account, user, msg): + logChats = int(vim.eval('g:vimchat_logchats')) + if logChats > 0: + logPath = vim.eval('g:vimchat_logpath') + logDir = \ + os.path.expanduser(logPath + '/' + account + '/' + user) + if not os.path.exists(logDir): + os.makedirs(logDir) + + day = time.strftime('%Y-%m-%d') + log = open(logDir + '/' + user + '-' + day, 'a') + log.write(msg + '\n') + log.close() + #}}} + #{{{ openLogFromBuddyList + def openLogFromBuddyList(self): + account, jid = VimChat.getBuddyListItem('jid') + VimChat.openLog(account, jid) + #}}} + #{{{ openLogFromChat + def openLogFromChat(self): + try: + jid = vim.eval('b:buddyId') + except: + print "You may only open the log from a chat buffer" + return + account = vim.eval('b:account') + if jid != '' and account != '': + VimChat.openLog(account, jid) + else: + print "Invalid chat window!" + #}}} + #{{{ openLog + def openLog(self, account, jid): + logPath = vim.eval('g:vimchat_logpath') + logDir = \ + os.path.expanduser(logPath + '/' + account + '/' + jid) + print logDir + if not os.path.exists(logDir): + print "No Logfile Found" + return 0 + else: + print "Opening log for: " + logDir + vim.command('tabe ' + logDir) + #}}} + + #OUTGOING + #{{{ sendMessage + def sendMessage(self): + try: + toJid = vim.eval('b:buddyId') + account = vim.eval('b:account') + except: + print "No valid chat found!" + return 0 + + connection = self.accounts[account] + chatBuf = self.getBufByName(connection._chats[toJid]) + if not chatBuf: + print "Chat Buffer Could not be found!" + return 0 + + r = vim.current.range + body = "" + for line in r: + body = body + line + '\n' + + body = body.strip() + + if self.isGroupChat(): + connection.jabberSendGroupChatMessage(toJid, body) + else: + connection.jabberOnSendMessage(toJid, body) + + secure = False + + if pyotr_enabled: + secure = connection.otrIsChatEncrypted(account, toJid) + if secure: + secure = "e" + + if not self.isGroupChat(): + VimChat.appendMessage(account, chatBuf,body,'Me',secure) + + + vim.command('hide') + vim.command('sbuffer ' + str(chatBuf.number)) + vim.command('normal G') + #}}} + #{{{ setStatus + def setStatus(self, status=None): + if not status: + status = str(vim.eval('input("Status: (away,xa,dnd,chat),message,priority: ")')) + + parts = status.split(',') + show = parts[0] + status = '' + priority = 10 + if len(parts) > 1: + status = parts[1] + if len(parts) > 2: + priority = parts[2] + + for jid,account in self.accounts.items(): + account.jabberPresenceUpdate(show,status,priority) + + print "Updated status to: " + str(priority) + " -- " + show + " -- " + status + #}}} + + #INCOMING + #{{{ presenceUpdate + def presenceUpdate(self, account, chat, fromJid, show, status, priority): + try: + #Only care if we have the chat window open + fullJid = fromJid + [fromJid,user,resource] = self.getJidParts(fromJid) + [chat,nada,nada2] = self.getJidParts(fromJid) + + connection = VimChat.accounts[account] + + if chat in connection._chats.keys(): + #Make sure buffer exists + chatFile = connection._chats[fromJid] + if chatFile.startswith('groupchat'): + return + chatBuf = self.getBufByName(chatFile) + bExists = int(vim.eval('buflisted("' + chatFile + '")')) + if chatBuf and bExists: + statusUpdateLine = self.formatPresenceUpdateLine(fullJid,show,status) + if chatBuf[-1] != statusUpdateLine: + chatBuf.append(statusUpdateLine) + self.moveCursorToBufBottom(chatBuf) + else: + #Should never get here! + print "Buffer did not exist for: " + fromJid + except Exception, e: + print "Error in presenceUpdate: " + str(e) + + #}}} + #{{{ messageReceived + def messageReceived(self, account, fromJid, message, secure=False, groupChat=""): + #Store the buffer we were in + origBufNum = vim.current.buffer.number + + # Commented out the next 2 lines. For some reason, when the orig + # buffer is the buddy list, it causes a bug that makes it so you + # don't receive any more messages. + # + #if origBufNum == self.buddyListBuffer.number: + # vim.command('wincmd w') + + #Get Jid Parts + [jid,user,resource] = self.getJidParts(fromJid) + + if groupChat: + if re.search('has (joined|quit|part).+\(.=.+@.+\)$', message): + return + buf = VimChat.beginChat(account, groupChat) + else: + buf = VimChat.beginChat(account, jid) + + try: + VimChat.appendMessage(account, buf, message, fromJid, secure) + except: + print 'Error zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' + print 'could not appendMessage:', message, 'from:', fromJid + + # Highlight the line. + # TODO: This only works if the right window has focus. Otherwise it + # highlights the wrong lines. + # vim.command("call matchadd('Error', '\%' . line('$') . 'l')") + + try: + self.notify(jid, message, groupChat) + except: + print 'Error zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' + print 'could not notify:', message, 'from:', jid + #}}} + #{{{ notify + def notify(self, jid, msg, groupChat): + # Important to keep this echo statement. As a side effect, it + # refreshes the buffer so the new message shows up. Need to find + # a better solution though. + vim.command("echo 'Message Received from: " + jid.replace("'", "''") + + "'") + + if groupChat: + msgLowered = msg.lower() + myNames = map(lambda x: x.split('@')[0], self.accounts.keys()) + myNames.extend(self.groupChatNames) + myNames = map(lambda x: x.lower(), myNames) + foundMyName = False + for name in myNames: + if name in msgLowered: + foundMyName = True + print (jid + ' said your name in #' + + groupChat.split('%')[0].split('@')[0]) + break + if not foundMyName: + return + + vim.command("set tabline=%#Error#New-message-from-" + jid); + + if pynotify_enabled and 'DBUS_SESSION_BUS_ADDRESS' in os.environ: + pynotify.init('vimchat') + n = pynotify.Notification(jid + ' says: ', msg, 'dialog-warning') + n.set_timeout(10000) + n.show() + + if self.gtk_enabled: + self.statusIcon.blink(True) + #}}} + #{{{ clearNotify + def clearNotify(self): + vim.command('set tabline&') + if self.gtk_enabled: + self.statusIcon.blink(False) + #}}} + + #OTR + #{{{ otrVerifyBuddy + def otrVerifyBuddy(self): + if not pyotr_enabled: + print "OTR Not enabled!" + return 0 + try: + jid = vim.eval('b:buddyId') + account = vim.eval('b:account') + except: + print "Invalid chat buffer!" + return + + response = str(vim.eval('input("Verify ' + jid + \ + ' (1:manual, 2:Question/Answer): ")')) + if response == "1": + response2 = str(vim.eval("input('Verify buddy? (y/n): ')")).lower() + if response2 == "y": + self.accounts[account].otrManualVerifyBuddy(jid) + else: + print "Verify Aborted." + elif response == "2": + question = vim.eval('input("Enter Your Question: ")') + secret = vim.eval('inputsecret("Enter your secret answer: ")') + self.accounts[account].otrSMPVerifyBuddy(jid,question,secret) + else: + print "Invalid Response." + #}}} + #{{{ otrGenerateKey + def otrGenerateKey(self): + if not pyotr_enabled: + print "Otr not enabled!" + return 0 + + accounts = self.showAccountList() + + try: + response = int(vim.eval("input('Account: ')")) + + if response < len(accounts): + print "Generating Key for " + \ + accounts[response]._jids + "(please bear with us)..." + accounts[response].otrGeneratePrivateKey() + print "Generated OTR Key!" + else: + print "Not Generating Key Now." + except: + print "Error generating key!" + #}}} + #{{{ otrSMPRequestNotify + def otrSMPRequestNotify(self, account, jid, question): + if not pyotr_enabled: + return 0 + + buf = VimChat.beginChat(account, jid) + if buf: + message = "-- OTR Verification Request received! " + \ + "Press or to answer the question below:\n" + question + VimChat.appendMessage(account, buf,message, "[OTR]") + print "OTR Verification Request from " + jid + #}}} + #{{{ otrSmpRespond + def otrSmpRespond(self): + if not pyotr_enabled: + return 0 + + try: + jid = vim.eval('b:buddyId') + account = vim.eval('b:account') + except: + print "Invalid chat buffer!" + return + + response = str(vim.eval( + "inputsecret('Answer to "+ jid +": ')")).lower() + self.accounts[account].otrSMPRespond(jid, response) + #}}} +#}}} +VimChat = VimChatScope() + +EOF + +"{{{ Vim Commands +if exists('g:vimchat_loaded') + finish +endif +let g:vimchat_loaded = 1 + +com! VimChat py VimChat.init() +com! VimChatBuddyList py VimChat.toggleBuddyList() +com! VimChatViewLog py VimChat.openLogFromChat() +com! VimChatJoinGroupChat py VimChat.openGroupChat() +com! VimChatOtrVerifyBuddy py VimChat.otrVerifyBuddy() +com! VimChatOtrSMPRespond py VimChat.otrSmpRespond() +com! VimChatOtrGenerateKey py VimChat.otrGenerateKey() +com! -nargs=0 VimChatSetStatus py VimChat.setStatus() +com! VimChatShowStatus py VimChat.showStatus() +com! VimChatJoinChatroom py VimChat.joinChatroom() + +set switchbuf=usetab + +"}}} +"{{{ VimChatCheckVars +fu! VimChatCheckVars() + if !exists('g:vimchat_buddylistwidth') + let g:vimchat_buddylistwidth=30 + endif + if !exists('g:vimchat_libnotify') + let g:vimchat_libnotify=1 + endif + if !exists('g:vimchat_logpath') + let g:vimchat_logpath="~/.vimchat/logs" + endif + if !exists('g:vimchat_logchats') + let g:vimchat_logchats=1 + endif + if !exists('g:vimchat_otr') + let g:vimchat_otr=0 + endif + if !exists('g:vimchat_logotr') + let g:vimchat_logotr=1 + endif + if !exists('g:vimchat_statusicon') + let g:vimchat_statusicon=1 + endif + + return 1 +endfu +"}}} +"{{{ VimChatFoldText +function! VimChatFoldText() + let line=substitute(getline(v:foldstart),'^[ \t#]*\([^=]*\).*', '\1', '') + let line=strpart(' ', 0, (v:foldlevel - 1)).substitute(line,'\s*{\+\s*', '', '') + return line +endfunction +"}}} + +" vim:et:fdm=marker:sts=4:sw=4:ts=4 diff --git a/syntax/vimchat.vim b/syntax/vimchat.vim new file mode 100644 index 0000000..a33c452 --- /dev/null +++ b/syntax/vimchat.vim @@ -0,0 +1,8 @@ +syn match vimChatMsg /^\[\d\d:\d\d].\{-}:/ contains=vimChatTime,vimChatMe +syn match vimChatTime /\[\d\d:\d\d\]/ contained nextgroup=vimChatMe +syn match vimChatMe /Me:/ contained + +" Comment, Type, String, Statement +hi link vimChatMsg Comment +hi link vimChatTime String +hi link vimChatMe Type diff --git a/vimrc b/vimrc index c9b0f39..f9c2225 100644 --- a/vimrc +++ b/vimrc @@ -2,9 +2,14 @@ set enc=utf-8 set fenc=utf-8 + call pathogen#runtime_append_all_bundles() "call pathogen#helptags() +if $VIMTEST + source ~/.vimrc-test +endif + syntax enable "num lines @@ -14,6 +19,10 @@ syntax enable " et nopaste le contraire set nopaste +" VI reprend le controle de la souris ! +" pour faire des copier coller a la souris +set mouse=a + " Toujours laisser des lignes visibles (içi 3) au dessus/en dessous du curseur quand on " atteint le début ou la fin de l'écran : set scrolloff=3 @@ -24,6 +33,7 @@ set nostartofline set laststatus=1 + "dict for autocomplete ctrl-x ctrl-k... set dictionary+=/usr/share/dict/french @@ -45,6 +55,12 @@ endif autocmd BufNewFile,BufRead COMMIT_EDITMSG set filetype=gitcommit +if hostname() == "st-si9" + if v:version > 702 + set relativenumber + endif +endif + " Include DokuVimKi Configuration if filereadable($HOME."/.vim/dokuvimkirc") source $HOME/.vim/dokuvimkirc