" ------------------------------------------------------------------------------ " File: plugin/utl.vim - Universal Text Linking - " URL based Hyperlinking for plain text " Author: Stefan Bittner " Maintainer: Stefan Bittner " " Licence: This program is free software; you can redistribute it and/or " modify it under the terms of the GNU General Public License. " See http://www.gnu.org/copyleft/gpl.txt " 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. " " Version: 3.0a ALPHA " " Docs: for online help type: :help utl-plugin " " Files: The Utl plugin consists of the following files: " plugin/{utl.vim,utl_scm.vim,utl_uri.vim,utl_rc.vim} " doc/utl_usr.txt " " History: " 1.0 2001-04-26 " First release for vim5 under the name thlnk.vim " 1.1 2002-05-07 " As plugin for vim6 with heavily revised documentation and homepage " 1.2 2002-06-14 " Two bug fixes, better error messages, largely enhanced documentation " 1.2.1 2002-06-15 " Bug fix. Better 'ff' setting for distribution files " --- Renamed plugin from Thlnk to Utl --- " 2.0 2005-03-22 " Configurable scheme and media type handlers, syntax " highlighting, naked URL support, #tn as default, heuristic " support and other new features. See ../doc/utl_usr.txt#utl-changes " 3.0a ALPHA 2008-07-31 " New : Generic media type handler, Mail protocol, Copy Link/ " Filename support, Foot-References [], Transparent editing of " share files, Tracing, Enhanced scheme handler interface, " Changed : User Interface with command :Utl, variable naming. " Bug fixes. " ------------------------------------------------------------------------------ if exists("loaded_utl") || &cp finish endif let loaded_utl = "3.0a" if v:version < 700 echohl ErrorMsg echo "Error: You need Vim version 7.0 or later for utl.vim version ".g:loaded_utl echohl None finish endif let s:save_cpo = &cpo set cpo&vim let g:utl__file = expand("") "--- Utl User Interface [ " (:Utl not as "command! to not override a possible user command of this name. " Fails with an error in this case.) command -complete=custom,s:completeArgs -range -nargs=* Utl call Utl() "------------------------------------------------------------------------------- " Intended as command line completion function called back by command :Utl. " See vimhelp:command-completion-custom. " Based on the command line provided by user input so far it returns a \n " separated line of items, which Vim then uses for presenting completion " suggestions to the user. " Also works if abbreviations ( see #r=cmd_abbreviations ) appear in cmdLine fu! s:completeArgs(dummy_argLead, cmdLine, dummy_cursorPos) " Split cmdLine to figure out how many arguments have been provided by user " so far. If Using argument keepempty=1 for split will provide empty last " arg in case of a new arg is about to begin or an non empty last argument " in case of an incomplete last argument. So can just remove the last arg. let utlArgs=split(a:cmdLine, '\s\+', 1) call remove(utlArgs, -1) " 1st arg to complete if len(utlArgs)==1 return "openLink\ncopyFileName\ncopyLink\nhelp" endif let utlArgs[1] = s:abbr2longArg(utlArgs[1]) " 2nd arg to complete if len(utlArgs)==2 if utlArgs[1]=='openLink' || utlArgs[1]=='copyFileName' || utlArgs[1]=='copyLink' if len(utlArgs)==2 return "underCursor\nvisual\ncurrentFile\n_your_URL_here" endif elseif utlArgs[1]=='help' if len(utlArgs)==2 return "manual\ncommands" endif endif " config return '' endif " 3rd argument to complete if len(utlArgs)==3 if utlArgs[1]=='openLink' return "edit\nsplit\nvsplit\ntabedit\nview\nread" elseif utlArgs[1]=='copyFileName' return "native\nslash\nbackSlash" endif return '' endif return '' endfun " [id=cmd_reference] "------------------------------------------------------------------------------- " Table of :Utl commands/arguments. The [xxx] are default values and can " be omitted. ( The table is implemented at #r=Utl ) " " arg# 1 2 3 " " :Utl [openLink] [underCursor] [edit] " :Utl visual split " :Utl currentFile vsplit " :Utl tabedit " :Utl view " :Utl read " " :Utl copyLink [underCursor] " :Utl visual " :Utl currentFile " :Utl " " :Utl copyFileName [underCursor] [native] " :Utl currentFile backSlash " :Utl Visual slash " :Utl " " :Utl help [manual] " :Utl commands " [id=cmd_abbreviations] "------------------------------------------------------------------------------- " Supported abbreviations of arguments to :Utl command. " Abbreviation conventions are: " - More than one abbreviation per argument is possible " - All uppercase letter of a camel word as lower letters (copyFileName -> cfn) " - Fewer and fewer uppercase letters as long as still unique " (cfn -> cf. But not c since else clash with copyLink) " - The shortest (camel sub-)word beginning until unique " (view and vsplit -> vi and vs resp.) " " (More keys (=abbreviations) can be added to the dictionaries without further " change as long as the values are valid long arguments.) " let s:d1= { 'o': 'openLink', 'ol': 'openLink', 'cl': 'copyLink', 'cf': 'copyFileName', 'cfn': 'copyFileName', 'h': 'help' } let s:d21={ 'u': 'underCursor', 'uc': 'underCursor', 'v': 'visual', 'c': 'currentFile', 'cf': 'currentFile' } let s:d22={ 'm': 'manual', 'c': 'commands' } let s:d31={ 'e': 'edit', 's': 'split', 'vs': 'vsplit', 't': 'tabedit', 'te': 'tabedit', 'vi': 'view', 'r': 'read' } let s:d32={ 'n': 'native', 'b': 'backSlash', 'bs': 'backSlash', 's': 'slash' } "------------------------------------------------------------------------------- " Convert possible :Utl arg abbreviation for last arg into long arg. The args " before are the :Utl args provided so far in long form. " " Args: Utl command arguments according #r=cmd_reference, where the last " can be abbreviated. " Returns: Last arg converted into long arg " " Collaboration: " " Example: s:abbr2longArg('copyFileName', 'underCursor', 's') " returns 'slash' " fu! s:abbr2longArg(...) if ! exists('a:2') return s:utilLookup(s:d1, a:1) elseif ! exists('a:3') if a:1=='openLink'|| a:1=='copyLink'|| a:1=='copyFileName' return s:utilLookup(s:d21, a:2) elseif a:1=='help' return s:utilLookup(s:d22, a:2) endif else if a:1=='openLink' return s:utilLookup(s:d31, a:3) elseif a:1 == 'copyFileName' return s:utilLookup(s:d32, a:3) endif endif endfu "------------------------------------------------------------------------------- " Lookup 'key' in 'dict'. If defined return its value else return the 'key' " itself fu! s:utilLookup(dict,key) if has_key(a:dict, a:key) return a:dict[a:key] endif return a:key endfu "----------------------------------------------------------id=Utl--------------- " Central Utl.vim function. Normally invoked by :Utl command " args: Same as command :Utl (but quoted), see #r=cmd_reference " " Example: call Utl('openLink','http://www.vim.org','split') " fu! Utl(...) call Utl_trace("- start function Utl()",1,1) if exists('a:1') | let cmd=s:abbr2longArg(a:1) | else | let cmd='openLink' | endif call Utl_trace("- arg1 (cmd) provided or by default = `".cmd."'") if cmd == 'openLink' if exists('a:2') | let operand=s:abbr2longArg(cmd,a:2) | else | let operand='underCursor' | endif call Utl_trace("- arg2 (operand) provided or by default = `".operand."'") if exists('a:3') | let dispMode=s:abbr2longArg(cmd,operand,a:3) | else | let dispMode='edit' | endif call Utl_trace("- arg3 (dispMode) provided or by default = `".dispMode."'") if operand=='underCursor' call s:Utl_goUrl(dispMode) elseif operand=='visual' let url = @* call s:Utl_processUrl(url, dispMode) elseif operand=='currentFile' let url = 'file://'.Utl_utilBack2FwdSlashes( expand("%:p") ) call s:Utl_processUrl(url, dispMode) else " the operand is the URL call s:Utl_processUrl(operand, dispMode) endif elseif cmd=='copyFileName' || cmd=='copyLink' if exists('a:2') | let operand=s:abbr2longArg(cmd,a:2) | else | let operand='underCursor' | endif call Utl_trace("- arg2 (operand) provided or by default = `".operand."'") let suffix='' if cmd == 'copyFileName' if exists('a:3') | let modifier=s:abbr2longArg(cmd,operand,a:3) | else | let modifier='native' | endif call Utl_trace("- arg3 (modifier) provided or by default = `".modifier."'") let suffix='_'.modifier endif if operand=='underCursor' call s:Utl_goUrl(cmd.suffix) elseif operand=='visual' let url = @* call s:Utl_processUrl(url, cmd.suffix) elseif operand=='currentFile' let url = 'file://'.Utl_utilBack2FwdSlashes( expand("%:p") ) call s:Utl_processUrl(url, cmd.suffix) else " the operand is the URL call Utl_trace("- `".operand."' (arg2) is not a keyword. So is directly taken as an URL") call s:Utl_processUrl(operand, cmd.suffix) endif elseif cmd == 'help' if exists('a:2') | let operand=s:abbr2longArg(cmd,a:2) | else | let operand='manual' | endif call Utl_trace("- arg2 (operand) provided or by default = `".operand."'\n") " CR054_extra_nl if operand=='manual' help utl_usr.txt elseif operand=='commands' call Utl('openLink', 'file://'.Utl_utilBack2FwdSlashes(expand(g:utl__file)).'#r=cmd_reference', 'sview') else echohl ErrorMsg | echo "invalid argument: `".operand."'" | echohl None endif else echohl ErrorMsg | echo "invalid argument: `".cmd."'" | echohl None endif call Utl_trace("- end function Utl()",1,-1) endfu "] "--- Set unset Utl options to defaults (id=options) [ if ! exists("utl_opt_verbose") let utl_opt_verbose=0 endif if ! exists("utl_opt_highlight_urls") let utl_opt_highlight_urls='yes' endif "] "--- Suggested mappings for most frequent commands [id=suggested_mappings] [ " " nmap ge :Utl openLink underCursor edit " nmap gu :Utl openLink underCursor edit " nmap gE :Utl openLink underCursor split " nmap gS :Utl openLink underCursor vsplit " nmap gt :Utl openLink underCursor tabedit " nmap gv :Utl openLink underCursor view " nmap gr :Utl openLink underCursor read " " [id=suggested_mappings_visual] " vmap ge "*y:Utl openLink visual edit " vmap gu "*y:Utl openLink visual edit " vmap gE "*y:Utl openLink visual split " vmap gS "*y:Utl openLink visual vsplit " vmap gt "*y:Utl openLink visual tabedit " vmap gv "*y:Utl openLink visual view " vmap gr "*y:Utl openLink visual read " " " nmap cfn :Utl copyFileName underCursor native " nmap cfs :Utl copyFileName underCursor slash " nmap cfb :Utl copyFileName underCursor backSlash " " vmap cfn "*y:Utl copyFileName visual native " vmap cfs "*y:Utl copyFileName visual slash " vmap cfb "*y:Utl copyFileName visual backSlash " " " nmap cl :Utl copyLink underCursor " " vmap cl "*y:Utl copyLink visual " "] let s:utl_esccmdspecial = '%#' " keep equal to utl_scm.vim#__esc " isfname adapted to URI Reference characters let s:isuriref="@,48-57,#,;,/,?,:,@-@,&,=,+,$,,,-,_,.,!,~,*,',(,),%" "----------------------------------------------------------id=thl_gourl--------- " Process URL (or read: URI, if you like---Utl isn't exact there) under " cursor: searches for something like or (depending " on the context), extracts myUrl, an processes that Url (e.g. retrieves the " document and displays it). " " - Arg dispMode -> see " fu! s:Utl_goUrl(dispMode) call Utl_trace("- start processing (dispMode=".a:dispMode.")",1,1) let url = Utl_getUrlUnderCursor() if url == '' let v:errmsg = "No URL under Cursor" echohl ErrorMsg | echo v:errmsg | echohl None else call s:Utl_processUrl(url, a:dispMode) endif call Utl_trace("- end processing.",1,-1) endfu "------------------------------------------------------------------------------- " Tries to extract an URL in current buffer at current cursor position. " " Returns: URL under cursor if any, else '' " fu! Utl_getUrlUnderCursor() call Utl_trace("- start getting URL under cursor",1,1) let line = getline('.') let icurs = col('.') - 1 " `Index-Cursor' call Utl_trace("- first try: checking for URL with embedding like in current line...",1,1) let url = s:Utl_extractUrlByPattern(line, icurs, '') if url=='' call Utl_trace("- ...no",1,-1) call Utl_trace("- retry: checking for embedded URL spanning over range of max 5 lines...",1,1) let lineno = line('.') " (lineno-1/2 can be negative -> getline gives empty string -> ok) let line = getline(lineno-2) . "\n" . getline(lineno-1) . "\n" . \ getline(lineno) . "\n" . \ getline(lineno+1) . "\n" . getline(lineno+2) " `Index of Cursor' " (icurs off by +2 because of 2 \n's, plus -1 because col() starts at 1 = +1) let icurs = strlen(getline(lineno-2)) + strlen(getline(lineno-1)) + col('.') +1 let url = s:Utl_extractUrlByPattern(line, icurs, '') endif if url=='' call Utl_trace("- ...no", 1, -1) call Utl_trace("- retry: checking if [ ] style reference...", 1, 1) if stridx(line, '[') != -1 let isfname_save = &isfname | let &isfname = s:isuriref " ([) let pat = '\(\(\[[A-Z0-9_]\{-}\]\)\(#\f*\)*\)' " &isfname here in \f let url = s:Utl_extractUrlByPattern(line, icurs, pat) let &isfname = isfname_save " (]) " remove trailing punctuation characters if any if url!='' call Utl_trace("- removing trailing punctuation chars from URL if any") let url = substitute(url, '[.,:;!?]$', '', '') endif endif endif if url=='' call Utl_trace("- ...no", 1,-1) call Utl_trace("- retry: checking for unembedded URL under cursor...", 1,1) " Take as URL. But adapt isfname to match all allowed URI Reference characters let isfname_save = &isfname | let &isfname = s:isuriref " ([) let url = expand("") let &isfname = isfname_save " (]) endif if url!='' call Utl_trace("- ...yes, URL found: `".url."'", 1,-1) else call Utl_trace("- ...no", 1,-1) endif call Utl_trace("- end getting URL under cursor.",1,-1) return url endfu "--------------------------------------------------------id=thl_curl------------ " `Utl_extractUrlByPattern' - Extracts embedded URLs from 'linestr': " Extracts URL from given string 'linestr' (if any) at position 'icurs' (first " character in linestr is 0). When there is no URL or icurs does not hit the " URL (i.e. 'URL is not under cursor') returns ''. Note, that there can " be more than one URL in linestr. Linestr may contain newlines (i.e. supports " multiline URLs). " " 'pat' argument: " Embedded URL means, that the URL is surrounded by some tag or characters " to allow for safe parsing, for instance ''. This regexp pattern " has to specify a group \(...\) by which defines the URL. " Example : ''. If an empty pattern '' is given, default " patterns apply (see code below). " " Examples: " :echo s:Utl_extractUrlByPattern('Two Urls in this line', 35, '') " returns `/f/b' " " :echo s:Utl_extractUrlByPattern('Two Urls in this line', 28, '') " returns `' " " :echo s:Utl_extractUrlByPattern('Another embedding here ', 27, '') " returns `foo bar' " " Details: " - The URL embedding (or if embedding at all) depends on the context: HTML " has different embedding than a txt file. " - Non HTML embeddings are of the following form: , or " <...> " - Returns `' if `no link under cursor'. (Note that cannot cause " problems because `<' is not a valid URI character) " - Empty Urls are legal, e.g. " - `Under cursor' is like with vim's gf-command: icurs may also point to " whitespace before the cursor. (Also pointing to the embedding characters " is valid.) " fu! s:Utl_extractUrlByPattern(linestr, icurs, pat) let pat = a:pat call Utl_trace("- start extracting URL by pattern `".pat."'",1,1) if pat == '' call Utl_trace("- pattern is , determine based on file type") if &ft == 'html' let embedType = 'html' else let embedType = 'txt' endif " (pat has to have the Url in first \(...\) because ({) ) if embedType == 'html' call Utl_trace("- file type is 'html'") " Html-Pattern: " - can have other attributes in , like " (before and/or behind HREF) " - can have Whitespace embedding the `=' like " " Note: Url must be surrounded by `"'. But that should not be mandatory... " Regexp-Guru please help! let pat = '' else call Utl_trace("- file type is not 'html', so use generic pattern") " Allow different embeddings: , . " Plus for backward compatibility utl-1.0 and future " extension. " ( % in pattern means that this group doesn't count as \1 ) let pat = '<\%(URL:\|LNK:\|\)\([^<]\{-}\)>' endif call Utl_trace("- will use pattern `".pat."'") endif let linestr = a:linestr let icurs = a:icurs " do match() and matchend() ic (i.e. allow url: urL: Url: lnk: lnk: LnK: " . " \_s* can't be used because a string is considered a single line.) let ibeg = match(linestr, "[ \\t \n]*".pat) if ibeg == -1 || ibeg > icurs let curl = '' break else " matchstart before cursor or same col as cursor, " look if matchend is ok (i.e. after or equal cursor) let iend = matchend(linestr, "[ \\t \n]*".pat) -1 if iend >= icurs " extract the URL itself from embedding let curl = substitute(linestr, '^.\{-}'.pat.'.*', '\1', '') " (}) break else " match was before cursor. Check for a second URL in linestr; " redo with linestr = `subline' behind the match let linestr = strpart(linestr, iend+1, 9999) let icurs = icurs-iend-1 continue endif endif endwhile let &ignorecase = saveIgnorecase " (]) call Utl_trace("- end extracting URL by pattern, returning URL=`".curl."'",1,-1) return curl endfu "------------------------------------------------------------------------------- " Switch syntax highlighting for URLs on or off. Depending on the config " variable g:utl_opt_highlight_urls fu! s:Utl_setHighl() if g:utl_opt_highlight_urls ==? 'yes' augroup utl_highl au! au BufWinEnter * syn case ignore " [id=highl_custom] " Highlighting of URL surrounding `' " [id=highl_surround] "au BufWinEnter * hi link UtlTag Identifier " as of Utl v2.0 "au BufWinEnter * hi link UtlTag Ignore " `' invisible like | | in Vim help "au BufWinEnter * hi link UtlTag PreProc " Highlighting of URL itself (what is inside `' " [id=highl_inside] " Some fixed colors ( not changing with :colorscheme, but all underlined ) "au BufWinEnter * hi UtlUrl ctermfg=LightBlue guifg=LightBlue cterm=underline gui=underline term=reverse "au BufWinEnter * hi UtlUrl ctermfg=Blue guifg=Blue cterm=underline gui=underline term=reverse "au BufWinEnter * hi UtlUrl ctermfg=Cyan guifg=Cyan cterm=underline gui=underline term=reverse " Some Standard group names (see ) "au BufWinEnter * hi link UtlUrl Tag "au BufWinEnter * hi link UtlUrl Constant au BufWinEnter * hi link UtlUrl Underlined au BufWinEnter * syn region UtlUrl matchgroup=UtlTag start=" under " chapter E, Recommendations. " " Examples: " call s:Utl_processUrl('file:///path/to/file.txt', 'edit') " " call s:Utl_processUrl('file:///usr/local/share/vim/', 'vie') " " may call Vim's explorer " " call s:Utl_processUrl('http://www.vim.org', 'edit') " " call browser on URL " " call s:Utl_processUrl('mailto:stb@bf-consulting.de', 'vie') " " the local file may be the return receipt in this case " fu! s:Utl_processUrl(uriref, dispMode) call Utl_trace("- start processing URL `".a:uriref."' in processing mode `".a:dispMode."'",1,1) let urirefpu = a:uriref " uriref with newline whitespace sequences purged " check if newline contained. Collapse \s*\n\s if match(a:uriref, "\n") != -1 let urirefpu = substitute(a:uriref, "\\s*\n\\s*", "", "g") call Utl_trace("- URL contains new line characters. Remove them.") call Utl_trace(" now URL= `".urirefpu."'") endif let uri = UriRef_getUri(urirefpu) let fragment = UriRef_getFragment(urirefpu) call Utl_trace("- fragment `".fragment."' stripped from URL") "--- Handle Same Document Reference (sdreference) " processed as separate case, because: " 1. No additional 'retrieval' should happen (see " ). " 2. UtlUri_abs() does not lead to a valid absolute Url (since the base-path- " file-component will always be discarded). " if uri == '' call Utl_trace("- is a same document reference. Go directly to fragment processing (in mode 'rel')") " m=go normal m' call s:Utl_processFragmentText( fragment, 'rel' ) call Utl_trace("- end processing URL",1,-1) return endif call Utl_trace("- start normalize URL to an absolute URL",1,1) let scheme = UtlUri_scheme(uri) if scheme != '' call Utl_trace("- scheme defined (".scheme.") - so is an absolute URL") let absuri = uri else " `uri' is formally no absolute URI but look for some " heuristic, e.g. prepend 'http://' to 'www.vim.org' call Utl_trace("- scheme undefined - so is a relative URL or a heuristic URL") call Utl_trace("- check for some heuristics like www.foo.com -> http://www.foo.com... ",0) let absuri = s:Utl_checkHeuristicAbsUrl(uri) if absuri != '' let scheme = UtlUri_scheme(absuri) call Utl_trace("yes,") | call Utl_trace(" absolute URL constructed by heuristic is `".absuri."'") else call Utl_trace("no") endif endif if scheme == '' let curPath = Utl_utilBack2FwdSlashes( expand("%:p") ) if stridx(curPath, '://') != -1 " id=url_buffer (e.g. by netrw) call Utl_trace("- buffer's name looks like an absolute URL (has substring ://)") call Utl_trace(" so take it as base URL.") let base = curPath else call Utl_trace("- try to construct a `file://' base URL from current buffer... ",0) " No corresponding resource to curPath known. (id=nobase) " i.e. curPath was not retrieved through Utl. " Now just make the usual heuristic of `file://localhost/'-Url; " assume, that the curPath is the resource itsself. If then the " retrieve with the so generated Url is not possible, nothing " severe happens. if curPath == '' call Utl_trace("not possible, give up") let v:errmsg = "Cannot make a base URL from unnamed buffer. Edit a file and try again" echohl ErrorMsg | echo v:errmsg | echohl None call Utl_trace("- end normalize URL to an absolute URL",1,-1) call Utl_trace("- end processing URL",1,-1) return endif let base = 'file://' . curPath call Utl_trace("done,") endif call Utl_trace(" base URL is `".base."'") let scheme = UtlUri_scheme(base) call Utl_trace("- construct absolute URL from combining base URL and relative URL") let absuri = UtlUri_abs(uri,base) endif call Utl_trace("- assertion: now have absolute URL `".absuri."' with scheme `".scheme."'") call Utl_trace("- end normalize URL to an absolute URL",1,-1) if a:dispMode==? 'copyLink' call Utl_trace("processing mode is `copyLink'. Copy link to clipboard") call setreg('*', absuri) echo "Copied `".@*."' to clipboard" call Utl_trace("- end processing URL",1,-1) return endif "--- Call the appropriate retriever (see ) call Utl_trace("- start scheme handler processing",1,1) " Always set a jump mark to allow get back to cursor position before " jump (see also CR051). " m=go id=_setj normal m' let cbfunc = 'Utl_AddressScheme_' . scheme call Utl_trace("- constructing call back function name from scheme: `".cbfunc."'") if !exists('*'.cbfunc) let v:errmsg = "Sorry, scheme `".scheme.":' not implemented" echohl ErrorMsg | echo v:errmsg | echohl None call Utl_trace("- end scheme handler processing",1,-1) call Utl_trace("- end processing URL",1,-1) return endif call Utl_trace("- calling call back function with arguments:") call Utl_trace(" arg 1 - absolute URL=`".absuri."'") call Utl_trace(" arg 2 - fragment =`".fragment."'") call Utl_trace(" arg 3 - display Mode=`".a:dispMode."'") exe 'let ret = ' cbfunc . '("'.absuri.'", "'.fragment.'", "'.a:dispMode.'")' call Utl_trace("- call back function `".cbfunc."' returned list:`". join(ret,',') ."'") exe "normal \" | " Redraw seems necessary for non GUI Vim under Unix'es if !len(ret) call Utl_trace("- empty list -> no further processing") call Utl_trace("- end scheme handler processing",1,-1) call Utl_trace("- end processing URL",1,-1) return endif let localPath = ret[0] let fragMode = get(ret, 1, 'abs') call Utl_trace("- first list element (local path): `".localPath."'") call Utl_trace("- second list element (fragment mode) or default: `".fragMode."'") " Assertion if stridx(localPath, '\') != -1 echohl ErrorMsg call input("Internal Error: localPath `".localPath."' contains backslashes ") echohl None endif call Utl_trace("- assertion: a local path corresponds to URL") call Utl_trace("- end scheme handler processing",1,-1) let dispMode = a:dispMode if a:dispMode == 'copyFileName_native' if has("win32") || has("win16") || has("win64") || has("dos32") || has("dos16") call Utl_trace("- changing dispMode `copyFileName_native' to 'copyFileName_backSlash' since under Windows") let dispMode = 'copyFileName_backSlash' else call Utl_trace("- changing dispMode `copyFileName_native' to 'copyFileName_slash' since not under Windows") let dispMode = 'copyFileName_slash' endif endif if dispMode == 'copyFileName_slash' call Utl_trace("- processing mode is `copyFileName_slash': copy file name, which corresponds to link") call Utl_trace(" (with forward slashes) to clipboard") call setreg('*', localPath ) echo "Copied `".@*."' to clipboard" call Utl_trace("- end processing URL",1,-1) return elseif dispMode == 'copyFileName_backSlash' call Utl_trace("- processing mode is `copyFileName_backSlash': copy file name, which corresponds to link") call Utl_trace(" (with backslashes) to clipboard") call setreg('*', Utl_utilFwd2BackSlashes(localPath) ) echo "Copied `".@*."' to clipboard" call Utl_trace("- end processing URL",1,-1) return endif " See if media type is defined for localPath, and if yes, whether a " handler is defined for this media type (if not the Setup is called to " define one). Everything else handle with the default handler " Utl_displayFile(), which displays the document in a Vim window. " The pseudo handler named 'VIM' is supported: Allows bypassing the media " type handling and call default vim handling (Utl_displayFile) " although there is a media type defined. call Utl_trace("- start media type handler processing",1,1) call Utl_trace("- check if there is a file-name to media-type mapping for local path") call Utl_trace(" (hardcoded in Utl)... ",0) let contentType = s:Utl_checkMediaType(localPath) if contentType == '' call Utl_trace("no. Display local path in this Vim.") else call Utl_trace("yes, media type is `".contentType."'.") let slashPos = stridx(contentType, '/') let var_s = 'g:utl_cfg_hdl_mt_' . substitute(contentType, '[-/+.]', '_', 'g') call Utl_trace("- constructing Vim variable for specific media type handler:") call Utl_trace(" `".var_s."'. Now check if it exists...") if exists(var_s) call Utl_trace(" ...exists, and will be used") let var = var_s else call Utl_trace(" ...does not exist. Now check generic media type handler variable") let var_g = 'g:utl_cfg_hdl_mt_generic' if exists(var_g) call Utl_trace("- Vim variable `".var_g."' does exist and will be used") else call Utl_trace(" Vim variable `".var_g."' does not exist either") endif let var = var_g endif if ! exists(var) " Entering setup echohl WarningMsg call input('No handler for media type '.contentType.' defined yet. Entering Setup now. ') echohl None call s:Utl_processUrl('config:#r=utl_cfg_hdl_mt_generic', 'split') " (recursion, setup) call Utl_trace("- end media type handler processing",1,-1) call Utl_trace("- end processing URL",1,-1) return endif exe 'let varVal =' . var call Utl_trace("- Variable has value `".varVal."'") if varVal ==? 'VIM' call Utl_trace("- value of variable is 'VIM': display in this Vim") else call Utl_trace("- construct command by expanding any % conversion specifiers.") let convSpecDict= { 'p': localPath, 'P': Utl_utilFwd2BackSlashes(localPath), \ 'f': (fragment=="" ? "" : fragment) } " '' -> '' for external handler exe 'let [errmsg,cmd] = Utl_utilExpandConvSpec('.var.', convSpecDict)' if errmsg != "" echohl ErrorMsg echo "The content of the Utl-setup variable `".var."' is invalid and has to be fixed! Reason: `".errmsg."'" echohl None call Utl_trace("- end media type handler processing",1,-1) call Utl_trace("- end processing URL",1,-1) return endif call Utl_trace("- constructed command is: `".cmd."'") " Escape string to be executed as a ex command (i.e. escape some " characters from special treatment ) " and execute the command let escCmd = escape(cmd, s:utl_esccmdspecial) if escCmd != cmd call Utl_trace("- escape characters, command changes to: `".escCmd."'") endif call Utl_trace("- execute command with :exe") exe escCmd call Utl_trace("- end media type handler processing",1,-1) call Utl_trace("- end processing URL",1,-1) return endif endif call Utl_trace("- end media type handler processing",1,-1) if s:Utl_displayFile(localPath, dispMode) call s:Utl_processFragmentText(fragment, fragMode) endif call Utl_trace("- end processing URL",1,-1) endfu "id=Utl_checkHeuristicAbsUrl-------------------------------------------------- " " This function is called for every URL which is not an absolute URL. " It should check if the URL is meant to be an absolute URL and return " the absolute URL. E.g. www.host.domain -> http://www.host.domain. " " You might want to extend this function for your own special URLs " and schemes, see #r=heur_example below " fu! s:Utl_checkHeuristicAbsUrl(uri) "--- [1] -> foot:1 if match(a:uri, '^\[.\{-}\]') != -1 return substitute(a:uri, '^\[\(.\{-}\)\]', 'foot:\1', '') "--- www.host.domain -> http://www.host.domain elseif match(a:uri, '^www\.') != -1 return 'http://' . a:uri "--- user@host.domain -> mailto:user@host.domain elseif match(a:uri, '@') != -1 return 'mailto:' . a:uri "--- :xxx -> vimscript::xxx elseif match(a:uri, '^:') != -1 return 'vimscript:' . a:uri " BT12084 -> BT:12084 #id=heur_example " This is an example of a custom heuristics which I use myself. I have a " text file which contains entries like 'BT12084' which refer to that id " 12084 in a bug tracking database. elseif match(a:uri, '^[PB]T\d\{4,}') != -1 return substitute(a:uri, '^\([PB]T\)\(\d\+\)', 'BT:\2', '') endif return '' endfu "------------------------------------------------------------------------------ " Escape some special characters in fileName which have special meaning " in Vim's command line but what is not desired in URLs. " Example: In file 'a%b.txt' the % must not be expanded to the current file. " " - returns: Escaped fileName " fu! s:Utl_escapeCmdLineSpecialChars(fileName) " - Escape characters '#' and '%' with special meaning for Vim " cmd-line (see because they must have no special " meaning in URLs. let escFileName = escape(a:fileName, s:utl_esccmdspecial) " - Also escape '$': Will otherwise tried to be expanded by Vim as Envvar (CR030). " But only escape if there is an identifier character after the $ (CR053). let escFileName = substitute(escFileName, '\$\(\I\)', '\\$\1', 'g') " - Also escape blanks because single word needed, e.g. `:e foo bar'. " Escape spaces only if on unix (no problem on Windows) (CR033) if has("unix") let escFileName = escape(escFileName, ' ') endif return escFileName endfu "------------------------------------------------------------------------------- " Description: " Display file `localPath' in a Vim window as determined by `dispMode' " There is special treatment if `localPath' already loaded in a buffer and " there is special treatment if current buffer cannot be abandoned. " Escapes characters in localPath which have special meaning for Vim but " which must not have special meaning in URL paths. " " - `dispMode' specification: (id=dispMode) " Resembles XML-XLink's `show' attribut. Value is taken directly as Vim " command. Examples: 'view', 'edit', 'sview', 'split', 'read', 'tabe' " " - localPath specification: " . May contain any characters that the OS allows (# % $ ' ') " Note: No percent escaping here, localPath is a file name not an URL. " For instance %20.txt is taken as literal file name. " " - returns: 1 on success (a:localPath loaded), else 0 " " - collaboration: " . Does not explicitly set the cursor " . Does not explicitly set the ' mark " " Example: :call s:Utl_displayFile('t.txt', 'split') " fu! s:Utl_displayFile(localPath, dispMode) call Utl_trace("- start display file `".a:localPath."' in mode `".a:dispMode."'",1,1) let bwnrlp = bufwinnr(a:localPath) if bwnrlp != -1 && winnr() == bwnrlp call Utl_trace("- file already displayed in current window") call Utl_trace("- end display file",1,-1) return 1 endif if bwnrlp != -1 " localPath already displayed, but not in current window " Just make this buffer the current window. call Utl_trace("- file already displayed, but not in other window. Move to that window") exe bwnrlp . "wincmd w" else " Open file call Utl_trace("- file not yet displayed in any window") " Possibly alter dispMode to avoid E37 error (id=_altersa) " If buffer cannot be ned, for given dispMode, " silently change the dispMode to a corresponding split-dispMode. Want " to avoid annoying E37 message when executing URL on modified buffer (CR024) let dispMode = a:dispMode if getbufvar(winbufnr(0),"&mod") && ! getbufvar(winbufnr(0),"&awa") && ! getbufvar(winbufnr(0),"&hid") if dispMode == 'edit' let dispMode = 'split' call Utl_trace("- current window can probably not be quit, so silently change mode to `split'") elseif dispMode == 'view' let dispMode = 'sview' call Utl_trace("- current window can probably not be quit, so silently change mode to `sview'") endif endif let escLocalPath = s:Utl_escapeCmdLineSpecialChars(a:localPath) if escLocalPath != a:localPath call Utl_trace("- Escaped one or more characters out of #,%,$ (under Unix also blank)") call Utl_trace(" because these would else be expanded in Vim's command line") call Utl_trace(" File name changed to: `".escLocalPath."'") endif "--- Try load file or create new buffer. Then check if buffer actually " loaded - might fail for if E325 (swap file exists) and user abort " let cmd = dispMode.' '.escLocalPath call Utl_trace("- trying to load/display file with command: `".cmd."'\n") " CR054_extra_nl exe cmd exe "normal \" | " Redraw seems necessary for non GUI Vim under Unix'es if bufwinnr(escLocalPath) != winnr() " not loaded call Utl_trace("- not loaded.") call Utl_trace("- end display file (not successful)",1,-1) return 0 endif endif call Utl_trace("- end display file (successful)",1,-1) return 1 endfu "----------------------------------------------------------id=utl_checkmtype---- " Possibly determines the media type (= mime type) for arg `path', e.g. " pic.jpeg -> 'image/jpeg' and returns it. Returns an empty string if media " type cannot be determined or is uninteresting to be determined. Uninteresting " means: Only those media types are defined here which are of potential " interest for being handled by some external helper program (e.g. MS Word for " application/msword or xnview for application/jpeg). " " When this function returns a non empty string Utl checks if a specific media " type handler is defined. If not Utl's setup utility is called to define one. " " - You may add other mediatypes. See " or " for the registry of " media types. On Linux try In general this makes only " sense when you also supply a handler for every media type you define, see " . " fu! s:Utl_checkMediaType(path) if isdirectory(a:path) return "text/directory" endif let ext = fnamemodify(a:path, ":e") let mt = '' " MS windows oriented if ext==?'doc' || ext==?'dot' || ext==?'wrd' let mt = 'application/msword' elseif ext==?'xls' let mt = 'application/excel' elseif ext==?'ppt' let mt = 'application/powerpoint' elseif ext==?'wav' let mt = 'audio/wav' elseif ext==?'msg' let mt = 'application/msmsg' elseif ext==?'avi' let mt = 'video/x-msvideo' " universal elseif ext==?'dvi' let mt = 'application/x-dvi' elseif ext==?'pdf' let mt = 'application/pdf' elseif ext==?'rtf' let mt = 'application/rtf' elseif ext==?'ai' || ext==?'eps' || ext==?'ps' let mt = 'application/postscript' elseif ext==?'rtf' let mt = 'application/rtf' elseif ext==?'zip' let mt = 'application/zip' elseif ext==?'mp3' || ext==?'mp2' || ext==?'mpga' let mt = 'audio/mpeg' elseif ext==?'png' let mt = 'image/png' elseif ext==?'jpeg' || ext==?'jpg' || ext==?'jpe' || ext==?'jfif' let mt = 'image/jpeg' elseif ext==?'tiff' || ext==?'tif' let mt = 'image/tiff' elseif ext==?'gif' || ext==?'gif' let mt = 'image/gif' elseif ext==?'mp2' || ext==?'mpe' || ext==?'mpeg' || ext==?'mpg' let mt = 'video/mpeg' " id=texthtml elseif ext==?'html' || ext==?'htm' let mt = 'text/html' " unix/linux oriented elseif ext==?'fig' let mt = 'image/x-fig' endif return mt endfu "id=Utl_processFragmentText----------------------------------------------------- " Description: " Position cursor in current buffer according `fragment', modified by " `fragMode' which can have values 'abs' or 'rel'. " " - arg `fragment' can be: " tn=string - searches string beginning at start position forward. " The naked fragment (without a `xx=' as prefix defaults " to tn=). " tp=string - searches string beginning at start position backward. " line=number - move cursor number lines from start position. Number " can be positive or negative. If `fragMode' is 'abs' " -1 denotes the last line, -2 the before last line etc. " r=identifier - (IdReference) search for id=identifier\> starting from " begin of buffer. `fragMode' is ignored. " " - arg `fragMode' modifies the start position. Can have the values: " 'abs' = absolute: Cursor is set to begin or end of document, depending on " fragment, then position starting from there. " Start position for tn=, line=nnn, line=+nnn r= is begin of buffer. " Start position for tp=, line=-nnn is end of buffer. " 'rel' = relative: Start positioning the cursor from current position. " " Details: " - `fragment' will be URI-Unescaped before processing (e.g. 'tn=A%3aB' -> " 'tn=A:B') " - Interpretation of `fragment' depends on the filetype. But currently, " the only non generic treatment is for HTML references. " - `Fragment' can be '' or '' (empty). " - If `rel' position the cursor to begin or end of line prior to actual " search: a target string in the same line will not be found. " (Remark: Intent is to support Same-Document references: avoid that " the search finds the fragment definition itself. Should not be a " problem in other cases, e.g. vimhelp scheme) " " Known Bugs: " - For 'abs' search does not find pattern starting at begin of file " fu! s:Utl_processFragmentText(fragment, fragMode) call Utl_trace("- start processing fragment `".a:fragment."' in mode `".a:fragMode."'",1,1) if a:fragment == '' || a:fragment == '' call Utl_trace("- have no or empty fragment") if a:fragMode=='abs' call Utl_trace("- since mode is `abs' position cursor to begin of buffer") call cursor(1,1) else call Utl_trace("- since mode is `rel' do nothing") endif call Utl_trace("- end processing fragment",1,-1) return endif let ufrag = UtlUri_unescape(a:fragment) if ufrag != a:fragment call Utl_trace("- unescaped URL to: `".ufrag."'") endif if ufrag =~ '^line=[-+]\=[0-9]*$' call Utl_trace("- is a `line=' fragment") let sign = substitute(ufrag, '^line=\([-+]\)\=\([0-9]*\)$', '\1', '') let num = substitute(ufrag, '^line=\([-+]\)\=\([0-9]*\)$', '\2', '') if a:fragMode=='abs' if sign == '-' call Utl_trace("- negative sign in mode 'abs': position cursor up ".num." lines from end of buffer") call cursor( line('$') - num + 1, 1 ) else call Utl_trace("- positive sign in mode 'abs': position cursor to line ".num) call cursor(num,1) endif else if sign == '-' call Utl_trace("- negative sign in mode 'rel': position cursor up ".num." lines from current position") call cursor( line('.') - num , 1 ) else call Utl_trace("- positive sign in mode 'rel': position cursor down ".num." lines from current position") call cursor( line('.') + num , 1 ) endif endif call Utl_trace("- end processing fragment",1,-1) return endif " (the rest is positioning by search) " Note: \r is necessary for executing cmd with :normal. " Note: \M is used in patterns to do search nomagic (e.g. pattern a.c to find a.c " and not abc). let fragMode = a:fragMode let sfwd=1 if ufrag =~ '^r=' call Utl_trace("- is an ID reference. Construct file type dependent search pattern") " ( \w\@! is normally the same as \> , i.e. match end of word, " but is not the same in help windows, where 'iskeyword' is " set to include non word characters. \w\@! is independent of " settings ) let val = substitute(ufrag, '^r=\(.*\)$', '\1', '') if &ft == 'html' call Utl_trace("- file type is 'html' - search for NAME=") let cmd = '/\c\MNAME=\.\=' . val . '\w\@!' . "\r" else call Utl_trace("- file type is not 'html' - search for id=") let cmd = '/\c\Mid=' . val . '\w\@!' . "\r" endif if fragMode=='rel' call Utl_trace("- search will be with 'wrapscan' (since ID reference anywhere in text)") let opt_wrapscan='wrapscan' endif elseif ufrag =~ '^tp=' " text previous call Utl_trace("- is a `tp=' (Text Previous) fragment: search backwards") let cmd = substitute(ufrag, '^tp=\(.*\)$', '?\\c\\M\1\r', '') let sfwd=0 elseif ufrag =~ '^tn=' " tn= or naked. text next call Utl_trace("- is a `tn=' (Text Next) fragment: search forward") let cmd = substitute(ufrag, '^tn=\(.*\)$', '/\\c\\M\1\r', '') else call Utl_trace("- is a naked fragment. Is treated like `tn=' (Text Next) fragment: search forward") let cmd = '/\c\M' . ufrag . "\r" " Note: \c\M vs \\c\\M at <#tp=substitute> endif " Initialize Cursor before actual search (CR051) if fragMode=='abs' if sfwd==1 call Utl_trace("- forward search in mode 'abs': starting search at begin of buffer") call cursor(1,1) else call Utl_trace("- backward search in mode 'abs': starting search at end of buffer") call cursor( line('$'), col('$') ) endif else if sfwd==1 call Utl_trace("- forward search in mode 'rel': starting search at end of current line") call cursor( line('.'), col('$') ) else call Utl_trace("- forward search in mode 'rel': starting search at begin of current line") call cursor( line('.'), 1) endif endif if ! exists('opt_wrapscan') let opt_wrapscan = 'nowrapscan' call Utl_trace("- search will be with 'nowrapscan' (avoid false hit if mode='rel')") endif " Do text search (id=fragTextSearch) " (Should better use search() instead normal / - there is also a w flag) let saveWrapscan = &wrapscan | exe 'set '.opt_wrapscan | "---[ " (keepjumps because before jump mark is set before link execution (s. #r=_setj ). " Call cursor() for line= fragments do not change jumps either.) call Utl_trace("- execute search command: `".cmd."'") let v:errmsg = "" silent! exe "keepjumps normal " . cmd if v:errmsg != "" let v:errmsg = "fragment address #" . a:fragment . " not found in target" echohl ErrorMsg | echo v:errmsg | echohl None endif let &wrapscan = saveWrapscan "---] call Utl_trace("- restored previous value for 'wrapscan'") call Utl_trace("- end processing fragment",1,-1) endfu " Utility functions [ "id=Utl_utilExpandConvSpec-------------------------------------------------------- " Expands conversion specifiers like %p in a:str by replacing " them by there replacement value. Conversion specifier - replacement pairs " as provided in convSpecDict dictionary. " Details : " All occurrences of conversion specifier in a:str will be replaced. " Specifiers not defined in convSpecDict lead to an error. " The case of conversion specifier matters, e.g. %p and '%P' are different. " " Args: " str - string to be expanded " convSpecDict - dictionary containing specifier - replacement entries, " e.g. 'p' - 'c:/path/to/file' " " Returns: List [errormessage, converted string], " where either or the other is an empty string " fu! Utl_utilExpandConvSpec(str, convSpecDict) let rest = a:str let out = '' while 1 let percentPos = stridx(rest, '%') if percentPos != -1 let left = strpart(rest, 0, percentPos) let specifier = strpart(rest, percentPos+1, 1) let rest = strpart(rest, percentPos+2) else let out = out . rest break endif if strpart(left, percentPos-1, 1) == '\' " escaped \% let left = strpart(left, 0, percentPos-1) let repl = '%' . specifier else " not escaped if specifier == '' return ["Unescaped % character at end of string >".a:str."<", ""] elseif has_key(a:convSpecDict, specifier) let repl = a:convSpecDict[specifier] else return ["Invalid conversion specifier `%".specifier."' in `".a:str. \ "'. Valid specifiers are: `". join(map(keys(a:convSpecDict), '"%".v:val')), ""] endif endif let out = out . left . repl endwhile return ["",out] endfu "------------------------------------------------------------------------------- " Print tracing messages (with :echo) to see what's going on. " Only prints if global variable utl_opt_verbose is not 0. " Currently works only in on/off-manner. Might be extended to distinguish " trace levels (as Vim's 'verbose' option does, see ) " " - args " msg, " [flush,] boolean, default=1 -> print msg directly " [incrLevel] number, values= -1 (reduce indent), 0 (unchanged), +1 (augment indent) " default ist 0 (unchanged) " let s:utl_trace_buffer = '' let s:utl_trace_level = 0 fu! Utl_trace(msg, ...) if g:utl_opt_verbose == 0 return endif "echo " DBG msg=`".a:msg."'" let flush=1 if exists('a:1') let flush = a:1 endif let incrLevel = 0 if exists('a:2') let incrLevel = a:2 endif " If negative, do it before printing if incrLevel < 0 let s:utl_trace_level += incrLevel " Assertion if s:utl_trace_level < 0 echohl ErrorMsg call input("Internal Error: Utl_trace: negative indent. Setting to zero ") echohl None let s:utl_trace_level = 0 endif "echo " DBG (changed,before) utl_trace_level=`".s:utl_trace_level."'" endif " echohl ErrorMsg " echo "Error: internal error: s:utl_trace_level < 0: `".s:utl_trace_level."'" " echohl None let s:utl_trace_buffer = s:utl_trace_buffer . a:msg if flush=='1' " construct indenting corresponding to level let indentNum = s:utl_trace_level let indent = '' while indentNum "echo " DBG indentNum=`".indentNum."'" let indent = indent . ' ' " indent depth is two blanks let indentNum -= 1 endwhile "echo " DBG indent=`".indent."'" echo indent . s:utl_trace_buffer let s:utl_trace_buffer = '' endif " If positive, do it after printing if incrLevel > 0 let s:utl_trace_level += incrLevel "echo " DBG (changed,after) utl_trace_level=`".s:utl_trace_level."'" endif endfu "------------------------------------------------------------------------------- " Descr: Creates a file named a:outFile as a copy of file a:srcFile, where " only the lines between the first and the second occurrence of a:mark are kept. " Details : " - a:outFile gets some additional header lines. " - a:mark is anchored at the beginning of the line (^ search) " - a:mark is taken literally (search with \M - nomagic for it) " " Collaboration: " - Shows result to user by prompting hit-any-key " - Except for use of utl_trace function pure utility function. " " Ret: - " " fu! Utl_utilCopyExtract(srcFile, outFile, mark) call Utl_trace("- start Utl_utilCopyExtract(".a:srcFile.",".a:outFile.",".a:mark.")",1,1) let go_back = 'b ' . bufnr("%") enew! exe 'read '.a:srcFile setl noswapfile modifiable norm gg let buf = bufnr("%") " Delete from first line to the first line that starts with a:mark let delCmd='1,/\M^'.a:mark.'/d' call Utl_trace("- command to delete from top to begin mark= `".delCmd."'") exe delCmd " Delete from the now first line that starts with a:mark to the end of the text let delCmd='/\M^'.a:mark.'/,$d' call Utl_trace("- command to delete from end mark to bottom= `".delCmd."'") exe delCmd 0insert ' ***** ' CREATED BY VIM PLUGIN UTL.VIM BY FUNCTION Utl_utilCopyExtract() ' ***** . exe 'w! '.a:outFile exe go_back exe 'bwipeout ' . buf echohl MoreMsg call input("Success: Created file ".a:outFile." ") echohl None call Utl_trace("- end Utl_utilCopyExtract()",1,-1) endfu "------------------------------------------------------------------------------- " Substitute all slashes with forward slashes in copy of a:str and return it. fu! Utl_utilFwd2BackSlashes(str) return substitute( a:str , '/', '\', 'g') endfu "------------------------------------------------------------------------------- " Substitute all backslashes with slashes in copy of a:str and return it. fu! Utl_utilBack2FwdSlashes(str) return substitute( a:str , '\', '/', 'g') endfu " ] " BEGIN OF DEFINITION OF STANDARD UTL `DRIVERS' " id=utl_drivers [ "------------------------------------------------------------------------------- " Retrieve a resource from the web using the wget network retriever. " Function designed as g:utl_cfg_hdl_scm_http interface function, e.g. intended to " be used via :let g:utl_cfg_hdl_scm_http="call Utl_if_hdl_scm_http__wget('%u')". " See also #r=utl_cfg_hdl_scm_http__wget " " Arg: url - URL to be downloaded " Ret: global Vim var g:utl__hdl_scm_ret_list set, containing one element: " the name of a temporary file where wget downloaded into. " " Setup: See " fu! Utl_if_hdl_scm_http__wget(url) call Utl_trace("- start Utl_if_hdl_scm_http__wget(".a:url.")",1,1) " Possibly transfer suffix from URL to tempname for correct subsequent " media type handling If no suffix then assume 'html' (ok for " http://www.vim.org -> index.html). But is not generally ok " (example: http://www.vim.org/download.php). " TODO: " Should determine media type from HTTP Header, e.g. " wget --save-headers -> Content-Type: text/html) let suffix = fnamemodify( UtlUri_path(a:url), ":e") if suffix == '' let suffix = 'html' endif let tmpFile = Utl_utilBack2FwdSlashes( tempname() ) .'.'.suffix call Utl_trace("- tmpFile name with best guess suffix: ".tmpFile) if ! executable('wget') call Utl_trace("- Vim variable g:utl_cfg_hdl_scm_mail does not exist") echohl WarningMsg let v:errmsg="No executable `wget' found." call input( v:errmsg . " Entering Setup now. ") echohl None Utl openLink config:#r=utl_if_hdl_scm_http_wget_setup split call Utl_trace("- end execution of Utl_AddressScheme_mail",1,-1) return endif let cmd = '!wget '.a:url.' -O '.tmpFile call Utl_trace("- executing cmd: `".cmd."'") exe cmd call Utl_trace("- setting global list g:utl__hdl_scm_ret_list to `[".tmpFile."]'") let g:utl__hdl_scm_ret_list = [tmpFile] call Utl_trace("- end Utl_if_hdl_scm_http__wget()",1,-1) endfu "------------------------------------------------------------------------------- " Display an email in Outlook " Function designed as g:utl_cfg_hdl_scm_mail interface function, e.g. intended to " be used via :let g:utl_cfg_hdl_scm_mail="call Utl_if_hdl_scm_mail__outlook('%a', " '%p','%d','%f','%s')". See also #r=utl_cfg_hdl_scm_mail__outlook " " Args: ... " Ret: - " " Setup: See fu! Utl_if_hdl_scm_mail__outlook(authority, path, date, from, subject) call Utl_trace("- start Utl_if_hdl_scm_mail__outlook(".a:authority.",".a:path.",".a:date.",".a:from.",".a:subject.")",1,1) if ! exists('g:utl__file_if_hdl_scm__outlook') let g:utl__file_if_hdl_scm__outlook = fnamemodify(g:utl__file, ":h") . '/../utl_if_hdl_scm__outlook.vbs' call Utl_trace("- configure interface handler variable for Outlook g:utl__file_if_hdl_scm__outlook=") call Utl_trace(" ".g:utl__file_if_hdl_scm__outlook) endif if ! filereadable(g:utl__file_if_hdl_scm__outlook) echohl WarningMsg let v:errmsg="No Outlook interface found." call input( v:errmsg . " Entering Setup now. ") echohl None Utl openLink config:#r=Utl_if_hdl_scm_mail__outlook_setup split call Utl_trace("- end Utl_if_hdl_scm_mail__outlook()",1,-1) return endif let cmd='!start wscript "'.g:utl__file_if_hdl_scm__outlook .'" "'. a:authority.'" "'.a:path.'" "'.a:date.'" "'.a:from.'" "'.a:subject.'"' call Utl_trace("- executing cmd: `".cmd."'") exe cmd call Utl_trace("- end Utl_if_hdl_scm_mail__outlook()",1,-1) endfu "------------------------------------------------------------------------------- " Display a file in Acrobat Reader. #page=123 Fragments are supported, i.e. " display the file at this given page. " Function designed as g:utl_cfg_hdl_mt_application_pdf interface function, " e.g. intended to be used via :let g:utl_cfg_hdl_mt_application_pdf="call " Utl_if_hdl_mt_application_pdf_acrobat('%P', '%f')". " See also #r=utl_cfg_hdl_mt_application_pdf_acrobat. " " Arg: path - file to be displayed in Acrobat (full path) " fragment - fragment (without #) or empty string if no fragment " " Ret: - " " Setup: See " fu! Utl_if_hdl_mt_application_pdf_acrobat(path,fragment) call Utl_trace("- start Utl_if_hdl_mt_application_pdf_acrobat(".a:path.",".a:fragment.")",1,1) let switches = '' if a:fragment != '' let ufrag = UtlUri_unescape(a:fragment) if ufrag =~ '^page=' let fval = substitute(ufrag, '^page=', '', '') let switches = '/a page='.fval else echohl ErrorMsg echo "Unsupported fragment `#".ufrag."' Valid only `#page='" echohl None return endif endif if ! exists('g:utl_cfg_hdl_mt_application_pdf_acrobat_exe_path') " Entering setup call Utl_trace("- Vim variable `g:utl_cfg_hdl_mt_application_pdf_acrobat_exe_path.' does not exist") echohl WarningMsg call input('variable g:utl_cfg_hdl_mt_application_pdf_acrobat_exe_path not defined. Entering Setup now. ') echohl None Utl openLink config:#r=Utl_if_hdl_mt_application_pdf_acrobat_setup split call Utl_trace("- end Utl_if_hdl_mt_application_pdf_acrobat() (not successful)",1,-1) return endif " id=ar_switches let cmd = ':silent !start '.g:utl_cfg_hdl_mt_application_pdf_acrobat_exe_path.' /a page='.ufrag.' "'.a:path.'"' call Utl_trace("- executing cmd: `".cmd."'") exe cmd call Utl_trace("- end Utl_if_hdl_mt_application_pdf_acrobat()",1,-1) endfu "------------------------------------------------------------------------------- " Display a file in MS-Word. #tn=text Fragments are supported, i.e. " display the file at position of first occurrence of text. " Function designed as g:utl_cfg_hdl_mt_application_msword interface function, " e.g. intended to be used via :let g:utl_cfg_hdl_mt_application_msword="call " Utl_if_hdl_mt_application_msword__word('%P', '%f')". " See also #r=utl_cfg_hdl_mt_application_msword__word. " " Arg: path - file to be displayed in Acrobat (full path) " fragment - fragment (without #) or empty string if no fragment " " Ret: - " " Setup: See " fu! Utl_if_hdl_mt_application_msword__word(path,fragment) call Utl_trace("- start Utl_if_hdl_mt_application_msword__word(".a:path.",".a:fragment.")",1,1) if ! exists('g:utl__file_if_hdl_mt_application_msword__word') let g:utl__file_if_hdl_mt_application_msword__word = fnamemodify(g:utl__file, ":h") . '/../utl_if_hdl_mt_application_msword__word.vbs' call Utl_trace("- configure interface handler variable for MS-Word g:utl__file_if_hdl_mt_application_msword__word=") call Utl_trace(" ".g:utl__file_if_hdl_mt_application_msword__word) endif if ! filereadable(g:utl__file_if_hdl_mt_application_msword__word) echohl WarningMsg let v:errmsg="No Word interface found." call input( v:errmsg . " Entering Setup now. ") echohl None Utl openLink config:#r=Utl_if_hdl_mt_application_msword__word_setup split call Utl_trace("- end Utl_if_hdl_mt_application_msword__word() (not successful)",1,-1) return endif if ! exists('g:utl_cfg_hdl_mt_application_msword__word_exe_path') " Entering setup call Utl_trace("- Vim variable `g:utl_cfg_hdl_mt_application_pdf_acrobat_exe_path.' does not exist") echohl WarningMsg call input('variable g:utl_cfg_hdl_mt_application_msword__word_exe_path not defined. Entering Setup now. ') echohl None Utl openLink config:#r=Utl_if_hdl_mt_application_msword__word_setup split call Utl_trace("- end Utl_if_hdl_mt_application_msword__word() (not successful)",1,-1) return endif let cmd = 'silent !start '.g:utl_cfg_hdl_mt_application_msword__word_exe_path.' "'.a:path.'"' call Utl_trace("- cmd to open document: `".cmd."'") exe cmd if a:fragment == '' call Utl_trace("- end Utl_if_hdl_mt_application_msword__word() (successful, no fragment)",1,-1) return endif " (CR044:frag) let ufrag = UtlUri_unescape(a:fragment) if ufrag =~ '^tn=' " text next / text previous let fval = substitute(ufrag, '^tn=', '', '') elseif ufrag =~ '[a-z]\+=' echohl ErrorMsg echo 'Unsupported fragment key `'.substitute(ufrag, '\c^\([a-z]\+\).*', '\1=', '')."'. Valid only: `tn='" echohl None call Utl_trace("- end Utl_if_hdl_mt_application_msword__word() (not successful)",1,-1) return else let fval=ufrag " naked fragment same as tn= endif let cmd='silent !start wscript "'.g:utl__file_if_hdl_mt_application_msword__word .'" "'. a:path.'" "'.fval.'"' call Utl_trace("- cmd to address fragment: `".cmd."'") exe cmd call Utl_trace("- end Utl_if_hdl_mt_application_msword__word()",1,-1) endfu let &cpo = s:save_cpo finish === FILE_OUTLOOK_VBS {{{ ' file: utl_if_hdl_scm__outlook.vbs ' synopsis: utl_if_hdl_scm__outlook.vbs "" "Inbox" "08.02.2008 13:31" "" "" ' collaboration: - Used by utl.vim when accessing "mail:" URLs using MS-Outlook. ' - Outlook must be running ' hist: ' 2008-02-29/Stb: Version for Utl.vim v3.0a Option Explicit Dim ol, olns, folder, entryId, item, myNewFolder Dim a_authority, a_path, a_from, a_subject, a_date a_authority = WScript.Arguments(0) a_path = WScript.Arguments(1) a_date = WScript.Arguments(2) a_from = WScript.Arguments(3) a_subject = WScript.Arguments(4) if a_from <> "" Then MsgBox "utl_if_hdl_scm__outlook.vbs: Sorry: from= query not supported. Will be ignored" end if if a_from <> "" Then MsgBox "utl_if_hdl_scm__outlook.vbs: Sorry: subject= query not supported. Will be ignored" end if Set ol = GetObject(, "Outlook.Application") Set olns = ol.GetNameSpace("MAPI") '----- ' Get root folder if a_authority = "" Then ' No a_authority defaults to folder which contains the default folders Set folder = olns.GetDefaultFolder(6) Set folder = folder.Parent else Set folder = olns.Folders.item( a_authority ) end if '----- ' Trailing slash possible even with no path defined. ' So remove it independently of path treatment if a_path <> "" Then ' Remove leading "/" a_path = Right( a_path, Len(a_path)-1 ) end if '----- ' If a_path given search a_path recursively to get corresponding ' folder object (currently no hierarchies, only one subfolder) if a_path <> "" Then Set folder = folder.Folders.item( a_path ) end if Dim sFilter '----- ' Four minute time range turned out to work fairly well finally... Dim dateMin, dateMax dateMin = CStr( DateAdd("n", -2, a_date) ) dateMax = CStr( DateAdd("n", 2, a_date) ) ' cut seconds added by DateAdd dateMin = Left(dateMin, Len(dateMin) -3 ) dateMax = Left(dateMax, Len(dateMax) -3 ) 'id=adapt_column_name ' Unless you have a german Outlook adapt the following line to match you language. ' The Word "Erhalten" probably something like "Received" in english. ' Have a look in you Outlook; its the name of the column which shows and sorts ' by date. ' ' ' [id=received] Change to actual column name in your Outlook ' +---------------------------------+ ' v v sFilter = "[Erhalten] > '" + dateMin + "' AND [Erhalten] < '" + dateMax + "'" Set item = folder.Items.find(sFilter) item.Display === FILE_OUTLOOK_VBS }}} === FILE_WORD_VBS {{{ ' usage: utl_if_hdl_mt_application_msword__word.vbs <.doc file> ' description: Position cursor in Word document <.doc file> at string ' ' Collaboration: Word being started or running. Document subject to fragment ' addressing active or being opened and activated. ' hist: ' 2008-03-20/Stb: Version for Utl.vim v3.0a ' TODO: "Option Explicit" ( Can't get it running with... %-/ ) const wdGoToPage = 1 const wdGoToAbsolute = 1 const wdFindContinue = 1 docPath = WScript.Arguments(0) fragment = WScript.Arguments(1) ' Wait for WORD in case it just starts up countTries = 0 maxTries = 50 Do While countTries < maxTries countTries = countTries+1 On Error Resume Next Set o = GetObject(, "Word.Application") If Err Then WScript.Sleep 200 Err.Clear Else Exit Do End If Loop ' TODO: Exit if still not loaded ' Wait until document loaded countTries = 0 maxTries = 20 docFound = FALSE Do While countTries < maxTries countTries = countTries+1 ' schauen ob ActiveDocument.Name (schon) gleich ' dem docPath ist. pos = InStr(1, docPath, o.ActiveDocument.Name, 1) If pos <> 0 then docFound = TRUE Exit Do End If WScript.Sleep 200 Loop If docFound=FALSE then WScript.Echo("Document not found") End If ' TODO: Exit If docFound=FALSE ' assertion: document active ' process fragment ' TODO: support also page= fragment: ' 'o.Selection.GoTo wdGotoPage, wdGoToAbsolute, 20 o.Selection.Find.ClearFormatting With o.Selection.Find .Text = fragment .Replacement.Text = "" .Forward = True .Wrap = wdFindContinue .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False End With o.Selection.Find.Execute === FILE_WORD_VBS }}} " END OF DEFINITION OF STANDARD UTL `DRIVERS' ] " vim: set foldmethod=marker: " -----id=foot1 " Thanks for trying out Utl.vim :-)