1"
2" Filename: cream-lib-os.vim
3"
4" Cream -- An easy-to-use configuration of the famous Vim text editor
5" [ http://cream.sourceforge.net ] Copyright (C) 2001-2011 Steve Hall
6"
7" License
8" GNU General Public License (GPL) {{{1
9"
10" This program is free software; you can redistribute it and/or modify
11" it under the terms of the GNU General Public License as published by
12" the Free Software Foundation; either version 3 of the License, or
13" (at your option) any later version. [
14" http://www.gnu.org/licenses/gpl.html ]
15"
16" This program is distributed in the hope that it will be useful, but
17" WITHOUT ANY WARRANTY; without even the implied warranty of
18" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19" General Public License for more details.
20"
21" You should have received a copy of the GNU General Public License
22" along with this program; if not, write to the Free Software
23" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24" 02111-1307, USA.
25"
26" 1}}}
27
28" Local functions {{{1
29
30"function! s:OnMS()
31"" NOTE: This localized function a duplicate of that from genutils.vim.
32""
33"    return has("win32") || has("dos32") || has("win16") || has("dos16") || has("win95")
34"endfunction
35
36
37" Path and filenames {{{1
38
39function! Cream_path_fullsystem(path, ...)
40" Return a completely expanded and valid path for the current system
41" from string {path}.
42" o Path does not have to exist, although generally invalid formats
43"   will not usually be properly expanded (e.g., backslash path separators
44"   on Unix).
45" o Both files and directories may be processed. (Paths will not be
46"   returned with a trailing path separator.)
47" o Preserves Windows UNC server name preceding "\\".
48" o {optional} argument can be used to override system settings:
49"   * "win" forces return in Windows format as possible:
50"     - No drive letter is added (none can be assumed)
51"   * "unix" forces return to Unix format as possible:
52"     - Windows drive letter is not removed
53"
54
55	" format type
56	" forced with argument
57	if a:0 == 1
58		if     a:1 == "win"
59			let format = "win"
60		elseif a:1 == "unix"
61			let format = "unix"
62		endif
63	endif
64	" detected if not forced
65	if !exists("format")
66		if Cream_has("ms")
67			let format = "win"
68		else
69			let format = "unix"
70		endif
71	endif
72
73	" expand to full path
74	let path = fnamemodify(a:path, ":p")
75
76	" make Windows format (assume is Unix)
77	if format == "win"
78
79		" remove escaping of spaces
80		let path = substitute(path, '\\ ', ' ', "g")
81
82		" convert forward slashes to backslashes
83		let path = substitute(path, '/', '\', "g")
84
85	" make Unix format (assume is Windows)
86	else
87
88		"" strip drive letter
89		"let path = substitute(path, '^\a:', '', '')
90
91		" convert backslashes to forward slashes
92		let path = substitute(path, '\', '/', "g")
93
94		" escape spaces (but not twice)
95		let path = substitute(path, '[/\\]* ', '\\ ', "g")
96
97	endif
98
99	" remove duplicate separators
100	let path = substitute(path, '\\\+', '\', "g")
101	let path = substitute(path, '/\+', '/', "g")
102
103	" remove trailing separators
104	let path = substitute(path, '[/\\]*$', '', "")
105
106	" maintain Windows UNC servername
107	if Cream_path_isunc(a:path)
108		let path = substitute(path, '^\', '\\\\', "")
109		let path = substitute(path, '^/', '\\\\', "")
110	endif
111
112	return path
113
114endfunction
115
116function! Cream_path_isunc(path)
117" Returns 1 if {path} is in Windows UNC format, 0 if not.
118	if match(a:path, '^\\\\') != -1 || match(a:path, '^//') != -1
119		return 1
120	endif
121endfunction
122
123function! Cream_pathexists(path)
124" Returns 1 if {path} is an existing file or directory. (Ignores
125" ability to write or read to it, only if exists.)
126
127	" if both unreadable and not a directory
128	if !filereadable(a:path) && filewritable(a:path) != 2
129		return 0
130	else
131		return 1
132	endif
133
134endfunction
135
136" Open with default app {{{1
137
138function! Cream_file_open_defaultapp(...)
139" Open file {...} with OS default application. If none passed, current
140" file used.
141
142	if a:0 == 0
143		" use current file
144		let file = Cream_path_fullsystem(expand("%"))
145	else
146		let file = a:1
147	endif
148
149	" GNOME2
150	if     has("gui_gtk2")
151		let cmd = 'silent! !gnome-open ' . escape(file, ' ')
152	" Windows
153	elseif Cream_has("ms")
154		" 95/98/ME
155		if has("win95")
156			let cmd = 'silent! !command /c start "' . file . '"'
157		" NT/2K/XP
158		else
159			" handle URLs differently (http://www.google.com)
160			if Cream_isURL(file)
161				" use start, don't quote
162				let cmd = 'silent! !cmd /c start ' . file
163			else
164				let cmd = 'silent! !cmd /c "' . file . '"'
165			endif
166		endif
167	else
168		" no command found, exit
169		call confirm(
170			\ "Platform not identified, unable to open file.\n" .
171			\ "\n", "&Ok", 1, "Info")
172		return
173	endif
174		if Cream_has("ms")
175			let myshellslash = &shellslash
176			set noshellslash
177			silent! execute cmd
178			let &shellslash = myshellslash
179		else
180			silent! execute cmd
181		endif
182	return 1
183
184endfunction
185
186" Open file explorer {{{1
187"function! Cream_open_fileexplorer()
188"" open the OS file manager to the current file's directory
189"
190"    " parse b:cream_pathfilename (respects links as opposed to
191"    " getcwd())
192"    if exists("b:cream_pathfilename")
193"        let mypath = fnamemodify(b:cream_pathfilename, ":p:h")
194"    else
195"        let mypath = getcwd()
196"    endif
197"
198"    call Cream_file_open_defaultapp(mypath)
199"
200"endfunction
201function! Cream_open_fileexplorer()
202" open the OS file manager to the current file's directory
203
204	" parse b:cream_pathfilename (respects links as opposed to
205	" getcwd())
206	if exists("b:cream_pathfilename")
207		let mypath = fnamemodify(b:cream_pathfilename, ":p:h")
208	else
209		let mypath = getcwd()
210	endif
211
212	let mypath = Cream_path_fullsystem(mypath)
213
214	" NOTE: On Windows XP (2008-01-07), pointing to a cmd.exe to a
215	" directory fails to open explorer--call explorer specifically
216	"
217	"call Cream_file_open_defaultapp(mypath)
218	"
219	" GNOME2
220	if     has("gui_gtk2")
221		let cmd = 'silent! !gnome-open ' . escape(mypath, ' ')
222	" Windows
223	elseif Cream_has("ms")
224		" 95/98/ME
225		if has("win95")
226			let cmd = 'silent! !command /c start "' . mypath . '"'
227		" NT/2K/XP
228		else
229			"let cmd = 'silent! !cmd /c "' . mypath . '"'
230			let cmd = 'silent! !explorer /e,"' . mypath . '"'
231		endif
232	endif
233
234	" no command found, exit
235	if !exists("cmd")
236		call confirm("Platform not identified, unable to open file.\n", "&Ok", 1, "Info")
237		return
238	endif
239	silent! execute cmd
240	return 1
241
242endfunction
243
244" File operations {{{1
245
246"function! Cream_touch(pathfile)
247"" create an empty file {pathfile}
248"" WARNING: Will overwrite an existing file of the same name!
249"
250"    " test that head exists
251"    if !Cream_pathexists(fnamemodify(a:pathfile, ":p:h"))
252"        call confirm(
253"            \ "Error: Invalid path passed to Cream_touch()\n" .
254"            \ "Touch file not created\n" .
255"            \ "\n", "&Ok", 1, "Warning")
256"        return -1
257"    endif
258"
259"    " save position
260"    if exists("$CREAM")
261"        let mypos = Cream_pos()
262"    endif
263"
264"    silent! enew
265"    silent! execute "saveas! " . a:pathfile
266"    " close buffer
267"    silent! bwipeout!
268"
269"    " restore pos
270"    if exists("$CREAM")
271"        execute mypos
272"    endif
273"
274"endfunction
275
276function! Cream_touch(pathfile)
277" create an empty file {pathfile}, prompting if it exists
278
279	" test that head exists
280	if !Cream_pathexists(fnamemodify(a:pathfile, ":p:h"))
281		call confirm(
282			\ "Error: Invalid path passed to Cream_touch().\n" .
283			\ "File not created.\n" .
284			\ "\n", "&Ok", 1, "Warning")
285		return -1
286	endif
287
288	if Cream_has("ms")
289		let pathfile = fnamemodify(a:pathfile, ":p:8")
290	else
291		let pathfile = fnamemodify(a:pathfile, ":p")
292	endif
293
294	execute "silent! confirm 0write " . pathfile
295
296endfunction
297
298" Windows drive letters {{{1
299function! Cream_windrives()
300" Return string listing existing drive letters on MS Windows. Each is
301" returned followed by a newline.
302
303	if !Cream_has("ms")
304		return ""
305	endif
306
307	let cmd = 'for %A in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if exist %A:\CON echo %A: >nul'
308
309	redir @x
310	silent! echo system(cmd)
311	redir END
312
313	let drives = @x
314	" remove DOS echos
315	let drives = substitute(drives, '\u:[[:print:]]\{-1,}>if exist \u:\\CON echo \u:', '', 'g')
316	" remove extra lines
317	let drives = substitute(drives, '\n\n', '', 'g')
318	" remove leading spaces
319	let drives = substitute(drives, '^[ \r\n]\+', '', 'g')
320
321	return drives
322
323endfunction
324
325" Windows Shortcut {{{1
326function! Cream_make_shortcut(spath, sname, target, key, desc)
327" Make a windows shortcut.
328"
329" Example:
330"   call Cream_make_shortcut( .
331"   \ "C:\WINDOWS\Desktop", .
332"   \ "MyShortcut", .
333"   \ "C:\WINDOWS\notepad.exe", .
334"   \ "Ctrl+Shift+N", .
335"   \ "My Notepad".
336"   \ )
337"
338" Arguments:
339" o {spath}  :: Path to shortcut, must exist.
340" o {sname}  :: Name of shortcut, extension ".lnk" not required.
341" o {target} :: Target (exe) of shortcut (can be empty "").
342" o {key}    :: Keyboard shortcut, e.g. "Ctrl+Shift+N".
343" o {desc}   :: Brief description of shortcut, can be empty.
344
345	" only if on Windows
346	if !Cream_has("ms")
347		call confirm(
348			\ "Only available on Windows systems.\n" .
349			\ "\n", "&Ok", 1, "Info")
350	endif
351	" warn if not 9x/NT/64
352	if has("win95") || has("win16") || has("win32unix")
353		let n = confirm(
354			\ "This has not been tested on this version of Windows, continue?\n" .
355			\ "\n", "&Ok", 1, "Info")
356		if n != 1
357			return
358		endif
359	endif
360
361	" verify a:spath has trailing slash
362	let spath = Cream_path_addtrailingslash(a:spath)
363
364	" reject if a:spath doesn't point to a real directory
365	if filewritable(spath) != 2
366		let n = confirm(
367		\ "Path for shortcut doesn't exist, unable to continue.\n" .
368		\ "\n", "&Ok", 1, "Info")
369		return
370	endif
371
372	" a:sname--add .lnk if doesn't exist
373	let sname = a:sname
374	if strpart(sname, strlen(sname)-4) !=? ".lnk"
375		let sname = sname . ".lnk"
376	endif
377
378	" warn if a:target doesn't point to a real file
379	if filereadable(a:target) != 1
380		if filewritable(a:target) == 2
381			let n = confirm(
382			\ "Ok that target points to a directory?\n" .
383			\ "\n", "&Ok\n&Cancel", 1, "Info")
384			if n != 1
385				return
386			endif
387		else
388			let n = confirm(
389			\ "Target does not exist, create anyway?\n" .
390			\ "\n", "&Ok\n&Cancel", 1, "Info")
391			if n != 1
392				return
393			endif
394		endif
395	endif
396
397	" warn if a:desc is too long
398	if strlen(a:desc) > 200
399		let n = confirm(
400			\ "Description is too long for a tooltip, continue anyway?\n" .
401			\ "\n", "&Ok", 1, "Info")
402		if n != 1
403			return
404		endif
405	endif
406
407	" cat valid VBS statements
408	let @x = ''
409	let @x = @x . 'set WshShell = WScript.CreateObject("WScript.Shell")' . "\n"
410	let @x = @x . 'set oShortCutLink = WshShell.CreateShortcut("' . spath . '" & "' . sname . '")' . "\n"
411	let @x = @x . 'oShortCutLink.TargetPath = "' . a:target . '"' . "\n"
412	let @x = @x . 'oShortCutLink.WindowStyle = 1' . "\n"
413	let @x = @x . 'oShortCutLink.Hotkey = "' . a:key . '"' . "\n"
414	let @x = @x . 'oShortCutLink.Description = "' . a:desc . '"' . "\n"
415	let @x = @x . 'oShortCutLink.Save' . "\n"
416
417	" write as temp VBS file
418	call Cream_file_new()
419	put x
420	let fname = tempname() . ".vbs"
421	execute "saveas " . fname
422
423	" run
424	call Cream_file_open_defaultapp()
425
426	" close it
427	silent bwipeout!
428
429	" delete file
430	call delete(fname)
431
432	" verify .lnk made
433	if !filereadable(spath . sname)
434		call confirm(
435			\ "Error: Shortcut not made.\n" .
436			\ "\n", "&Ok", 1, "Info")
437	endif
438
439endfunction
440
441" 1}}}
442" vim:foldmethod=marker
443