Pastey startw.exw

--
-- startw.exw 
-- Start an application via the command line. 
--  
-- Copyright (c) 2014-2016 Greg Haberek <ghaberek@gmail.com> 
--  
-- 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 OR COPYRIGHT HOLDERS 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. 
--  
-- History: 
-- v0.1 - Initial release 
-- v0.2 - Fixed issue with spaces 
--      - Added "-s/--show" option 
 
include std/cmdline.e 
include std/dll.e 
include std/filesys.e 
include std/map.e 
include std/machine.e 
include std/search.e 
include std/sequence.e 
include std/text.e 
without warning 
 
constant CMD_OPTS = { 
    { "d", "path", "Starting directory", {HAS_PARAMETER, ONCE}, -1 }, 
    { "s", "show", "Show method: normal, hidden, minimized, maximized (default: normal)", {HAS_PARAMETER,ONCE}, -1 } 
} 
 
constant HELP_TEXT = { 
    "usage:", 
    "   startw [-d path] [-s show] \"command\" [parameters]" 
} 
 
constant 
    SW_HIDE            =  0, 
    SW_SHOWNORMAL      =  1, 
    SW_SHOWMINIMIZED   =  2, 
    SW_SHOWMAXIMIZED   =  3, 
    SW_MAXIMIZE        =  3, 
    SW_SHOWNOACTIVATE  =  4, 
    SW_SHOW            =  5, 
    SW_MINIMIZE        =  6, 
    SW_SHOWMINNOACTIVE =  7, 
    SW_SHOWNA          =  8, 
    SW_RESTORE         =  9, 
    SW_SHOWDEFAULT     = 10, 
$ 
 
constant SHOW_NAMES = { 
    { "normal",    SW_SHOWNORMAL }, 
    { "hidden",    SW_HIDE }, 
    { "minimized", SW_SHOWMINIMIZED }, 
    { "maximized", SW_SHOWMAXIMIZED } 
} 
 
constant shell32 = open_dll( "shell32.dll" ) 
constant xShellExecute = define_c_func( shell32, "ShellExecuteA", {C_HANDLE,C_POINTER,C_POINTER,C_POINTER,C_POINTER,C_INT}, C_HANDLE ) 
 
-- acceptable values for lpOperation parameter of ShellExecute() 
constant OPERATIONS = { "edit", "explore", "find", "open", "print" } 
 
-- allocates a string (if sequence) or an amount of data (if atom) 
-- and returns NULL if the sequence is empty or the atom is zero 
function allocate_null( object s, integer cleanup = 0 ) 
     
    if sequence( s ) then 
         
        if length( s ) = 0 then 
            return NULL 
        end if 
         
        return allocate_string( s, cleanup ) 
    end if 
     
    if equal( s, 0 ) then 
        return NULL 
    end if 
     
    return allocate_data( s, cleanup ) 
end function 
 
-- performs an operation on a specified file 
function ShellExecute( atom hwnd, sequence operation, sequence file, sequence parameters, sequence directory, integer show_cmd ) 
     
    atom lpOperation    = allocate_null( operation, 1 ) 
    atom lpFile         = allocate_null( file, 1 ) 
    atom lpParameters   = allocate_null( parameters, 1 ) 
    atom lpDirectory    = allocate_null( directory, 1 ) 
    integer nShowCmd    = show_cmd 
     
    return c_func( xShellExecute, {hwnd,lpOperation,lpFile,lpParameters,lpDirectory,nShowCmd} ) 
end function 
 
procedure main() 
     
    map opts = cmd_parse( CMD_OPTS, {HELP_RID, HELP_TEXT} ) 
     
    sequence path   = map:get( opts, "path", current_dir() ) 
    sequence show   = map:get( opts, "show", "normal" ) 
    sequence extras = map:get( opts, EXTRAS ) 
     
    sequence operation = "open" 
    sequence command = "" 
    sequence parameters = "" 
    sequence directory = path 
     
    integer show_cmd = vlookup( show, 
        SHOW_NAMES, 1, 2, SW_SHOWNORMAL ) 
     
    if length( extras ) = 0 then 
         
        -- no options provided, run %ComSpec% (i.e. cmd.exe) 
        command = getenv( "ComSpec" ) 
         
    else 
         
        -- is the first option an operation? 
        if find( extras[1], OPERATIONS ) then 
             
            -- get the operation 
            operation = extras[1] 
             
            -- and trim it off the list 
            extras = extras[2..$] 
             
        end if 
         
        -- do we have an command? 
        if length( extras ) > 0 then 
             
            -- get the command 
            command = extras[1] 
             
            -- and trim it off the list 
            extras = extras[2..$] 
             
            -- get the path to the command 
            command = locate_file( command ) 
             
        end if 
         
        -- quote extras to preserve spaces 
        for i = 1 to length( extras ) do 
            extras[i] = quote( extras[i] ) 
        end for 
         
        -- join the extras into a string of parameters 
        parameters = stdseq:join( extras, ' ' ) 
         
    end if 
     
    -- translate the directory to its canonical path 
    directory = canonical_path( directory, 1 ) 
     
    -- run the command! 
    ShellExecute( NULL, operation, command, parameters, directory, show_cmd ) 
     
end procedure 
 
main()