diff --git a/README b/README deleted file mode 100644 index 184b3cb..0000000 --- a/README +++ /dev/null @@ -1,71 +0,0 @@ -= vimblog.vim - -== description - - For Vi, Vim or GVim users, there is a simple way to manage your blog posts. Under Vim environment, you can create new blog posts, edit, list all categories, list older posts, delete posts, turn Published into Draft posts, and vice-versa. - It is out-of-the-box working for Wordpress, but very easilly, you can make it manage Blogger, MovableType, TextPattern, etc, platforms. Its the beauty of Open Source software. Study the code, change it, and use it. It is very safe to use it because unlike proprietary software, you can check for “phone_home” procedures, etc. - -== requirements: - - * you'll need VIM compiled with Ruby scripting support - - example: for Debian/Ubuntu: sudo apt-get install vim-ruby - * please, copy this file to one of your VIM dir - - example: to your .vim home folder: $HOME/.vim/vimlog.vim - * please, add this code to your .vimrc file: - - if !exists('*Wordpress_vim') - runtime vimblog.vim - endif - - * change your blog login/password info on the get_personal_data - function bellow. - * make sure you have xmlrpc.php file in your / blog dir. If not, - change the @xml variable to find it. - * testing: open vim, ando do - :Blog rp - to get your recent 10 posts. - -== how-to - - * copy the script to your Vim scripts path, $HOME/.vim directory - * edit you .vimrc (if not exists, create it: $HOME/.vimrc) and insert: - -if !exists('*Wordpress_vim') -runtime vimblog.vim -endif - - * open the vimblog.vim script and edit the personal data in def get_personal_data method approx. at line 97. - * @site value, do not insert “http://”. Just insert the blog address, like in my case “blog.tquadrado.com” - * @xml value, insert the path to your blog’s xmlrpc.php file. If, like in my case, it is in / from your blog address, do insert “/xmlrpc.php” - * run Vim and try fetching the last 10 posts by doing: - -:Blog rp - -If you can see them, it’s fine. If not, test this: - - * check if the script is being found, by typing :B + TAB key. Upon code completion, it is ok. Remember, capital B. - * if error persist, check for the correct path for xmlrpc.php in @xml value. - -== license - -== LICENSE: - - Copyright (c) 2007 pedro mg - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to - deal in the Software without restriction, including without limitation the - rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - sell copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/README.md b/README.md new file mode 100644 index 0000000..f77a296 --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +# VIMBLOG.VIM + +## Description + +For Vi, Vim or GVim users, there is a simple way to manage your blog +posts. + +In the Vim environment you can now: + +* create new blog posts +* edit / posts +* list all categories +* list older posts +* Promote turn "draft" posts into "published" (and vice-versa) +* Upload media to your blog from within VIM and get a link to it +* *Mac+Wordpress+Chrome*: After using `:Blog draft` you can preview + your draft with `p`, `\\p` by default. Additionally, if you + access a pre-existing post (`Blog rp`, then `` on a line with the ID + in it), thereafter `\\p` will launch the entry in Chrome. + +In short, if you've been hanging on to Textmate for its blogging bundle, +you now have a comparable featureset in Vim thanks to Vimblog and +[GIFL](http://github.com/sgharms/gifl). + +It is an out-of-the-box solution that works for Wordpress, but which can +very easilly, be customized to manage Blogger, MovableType, TextPattern, +et al. Its the beauty of Open Source software. Study the code, change +it, and use it. It is very safe to use it because unlike proprietary +software, you can check for "phone\_home" procedures, etc. + +## Requirements: + +1. You'll need VIM compiled with Ruby scripting support. Check for + this by executing `vim --version|grep ruby`. My result ([MacVim + +Janus](https://github.com/carlhuda/janus)) shows: `+reltime +rightleft +ruby +scrollbind +signs +smartindent -sniff +startuptime`. This means that I have ruby scripting support compiled. Debian/Ubuntu can install Ruby support with: `sudo apt-get install vim-ruby` +1. To install you several options: + 1. Copy this file to one of your VIM directories + 1. *Pure Vim Example*: copy the script file to your .vim home folder: $HOME/.vim/vimlog.vim + 1. *Pathogen Example*: If you're using [Tim Pope's + Pathogen](http://www.vim.org/scripts/script.php?script_id=2332), +go to your Pathogen root directory and then `git clone` this repository + 1. *Janus Example*: If you're using Janus then you're just a + variation on the Pathogen setup. Create a `~/.janus` directory +and then add this repository as a submodule with `git submodule add +$GIT_REPO_PATH vimblog`. Git will check out the plugin for you as a +[git submodule](http://book.git-scm.com/5_submodules.html) +1. Your VIM runtime must be made aware of this plugin by means of the + following command. Make sure it is in your `~/.vimrc` or, for +MacVim + Janus users, make sure it is in `~/.vimrc.after` + + if !exists('\*Wordpress\_vim') + runtime vimblog.vim + endif + +1. Update your configuration credentials as described in the next section +1. After completing configuration, you can verify your installation by opening vim, and executing `:Blog rp` to get your + recent 10 posts. If you see them, then congratulations, you're ready to go. + +## Configuration + +**YOU MUST** define the following global in your `.vimrc`. + + let g:vimblogConfig = {'login': '*username*', 'passwd': '*pw*', 'site': '*yoursite*', 'xml_rpc_path': '/xmlrpc.php', 'port': '80', 'image_style': '*classes you want to add to images*', additional_ft': *additional filetypes that a vimblog should syntax highlight with e.g. (markdown|textile|html) - if unset, vimblog buffers will only have 'vimblog' highlighting } + +I put mine like so: + + let g:vimblogConfig = { ... my configuration dictionary ...} + if !exists('\*Wordpress\_vim') + runtime vimblog.vim + endif + +`image_style` : This will provide CSS classes that are applied to the +`` tags that result from using the media upload function. +Typically you would add `centered` or `featured-image`. + +Use of this configuration dictionary allows the configuration and the +code to be separated. + +## Troubleshooting + +### "That Didn't Work" +1. Check if the script is being found, by typing :B + TAB key. Upon code completion, it is ok. Remember, capital B. +1. If the error persist, check for the correct path for xmlrpc.php in @xml value. +1. Open an issue on github + +## LICENSE: + + Copyright (c) 2007 pedro mg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/doc/vimblog.txt b/doc/vimblog.txt new file mode 100644 index 0000000..66acb8e --- /dev/null +++ b/doc/vimblog.txt @@ -0,0 +1,75 @@ +*vimblog.vim* : Plugin for blogging from within Vim + +#=============================================================================== + *vimblog-author* +Original Author: Pedro MG +Major Upgrate: Steven G. Harms +#=============================================================================== + +CONTENTS *vimblog-contents* + +|vimblog-about| Introduction +|vimblog-configuration| Configuration +|vimblog-usage| Usage + +ABOUT VIMBLOG *vimblog-about* + +For Vi, Vim or GVim users, there is a simple way to manage your blog +posts. + +In the Vim environment you can now: + + * Create new blog posts + * Edit / posts + * List all categories + * List older posts + * Promote turn "draft" posts into "published" (and vice-versa) + * Upload media to your blog from within VIM and get a link to it + * Mac+Wordpress+Chrome: After using :Blog draft you can preview + your draft with p, \p by default. Additionally, if you + access a pre-existing post (Blog rp, then on a line with the ID + in it), thereafter \p will launch the entry in Chrome. + +In short, if you've been hanging on to Textmate for its blogging bundle, +you now have a comparable featureset in Vim thanks to Vimblog and +|GIFL|. + +It is an out-of-the-box solution that works for Wordpress, but which can +very easilly, be customized to manage Blogger, MovableType, TextPattern, +et al. Its the beauty of Open Source software. Study the code, change +it, and use it. It is very safe to use it because unlike proprietary +software, you can check for "phone\_home" procedures, etc. + +VIMBLOG CONFIGURATION *vimblog-configuration* + *g:vimblogConfig* + +You must define the configuration in your ~/.vimrc by defining a +dictionary (aka a Hash) called g:vimblogConfig. + + +g:vimblogConfig = { + 'login': '*username*', + 'passwd': '*pw*', + 'site': '*yoursite*', + 'xml_rpc_path': '/xmlrpc.php', + 'port': '80', + 'image_style': '*classes you want to add to images*' +} + + +USING VIMBLOG *vimblog-usage* + +Vimblog functions are invoked from the : prompt and the keyword +"Blog". Thus :Blog np will allow you to create a new post, :Blog rp +will fetch recent posts. :Blog help will also display this help menu. + + :blog rp [x] => show recent [x] posts" + :blog gp id => get post with identification id" + :blog np => create a new post" + :blog um file => upload media asset [path to asset]" + :blog publish => publish an edited/new post" + :blog draft => save edited/new post as draft" + :blog gc => get the list of categories" + :blog del id => delete post with identification id" + :blog help => this message" + diff --git a/ftdetect/vimblog.vim b/ftdetect/vimblog.vim new file mode 100644 index 0000000..caff9bd --- /dev/null +++ b/ftdetect/vimblog.vim @@ -0,0 +1 @@ +au BufNewFile,BufRead *.blog set filetype=vimblog diff --git a/plugin/vimblog.vim b/plugin/vimblog.vim new file mode 100644 index 0000000..7e3be93 --- /dev/null +++ b/plugin/vimblog.vim @@ -0,0 +1,524 @@ +" vim: set foldmethod=marker: " +" For use and setup documentation, consult the Readme.md file + +" Auxiliary Ruby commands{{{ 2 + + +"{{{3 +function! s:BlogHelp() + echo "Usage is :Blog option [arg]" + echo " switches:" + echo " - rp [x] => show recent [x] posts" + echo " - gp id => get post with identification id" + echo " - np => create a new post" + echo " - um file => upload media asset [path to asset]" + echo " - publish => publish an edited/new post" + echo " - draft => save edited/new post as draft" + echo " - gc => get the list of categories" + echo " - del id => delete post with identification id" + echo " - help => this message" +endfunction +"}}}3 + +function! s:CloseQuickfixAndOpenaPost(id) " {{{3 + cclose + new +ruby <f:2ly$g`." + if @@ == 'none' + echom("No preview URL found") + else + if (a:0 > 0 ) + let l:url = @@ . '&preview=true' + let @@ = l:url + echo('Previewing: ' . l:url) + else + let l:url = @@ + echo('Viewing: ' . l:url) + endif + exec(system("open -a \"Google Chrome\" \"". l:url . "\"")) + endif + + let @@ = l:storage +endfunction +" }}}3 + +function! FetchPostIDBasedOnCurrentLine() " {{{ 3 + let l:temp = @@ + execute "normal! yy" + let l:line = @@ + let @@ = l:temp +ruby < +" Version: 1.2 +" Last Change: 2012 Apr 08 + +" Inhibit loading of the script per usr_41 of Vim manual +if exists("g:loaded_vimblog") + finish +endif +let g:loaded_vimblog = 1 + +:command! -nargs=* -complete=file Blog call Wordpress_vim() + +function! Wordpress_vim(start, ...) " {{{1 + if !has('ruby') + echoerr("Vimblog is not operational since it was not compiled with a Ruby interpreter (+ruby)") + finish + endif + if !exists("g:vimblogConfig") + echoerr("Vimblog is not operational since its g:vimblogConfig does not exist.") + finish + endif + +" }}}1 + + try +" {{{1 +ruby < e + xmlrpc_flt_xcptn(e) + rescue => ex + VIM::command("echo \"Unhandled Error: #{ex.to_s} and #{ex.backtrace.join('*')}\"") + end + end + + def blog_debug(args) + blog_api('debug') + end + + def blog_help(args) + blog_api('help') + end + + def method_missing(sym, *args) + VIM.command("echo \"Vimblog fatal error: unable to resolve #{sym.to_s} with #{args}\"") + end + + ####### + # class variables for personal data. Please define in your .vimrc in g:vimblogConfig + def get_personal_data + config = VIM::evaluate("g:vimblogConfig") + VIM::command("echo \"Your g:vimblogConfig configuration was not set. Check out the vimblog README.md\"") unless config + @login = config["login"] + @passwd = config["passwd"] + @site = config["site"] + @xml = config["xml_rpc_path"] + @port = config["port"] + @blog_id = 0 + @user = 1 + end + + def calculate_date(line) + line.gsub!(/Date *:/, '').strip! + parsed_line = DateTime.strptime(line,"%m/%d/%Y %H:%M:%S") + raise "Parsed line was nil" if parsed_line.iso8601.empty? + parsed_line + end + + def get_post_content #{{{2 + post_content = {} + new_post = VIM::Buffer.current[1][0..4].upcase == "Title".upcase + post_content['new_post'] = new_post + case new_post + when true + post_content['title'] = (VIM::Buffer.current[1]).gsub(/Title *:/, '').strip + post_content['dateCreated'] = calculate_date(VIM::Buffer.current[2]) + post_content['mt_allow_comments'] = (VIM::Buffer.current[3]).gsub(/Comments *:/, '') + post_content['mt_allow_pings'] = (VIM::Buffer.current[4]).gsub(/Pings *:/, '') + post_content['categories'] = (VIM::Buffer.current[5]).split(':').last.sub(/^\s+/,'').split(',') + body = [] # from line 7 to the end, grab the post body content + 7.upto(VIM::Buffer.current.count) { |line| body << VIM::Buffer.current[line] } + post_content['description'] = body.join("\r") + else + post_content['post_id'] = ((VIM::Buffer.current[1]).gsub(/Post.*\[/, '')).strip.chop + post_content['title'] = (VIM::Buffer.current[2]).gsub(/Title *:/, '') + post_content['dateCreated'] = calculate_date(VIM::Buffer.current[3]) + post_content['mt_allow_comments'] = (VIM::Buffer.current[7]).gsub(/Comments *:/, '') + post_content['mt_allow_pings'] = (VIM::Buffer.current[8]).gsub(/Pings *:/, '') + post_content['categories'] = (VIM::Buffer.current[9]).split(':').last.sub(/^\s+/,'').split(',') + body = [] # from line 12 to the end, grab the post body content + 12.upto(VIM::Buffer.current.count) { |line| body << VIM::Buffer.current[line] } + post_content['description'] = body.join("\r") + end + + post_content['mt_excerpt'] = '' + post_content['mt_text_more'] = '' + post_content['mt_tb_ping_urls'] = [] + return post_content + end + + ####### + # publish the post. Verifies if it is new post, or an editied existing one. + # + def blog_publish(*args) #{{{2 + p = get_post_content + resp = blog_api("publish", p, true, p['new_post']) + if (p['new_post'] and resp['post_id']) + then + VIM::command("enew!") + VIM::command("Blog gp #{resp['post_id']}") + end + end + + #######"{{{ + # upload a media asset. Returns the URL to the file + # + def blog_um(args) + require 'xmlrpc/base64' + require 'xmlrpc/client.rb' + + VIM::command("let l:storage = @@") + + data = {} + + full_path = File.expand_path(args[0]) + raise "Could not gather a full file path" if full_path.empty? + + upload_name = full_path.split('/').last + + data['name'] = upload_name + begin + data['bits'] = XMLRPC::Base64.new(IO.read(full_path)) + rescue => ex + VIM::command("echom \"Encoding failed because #{ex.to_s}\"") + end + + result = blog_api("um", data) + config = VIM::evaluate("g:vimblogConfig") + gas = config['image_style'] + VIM::command("echo \"Your g:vimblogConfig['image_style'] configuration was not set. Check out the vimblog README.md\"") unless gas + gas = (gas.nil? ? '' : 'class="' + gas + '"') + url = "\"#\"" + + v = VIM::Buffer.current + ln = v.line_number + v.append(ln, url) + VIM::command("normal! j==f#") + end + + ####### + # save post as draft. Verifies if it is new post, or an editied existing one. + # + def blog_draft(*args) #{{{2 + p = get_post_content + resp = blog_api("draft", p, false, p['new_post']) + if (p['new_post'] and resp['post_id']) + then + VIM::command("enew!") + VIM::command("Blog gp #{resp['post_id']}") + end + VIM::command("nnoremap p WordpressViewWithChromeOnMac('preview-mode')") + end + + ####### + # new post. Creates a template for a new post. + # + def blog_np(*args) #{{{2 + @post_date = same_dt_fmt(Time.now) + @post_author = @user + v = VIM::Buffer.current + v.append(v.count-1, "Title : ") + v.append(v.count-1, "Date : #{@post_date}") + v.append(v.count-1, "Comments : 1") + v.append(v.count-1, "Pings : 1") + v.append(v.count-1, "Categs : ") + v.append(v.count-1, "") + VIM::command(%q`setlocal ft=#{get_filetype}`) + end + + def get_filetype + addtl = VIM::evaluate("g:vimblogConfig['additional_ft']") + 'vimblog' + (addtl.length > 0 ? '.' + addtl : '') + end + + ####### + # list of categories. It is opened in a new quickfix window. + # The window can be dismissed by 'q', but if you hit on a category's line, + # that name will be yanked to the default buffer and quoted so that you can put it + # in a post. + # + def blog_cl(*args) #{{{2 + resp = blog_api("cl") + # create a new window with syntax highlight. + # this allows you to rapidly close the window (q) and continue blogging. + configure_quicklist do |v| + ["CATEGORIES LIST:", " ", resp].flatten.each do |str| + v.append(v.count, str) + end + VIM::command(%q[nnoremap :execute "normal! 0y$" \| :cclose]) + end + end + + ####### # {{{3 + # Utility function used to create a quickfix window which can be closed + # with a 'q' (similar to what the Ack plugin does). This can be overridden + # by passing in a string ('action') which defines the RHS of a Vimscript + # map statement e.g. configure_quicklist(%q{:echo 'moon base alpha!'}) + # + # If a block is passed with additional VimRuby goodness, that will be executed + # in the context of the new buffer. It yields back the buffer. + # + def configure_quicklist(qaction=':cclose') #{{{2 + VIM::command(":copen 10") + VIM::command("setlocal modifiable") + VIM::command("setlocal wrap") + VIM::command("nnoremap q #{qaction}") + VIM::command("setl ft=vimblog.qf") + v = VIM::Buffer.current + yield v + end + + ####### + # recent [num] posts. Gets some info for the most recent [num] or 10 posts + # + def blog_rp(*args) #{{{2 + VIM::evaluate("a:0").to_i > 0 ? ((num = VIM::evaluate("a:1")).to_i ? num.to_i : num = 10) : num = 10 + resp = blog_api("rp", num) + # create a new window with syntax highlight. + # this allows you to rapidly close the window (:q!) and get that post id. + configure_quicklist do |buf| + enter_action = ':call CloseQuickfixAndOpenaPost(FetchPostIDBasedOnCurrentLine())' + VIM::command("nnoremap #{enter_action}") + + buf.append(0, "Move your cursor to the line with the postID and hit to edit it.") + buf.append(buf.count, "") + buf.append(buf.count, "#{num} MOST RECENT POSTS:") + buf.append(buf.count, "") + + resp.each { |r| + buf.append(buf.count, "Post : [#{r['post_id']}] Date: #{r['post_date']}") + buf.append(buf.count, "Title: \"#{r['post_title']}\"") + buf.append(buf.count, "") + } + + end + end + + def blog_xmlrpc_debug(*args) #{{{2 + VIM::command("echo \"Creating a Debuggable Post\"") + VIM::command("echo \"Ruby version is #{RUBY_VERSION}\"") + post_content = {} + + post_content['title'] = 'Debugging VimBlog Post' + post_content['dateCreated'] = calculate_date("Date : #{same_dt_fmt(Time.now)}") + post_content['mt_allow_comments'] = 1 + post_content['mt_allow_pings'] = 1 + post_content['categories'] = 'blogroll' + body = %w(this is a debugging blog post by vimblog xmlrpc debug) + post_content['description'] = body.join("\r") + + VIM::command("echo \"Let's verify what's in post content\"") + post_content.each_pair do |k,v| + if k == 'description' + VIM::command("echo \"Skipping #{k} because of whack-r\"") + next + end + VIM::command("echo \"Saw key:[#{k}] and value: [#{v}]\"") + end + VIM::command("echo \"About to send things off to a #{@blog.class}\"") + resp = @blog.call("metaWeblog.newPost", '', @login, @passwd, post_content, true) + + end #}}}2 + + ####### + # get post [id]. Fetches blog post with id [id], or the last one. + # + def blog_gp(*args) #{{{2 + VIM::evaluate("a:0").to_i > 0 ? ((id = VIM::evaluate("a:1")) ? id : id = nil) : id = nil + resp = blog_api("gp", id) + v = VIM::Buffer.current + v.append(v.count-1, "Post : [#{resp['post_id']}]") + v.append(v.count-1, "Title : #{resp['post_title']}") + v.append(v.count-1, "Date : #{resp['post_date']}") + v.append(v.count-1, "Link : #{resp['post_link']}") + v.append(v.count-1, "Permalink: #{resp['post_permaLink']}") + v.append(v.count-1, "Author : #{resp['post_author']}") + v.append(v.count-1, "Comments : #{resp['post_allow_comments']}") + v.append(v.count-1, "Pings : #{resp['post_allow_pings']}") + v.append(v.count-1, "Categs : #{resp['post_categories']}") + v.append(v.count-1, " ") + v.append(v.count-1, " ") + resp['post_body'].each_line { |l| v.append(v.count-1, l.strip)} + VIM::command("nnoremap p :call WordpressViewWithChromeOnMac()") + VIM::command(%Q`setlocal ft=#{get_filetype}`) + end + + ####### + # delete post with id [id]. Asks for confirmation first + # + def blog_del(*args) #{{{2 + VIM::evaluate("a:0").to_i > 0 ? ((id = VIM::evaluate("a:1")) ? id : id = nil) : id = nil + resp = blog_api("del", id) + resp ? VIM.command("echo \"Blog post ##{id} successfully deleted\"") : VIM.command("echo \"Deletion problem for post id ##{id}\"") + end + + ####### + # api calls. Allways returns an hash so that if api is changed, only this + # function needs to be changed. One can use between Blogger, metaWeblog or + # MovableType very easily. + # + def blog_api(fn_api, *args) #{{{2 + begin + case fn_api + + when "debug" + blog_xmlrpc_debug + when "gp" + resp = @blog.call("metaWeblog.getPost", args[0], @login, @passwd) + @post_id = resp['postid'] + body = resp['description'] + + ( resp['mt_text_more'].empty? ? + '' : '' + resp['mt_text_more'] ) + return { 'post_id' => resp['postid'], + 'post_title' => resp['title'], + 'post_date' => same_dt_fmt(resp['dateCreated'].to_time), + 'post_link' => resp['link'], + 'post_permalink' => resp['permalink'], + 'post_author' => resp['userid'], + 'post_allow_comments' => resp['mt_allow_comments'], + 'post_comment_status' => resp['comment_status'], + 'post_allow_pings' => resp['mt_allow_pings'], + 'post_ping_status' => resp['mt_ping_status'], + 'post_categories' => resp['categories'].join(', '), + 'post_body' => body + } + + when "rp" + resp = @blog.call("mt.getRecentPostTitles", @blog_id, @login, @passwd, args[0]) + arr_hash = [] + resp.each { |r| arr_hash << { 'post_id' => r['postid'], + 'post_title' => r['title'], + 'post_date' => r['dateCreated'].to_time } + } + return arr_hash + + when "um" + args = ["metaWeblog.newMediaObject", @blog_id, @login, @passwd, args.pop] + result = @blog.call *args + return result + + when "help" + VIM::command("throw \"help\"") + + when "cl" + resp = @blog.call("mt.getCategoryList", @blog_id, @login, @passwd) + arr_hash = [] + resp.each { |r| arr_hash << r['categoryName'] } + return arr_hash + + when "draft" + args[2] ? call = "metaWeblog.newPost" : call = "metaWeblog.editPost" + args[2] ? which_id = @blog_id : which_id = args[0]['post_id'] + resp = @blog.call(call, which_id, @login, @passwd, args[0], args[1]) # hash content, boolean state ("publish"|"draft") + return { 'post_id' => resp } + + when "publish" + call = args[2] ? "metaWeblog.newPost" : "metaWeblog.editPost" + which_id = args[2] ? @blog_id : args[0]['post_id'] + resp = @blog.call(call, which_id, @login, @passwd, args[0], args[1]) # hash content, boolean state ("publish"|"draft") + return { 'post_id' => resp } + + when "del" + resp = @blog.call("metaWeblog.deletePost", "1234567890ABCDE", args[0], @login, @passwd) + return resp + + end + rescue XMLRPC::FaultException => e + xmlrpc_flt_xcptn(e) + end + end + + ####### + # same datetime format for dates + # + def same_dt_fmt(dt) #{{{2 + dt.strftime('%m/%d/%Y %H:%M:%S %Z') + end + + ####### + # exception handling error display message for communication problems + # + def xmlrpc_flt_xcptn(excpt) #{{{2 + msg = "Error code: #{excpt.faultCode} :: Error msg.:#{excpt.faultString}" + VIM::command("echo \"#{msg}\"") + end + + end # class Wp_vim + Wp_vim.new(VIM::evaluate("a:start"), (VIM::evaluate("a:0") > 0 ? VIM::evaluate("a:000") : '' )) +EOF +" }}} 1 +" {{{ 1 + catch /del/ + :echo "Usage for deleting a post:" + :echo " :Blog del id" + catch /draft/ + :echo "Usage for saving a draft of a post:" + :echo " :Blog draft" + catch /publish/ + :echo "Usage for Publishing a post:" + :echo " :Blog publish" + catch /gc/ + :echo "Usage for getting the list of categories: :" + :echo " :Blog cl" + catch /gp/ + :echo "Usage for Get Post [id]:" + :echo " :Blog gp id" + catch /np/ + :echo "Usage for New Post:" + :echo " :Blog np" + catch /rp/ + :echo "Usage for Recent [x] Posts (defaults to last 10): " + :echo " :Blog rp [x]" + catch /um/ + :echo "Usage for Upload Media" + :echo " :Blog um [filename]" + catch /help/ + call BlogHelp() + catch /(.*)/ + :echo v:exception + call BlogHelp() + endtry +endfunction +" }}}1 diff --git a/syntax/vimblog.vim b/syntax/vimblog.vim new file mode 100644 index 0000000..4273799 --- /dev/null +++ b/syntax/vimblog.vim @@ -0,0 +1,25 @@ +if exists("b:current_syntax") + finish +endif + +syntax keyword wpType Post Title Date Author Link + \ Permalink Allow Comments Allow Pings Categs + +syntax match wpFields /: .*/hs=s+2 contains=wpPostId, wpTitle + +syntax region wpTitle start=/"/ end=/$/ contained +syntax region wpPostId start=/\[/ end=/\]/ contained + +if &background ==? "dark" + highlight wpType ctermfg=Green guifg=LightGreen + \ gui=bold + highlight wpPostId ctermfg=Red guifg=Red + highlight wpFields ctermfg=Blue guifg=Blue + \ guibg=LightCyan +else + highlight wpType ctermfg=Green guifg=DarkMagenta + \ gui=bold + highlight wpPostId ctermfg=Red guifg=Red + highlight wpFields ctermfg=Blue guifg=Blue + \ guifg=DarkCyan +endif diff --git a/vimblog.vim b/vimblog.vim deleted file mode 100644 index 3fdb932..0000000 --- a/vimblog.vim +++ /dev/null @@ -1,385 +0,0 @@ -" Requirements: -" - you'll need VIM compiled with Ruby scripting support -" - example: for Debian/Ubuntu: sudo apt-get install vim-ruby -" - please, copy this file to one of your VIM dir -" - example: to your .vim home folder: $HOME/.vim/vimlog.vim -" - please, add this code to your .vimrc file: -" -" if !exists('*Wordpress_vim') -" runtime vimblog.vim -" endif -" -" - change your blog login/password info on the get_personal_data -" function bellow. -" - make sure you have xmlrpc.php file in your / blog dir. If not, -" change the @xml variable to find it. -" - testing: open vim, ando do -" :Blog rp -" to get your recent 10 posts. -" - Questions ? e-mail please ;) -" - Using it ? please, leave a word ;) - - -if !has('ruby') - s:ErrMsg( "Error: Required vim compiled with +ruby" ) - finish -endif - -" Vim syntax functions -" Language: wordpress_vim -" Maintainer: pedro mg -" Version: 1.1 -" Last Change: 2008 Apr 04 -" Remark: Simple functions for vim blogging bundle in ruby. -" Remark: Please, if you fine tune this code, send it back -" Remark: for version upgrade ;) - -function! Blog_syn_hl() " {{{2 - :syntax clear - :syntax keyword wpType Post Title Date - :syntax region wpTitle start=/"/ end=/$/ - :syntax region wpPostId start=/\[/ end=/\]/ - :highlight wpType ctermfg=Green guifg=LightGreen - :highlight wpTitle cterm=bold ctermfg=Blue guifg=Blue guibg=LightCyan gui=bold - :highlight wpPostId ctermfg=Red guifg=Red -endfunction -" }}}2 - -function! Post_syn_hl() " {{{3 - :syntax clear - :runtime! syntax/html.vim " content syntax is html hl, except for headers - :syntax keyword wpType Post Title Date Author Link Permalink Allow Comments Allow Pings Categs - :syntax region wpPostId start=/\[/ end=/\]/ contained - :syntax match wpFields /: .*/hs=s+2 contains=wpPostId - :highlight wpType ctermfg=Green guifg=LightGreen gui=bold - :highlight wpPostId ctermfg=Red guifg=Red - :highlight wpFields ctermfg=Blue guifg=Blue guibg=LightCyan -endfunction -" }}}3 - -" Vim blogging function -" Language: vim script -" Interface: ruby -" Maintainer: pedro mg -" Version: 1.2 -" Last Change: 2008 Jun 14 -" Remark: script function for vim blogging bundle in ruby. -" Remark: Please, if you fine tune this code, send it back -" Remark: for version upgrade ;) -" Remark: V1.2 - commands added: -" Remark: - Blog link ADDRESS,TITLE,STRING - -:command -nargs=* Blog call Wordpress_vim() - -function! Wordpress_vim(start, ...) " {{{1 - call Blog_syn_hl() " comment if you don't wish syntax highlight activation - try -ruby < e - xmlrpc_flt_xcptn(e) - end - end - - ####### - # class variables for personnal data. Please *change* them accordingly. - # CHANGE HERE: - def get_personal_data - @login = "" # insert your login here - @passwd = "" # insert your password here - @site = "" # insert your blog url here, but do not use http:// - @xml = "/xmlrpc.php" # change if necessary - @port = 80 # change if necessary - @blog_id = 0 - @user = 1 - end - - def get_post_content - post_content = {} - new_post = VIM::Buffer.current[1][0..4].upcase == "Title".upcase - post_content['new_post'] = new_post - case new_post - when true - post_content['title'] = (VIM::Buffer.current[1]).gsub(/Title *:/, '').strip - post_content['dateCreated'] = Time.parse(((VIM::Buffer.current[2]).gsub(/Date *:/, '')).strip) - post_content['mt_allow_comments'] = (VIM::Buffer.current[3]).gsub(/Comments *:/, '') - post_content['mt_allow_pings'] = (VIM::Buffer.current[4]).gsub(/Pings *:/, '') - post_content['categories'] = (VIM::Buffer.current[5]).gsub(/Categs *:/, '').split - body = [] # from line 8 to the end, grab the post body content - 8.upto(VIM::Buffer.current.count) { |line| body << VIM::Buffer.current[line] } - post_content['description'] = body.join("\r") - else - post_content['post_id'] = ((VIM::Buffer.current[1]).gsub(/Post.*\[/, '')).strip.chop - post_content['title'] = (VIM::Buffer.current[2]).gsub(/Title *:/, '') - post_content['dateCreated'] = Time.parse(((VIM::Buffer.current[3]).gsub(/Date *:/, '')).strip) - post_content['mt_allow_comments'] = (VIM::Buffer.current[7]).gsub(/Comments *:/, '') - post_content['mt_allow_pings'] = (VIM::Buffer.current[8]).gsub(/Pings *:/, '') - post_content['categories'] = (VIM::Buffer.current[9]).gsub(/Categs *:/, '').split - body = [] # from line 11 to the end, grab the post body content - 11.upto(VIM::Buffer.current.count) { |line| body << VIM::Buffer.current[line] } - post_content['description'] = body.join("\r") - end - post_content['mt_exceprt'] = '' - post_content['mt_text_more'] = '' - post_content['mt_tb_ping_urls'] = [] - return post_content - end - - ####### - # publish the post. Verifies if it is new post, or an editied existing one. - # - def blog_publish - p = get_post_content - resp = blog_api("publish", p, true, p['new_post']) - if (p['new_post'] and resp['post_id']) - then - VIM::command("enew!") - VIM::command("Blog gp #{resp['post_id']}") - end - end - - ####### - # save post as draft. Verifies if it is new post, or an editied existing one. - # - def blog_draft - p = get_post_content - resp = blog_api("draft", p, false, p['new_post']) - if (p['new_post'] and resp['post_id']) - then - VIM::command("enew!") - VIM::command("Blog gp #{resp['post_id']}") - end - end - - ####### - # new post. Creates a template for a new post. - # - def blog_np - @post_date = same_dt_fmt(Time.now) - @post_author = @user - VIM::command("call Post_syn_hl()") - v = VIM::Buffer.current - v.append(v.count-1, "Title : ") - v.append(v.count-1, "Date : #{@post_date}") - v.append(v.count-1, "Comments : 1") - v.append(v.count-1, "Pings : 1") - v.append(v.count-1, "Categs : ") - v.append(v.count-1, " ") - v.append(v.count-1, " ") - v.append(v.count-1, " ") - end - - ####### - # list of categories. Is opened in a new temporary window, because may me for assistance on - # creating/editing a post. - # - def blog_cl - resp = blog_api("cl") - # create a new window with syntax highlight. - # this allows you to rapidelly close the window (:q!) and continue blogging. - VIM::command(":new") - VIM::command("call Blog_syn_hl()") - VIM::command(":set wrap") - v = VIM::Buffer.current - v.append(v.count, "CATEGORIES LIST: ") - v.append(v.count, " ") - v.append(v.count, "\"#{resp.join(' ')}\"") - end - - ####### - # recent [num] posts. Gets some info for the most recent [num] or 10 posts - # - def blog_rp - VIM::evaluate("a:0").to_i > 0 ? ((num = VIM::evaluate("a:1")).to_i ? num.to_i : num = 10) : num = 10 - resp = blog_api("rp", num) - # create a new window with syntax highlight. - # this allows you to rapidely close the window (:q!) and get that post id. - VIM::command(":new") - VIM::command("call Blog_syn_hl()") - v = VIM::Buffer.current - v.append(v.count, "MOST RECENT #{num} POSTS: ") - v.append(v.count, " ") - resp.each { |r| - v.append(v.count, "Post : [#{r['post_id']}] Date: #{r['post_date']}") - v.append(v.count, "Title: \"#{r['post_title']}\"") - v.append(v.count, " ") - } - end - - ####### - # get post [id]. Fetches blog post with id [id], or the last one. - # - def blog_gp - VIM::command("call Post_syn_hl()") - VIM::evaluate("a:0").to_i > 0 ? ((id = VIM::evaluate("a:1")) ? id : id = nil) : id = nil - resp = blog_api("gp", id) - v = VIM::Buffer.current - v.append(v.count-1, "Post : [#{resp['post_id']}]") - v.append(v.count-1, "Title : #{resp['post_title']}") - v.append(v.count-1, "Date : #{resp['post_date']}") - v.append(v.count-1, "Link : #{resp['post_link']}") - v.append(v.count-1, "Permalink: #{resp['post_permaLink']}") - v.append(v.count-1, "Author : #{resp['post_author']}") - v.append(v.count-1, "Comments : #{resp['post_allow_comments']}") - v.append(v.count-1, "Pings : #{resp['post_allow_pings']}") - v.append(v.count-1, "Categs : #{resp['post_categories']}") - v.append(v.count-1, " ") - v.append(v.count-1, " ") - resp['post_body'].each_line { |l| v.append(v.count-1, l.strip)} - end - - ####### - # delete post with id [id]. Asks for confirmation first - # - def blog_del - VIM::evaluate("a:0").to_i > 0 ? ((id = VIM::evaluate("a:1")) ? id : id = nil) : id = nil - resp = blog_api("del", id) - resp ? VIM.command("echo \"Blog post ##{id} successfully deleted\"") : VIM.command("echo \"Deletion problem for post id ##{id}\"") - end - - ####### - # insert a link. Is it interesting to implement these options ? - # ** http://address.com - # ** title (hint) - # ** string - # - def blog_link - v = VIM::Buffer.current - link = {:link => '', :string => '', :title => ''} - VIM::evaluate("a:0").to_i > 0 ? ((id = VIM::evaluate("a:1")) ? id : id = nil) : id = nil - v.append(v.count-1, " a:0 --> #{VIM::evaluate("a:0")} ") - v.append(v.count-1, " a:1 --> #{VIM::evaluate("a:1")} ") - v.append(v.count-1, "#{link[:string]}") - end - - ####### - # api calls. Allways returns an hash so that if api is changed, only this - # function needs to be changed. One can use between Blogger, metaWeblog or - # MovableType very easilly. - # - def blog_api(fn_api, *args) - begin - case fn_api - - when "gp" - resp = @blog.call("metaWeblog.getPost", args[0], @login, @passwd) - @post_id = resp['postid'] - return { 'post_id' => resp['postid'], - 'post_title' => resp['title'], - 'post_date' => same_dt_fmt(resp['dateCreated'].to_time), - 'post_link' => resp['link'], - 'post_permalink' => resp['permalink'], - 'post_author' => resp['userid'], - 'post_allow_comments' => resp['mt_allow_comments'], - 'post_comment_status' => resp['comment_status'], - 'post_allow_pings' => resp['mt_allow_pings'], - 'post_ping_status' => resp['mt_ping_status'], - 'post_categories' => resp['categories'].join(' '), - 'post_body' => resp['description'] - } - - when "rp" - resp = @blog.call("mt.getRecentPostTitles", @blog_id, @login, @passwd, args[0]) - arr_hash = [] - resp.each { |r| arr_hash << { 'post_id' => r['postid'], - 'post_title' => r['title'], - 'post_date' => r['dateCreated'].to_time } - } - return arr_hash - - when "cl" - resp = @blog.call("mt.getCategoryList", @blog_id, @login, @passwd) - arr_hash = [] - resp.each { |r| arr_hash << r['categoryName'] } - return arr_hash - - when "draft" - args[2] ? call = "metaWeblog.newPost" : call = "metaWeblog.editPost" - args[2] ? which_id = @blog_id : which_id = args[0]['post_id'] - resp = @blog.call(call, which_id, @login, @passwd, args[0], args[1]) # hash content, boolean state ("publish"|"draft") - return { 'post_id' => resp } - - when "publish" - args[2] ? call = "metaWeblog.newPost" : call = "metaWeblog.editPost" - args[2] ? which_id = @blog_id : which_id = args[0]['post_id'] - resp = @blog.call(call, which_id, @login, @passwd, args[0], args[1]) # hash content, boolean state ("publish"|"draft") - return { 'post_id' => resp } - - when "del" - resp = @blog.call("metaWeblog.deletePost", "1234567890ABCDE", args[0], @login, @passwd) - return resp - - end - rescue XMLRPC::FaultException => e - xmlrpc_flt_xcptn(e) - end - end - - ####### - # same datetime format for dates - # - def same_dt_fmt(dt) - dt.strftime('%m/%d/%Y %H:%M:%S %Z') - end - - ####### - # exception handling error display message for communication problems - # - def xmlrpc_flt_xcptn(excpt) - msg = "Error code: #{excpt.faultCode} :: Error msg.:#{excpt.faultString}" - VIM::command("echo \"#{msg}\"") - end - - end # class Wp_vim - Wp_vim.new -EOF - catch /del/ - :echo "Usage for deleting a post:" - :echo " :Blog del id" - catch /draft/ - :echo "Usage for saving a draft of a post:" - :echo " :Blog draft" - catch /publish/ - :echo "Usage for Publishing a post:" - :echo " :Blog publish" - catch /gc/ - :echo "Usage for getting the list of Categories :" - :echo " :Blog cl" - catch /gp/ - :echo "Usage for Get Post [id]:" - :echo " :Blog gp id" - catch /np/ - :echo "Usage for New Post:" - :echo " :Blog np" - catch /rp/ - :echo "Usage for Recent [x] Posts (defaults to last 10): " - :echo " :Blog rp [x]" - catch // - :echo "Usage is :Blog option [arg]" - :echo " switches:" - :echo " - rp [x] => show recent [x] posts" - :echo " - gp id => get post with identification id" - :echo " - np => create a new post" - :echo " - publish => publish an edited/new post" - :echo " - draft => save edited/new post as draft" - :echo " - gc => get the list of categories" - :echo " - del id => delete post with identification id" - :echo " --- syntax helpers:" - :echo " - link ADDRESS,TITLE,STRING => insert link STRING link" - endtry -endfunction -" }}}1 - -