Make editors use the new path-finding vocabulary and protocol.

Implement io.standard-paths on Windows.
db4
Doug Coleman 2011-10-31 11:53:07 -07:00
parent bf0c7eaa22
commit a647df58f6
31 changed files with 205 additions and 197 deletions

View File

@ -9,19 +9,16 @@ ARTICLE: "editor" "Editor integration"
{ $code "USE: editors.emacs" }
"If you intend to always use the same editor, it helps to have it load during stage 2 bootstrap. Place the code to load and possibly configure it in the " { $link ".factor-boot-rc" } "."
$nl
"Editor integration vocabularies store a quotation in a global variable when loaded:"
{ $subsections edit-hook }
"Editor integration vocabularies store a class or tuple in a global variable when loaded:"
{ $subsections editor-class }
"If a syntax error was thrown while loading a source file, you can jump to the location of the error in your editor:"
{ $subsections :edit } ;
ABOUT: "editor"
HELP: edit-hook
{ $var-description "A quotation with stack effect " { $snippet "( file line -- )" } ". If not set, the " { $link edit } " word throws a condition with restarts for loading one of the sub-vocabularies of the " { $vocab-link "editors" } " vocabulary." } ;
HELP: edit
{ $values { "object" object } }
{ $description "Opens the source file containing the definition using the current " { $link edit-hook } ". See " { $link "editor" } "." }
{ $description "Opens the source file containing the definition using the current " { $link editor-class } ". See " { $link "editor" } "." }
{ $examples
"Editing a word definition:"
{ $code "\\ foo edit" }
@ -35,10 +32,7 @@ HELP: edit
HELP: edit-location
{ $values { "file" "a pathname string" } { "line" "a positive integer" } }
{ $description "Opens a source file at the specified line number containing using the current " { $link edit-hook } ". Line numbers are indexed starting from 1. See " { $link "editor" } "." } ;
HELP: no-edit-hook
{ $error-description "Thrown when " { $link edit } " is called when the " { $link edit-hook } " variable is not set. See " { $link "editor" } "." } ;
{ $description "Opens a source file at the specified line number containing using the current " { $link editor-class } ". Line numbers are indexed starting from 1. See " { $link "editor" } "." } ;
HELP: :edit
{ $description "If the most recent error was a " { $link source-file-error } " thrown while parsing a source file, opens the source file at the failing line in the default editor using the " { $link edit-hook } ". See " { $link "editor" } "." } ;
{ $description "If the most recent error was a " { $link source-file-error } " thrown while parsing a source file, opens the source file at the failing line in the default editor. See " { $link "editor" } "." } ;

View File

@ -1,20 +1,15 @@
! Copyright (C) 2005, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs continuations debugger definitions
help.topics io io.backend io.files io.pathnames kernel lexer
namespaces parser prettyprint sequences source-files
source-files.errors splitting strings summary tools.crossref
vocabs vocabs.files vocabs.hierarchy vocabs.loader
vocabs.metadata ;
help.topics io io.backend io.files io.launcher io.pathnames
kernel lexer math namespaces parser prettyprint sequences
source-files source-files.errors splitting strings summary
tools.crossref vocabs vocabs.files vocabs.hierarchy
vocabs.loader vocabs.metadata ;
FROM: vocabs => vocab-name >vocab-link ;
IN: editors
TUPLE: no-edit-hook ;
M: no-edit-hook summary
drop "You must load one of the below vocabularies before using editor integration:" ;
SYMBOL: edit-hook
SYMBOL: editor-class
: available-editors ( -- seq )
"editors" child-vocab-names ;
@ -23,14 +18,20 @@ SYMBOL: edit-hook
available-editors
[ [ "Load " prepend ] keep ] { } map>assoc ;
: no-edit-hook ( -- )
\ no-edit-hook new
editor-restarts throw-restarts
require ;
HOOK: editor-command editor-class ( file line -- command )
HOOK: editor-detached? editor-class ( -- ? )
M: object editor-detached? t ;
: run-and-wait-for-editor ( command -- )
<process>
swap >>command
editor-detached? >>detached
run-process dup status>> { 0 f } member?
[ drop ] [ process-failed ] if ;
: edit-location ( file line -- )
[ absolute-path ] dip edit-hook get-global
[ call( file line -- ) ] [ no-edit-hook edit-location ] if* ;
[ absolute-path ] dip
editor-command [ run-and-wait-for-editor ] when* ;
ERROR: cannot-find-source definition ;
@ -96,4 +97,3 @@ M: string edit edit-vocab ;
: edit-summary ( vocab -- )
dup vocab-summary-path vocab-append-path 1 edit-location ;

View File

@ -1,17 +1,19 @@
USING: definitions kernel parser words sequences math.parser
namespaces editors io.launcher windows.shell32 io.files
io.directories.search.windows strings unicode.case make ;
USING: combinators.short-circuit editors io.standard-paths
kernel make namespaces ;
IN: editors.editpadlite
SINGLETON: editpadlite
editpadlite editor-class set-global
: editpadlite-path ( -- path )
\ editpadlite-path get-global [
"JGsoft" [ >lower "editpadlite.exe" tail? ] find-in-program-files
[ "editpadlite.exe" ] unless*
{
[ { "Just Great Software" "JGsoft" } "editpadlite.exe" find-in-applications ]
[ { "Just Great Software" "JGsoft" } "editpadlite7.exe" find-in-applications ]
[ "editpadlite7.exe" ]
} 0||
] unless* ;
: editpadlite ( file line -- )
[
editpadlite-path , drop ,
] { } make run-detached drop ;
[ editpadlite ] edit-hook set-global
M: editpadlite editor-command
drop
[ editpadlite-path , , ] { } make ;

View File

@ -1,17 +1,21 @@
USING: definitions kernel parser words sequences math.parser
namespaces editors io.launcher windows.shell32 io.files
io.directories.search.windows strings unicode.case make ;
USING: combinators.short-circuit editors io.standard-paths
kernel make math.parser namespaces sequences ;
IN: editors.editpadpro
SINGLETON: editpadpro
editpadpro editor-class set-global
: editpadpro-path ( -- path )
\ editpadpro-path get-global [
"JGsoft" [ >lower "editpadpro.exe" tail? ] find-in-program-files
[ "editpadpro.exe" ] unless*
{
[ { "Just Great Software" "JGsoft" } "editpadpro.exe" find-in-applications ]
[ { "Just Great Software" "JGsoft" } "editpadpro7.exe" find-in-applications ]
[ "editpadpro7.exe" ]
} 0||
] unless* ;
: editpadpro ( file line -- )
M: editpadpro editor-command ( file line -- command )
[
editpadpro-path , number>string "/l" prepend , ,
] { } make run-detached drop ;
] { } make ;
[ editpadpro ] edit-hook set-global

View File

@ -3,15 +3,16 @@ namespaces sequences windows.shell32 make
io.directories.search.windows ;
IN: editors.editplus
SINGLETON: editplus
editplus editor-class set-global
: editplus-path ( -- path )
\ editplus-path get-global [
"EditPlus 2" [ "editplus.exe" tail? ] find-in-program-files
[ "editplus.exe" ] unless*
] unless* ;
: editplus ( file line -- )
M: editplus editor-command ( file line -- command )
[
editplus-path , "-cursor" , number>string , ,
] { } make run-detached drop ;
[ editplus ] edit-hook set-global
] { } make ;

View File

@ -3,13 +3,16 @@ math.parser namespaces editors make system combinators.short-circuit
fry threads vocabs.loader ;
IN: editors.emacs
SINGLETON: emacsclient
emacsclient editor-class set-global
SYMBOL: emacsclient-path
HOOK: default-emacsclient os ( -- path )
M: object default-emacsclient ( -- path ) "emacsclient" ;
: emacsclient ( file line -- )
M: emacsclient editor-command ( file line -- command )
[
{
[ emacsclient-path get-global ]
@ -24,6 +27,4 @@ M: object default-emacsclient ( -- path ) "emacsclient" ;
: emacs ( word -- )
where first2 emacsclient ;
[ emacsclient ] edit-hook set-global
os windows? [ "editors.emacs.windows" require ] when

View File

@ -3,15 +3,16 @@ namespaces sequences windows.shell32 make
io.directories.search.windows ;
IN: editors.emeditor
SINGLETON: emeditor
emeditor editor-class set-global
: emeditor-path ( -- path )
\ emeditor-path get-global [
"EmEditor" [ "EmEditor.exe" tail? ] find-in-program-files
[ "EmEditor.exe" ] unless*
] unless* ;
: emeditor ( file line -- )
M: emeditor editor-command ( file line -- command )
[
emeditor-path , "/l" , number>string , ,
] { } make run-detached drop ;
[ emeditor ] edit-hook set-global
] { } make ;

View File

@ -4,16 +4,18 @@ USING: editors io.files io.launcher kernel math.parser make
namespaces sequences windows.shell32 io.directories.search.windows ;
IN: editors.etexteditor
SINGLETON: etexteditor
etexteditor editor-class set-global
: etexteditor-path ( -- str )
\ etexteditor-path get-global [
"e" [ "e.exe" tail? ] find-in-program-files
[ "e" ] unless*
] unless* ;
: etexteditor ( file line -- )
M: etexteditor editor-command ( file line -- command )
[
etexteditor-path ,
[ , ] [ "--line" , number>string , ] bi*
] { } make run-detached drop ;
] { } make ;
[ etexteditor ] edit-hook set-global

View File

@ -4,14 +4,15 @@ USING: editors io.launcher kernel make math.parser namespaces
sequences ;
IN: editors.gedit
SINGLETON: gedit
gedit editor-class set-global
: gedit-path ( -- path )
\ gedit-path get-global [
"gedit"
] unless* ;
: gedit ( file line -- )
M: gedit editor-command ( file line -- command )
[
gedit-path , number>string "+" prepend , ,
] { } make run-detached drop ;
[ gedit ] edit-hook set-global
] { } make ;

View File

@ -1,18 +1,18 @@
USING: editors.vim io.backend kernel namespaces system
vocabs.loader ;
vocabs.loader editors ;
IN: editors.gvim
! This code builds on the code in editors.vim; see there for
! more information.
SINGLETON: gvim
gvim vim-editor set-global
TUPLE: gvim < vim ;
T{ gvim } editor-class set-global
HOOK: find-gvim-path io-backend ( -- path )
M: object find-gvim-path f ;
M: gvim find-vim-path find-gvim-path "gvim" or ;
M: gvim vim-detached? t ;
M: gvim vim-ui? t ;
M: gvim editor-detached? t ;
os windows? [ "editors.gvim.windows" require ] when

View File

@ -1,46 +1,33 @@
! Copyright (C) 2004, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays editors io io.binary io.encodings.ascii
io.encodings.binary io.encodings.utf8 io.files io.files.private
io.pathnames io.sockets io.streams.byte-array kernel locals
math.parser namespaces prettyprint sequences ;
USING: combinators.short-circuit editors io.pathnames
io.standard-paths kernel make math.parser namespaces sequences
system ;
IN: editors.jedit
: jedit-server-file ( -- server-files )
home ".jedit/server" append-path
home "Library/jEdit/server" append-path 2array
[ exists? ] find nip ;
SINGLETON: jedit
jedit editor-class set-global
: jedit-server-info ( server-file -- port auth )
ascii [
readln drop
readln string>number
readln string>number
] with-file-reader ;
ERROR: jedit-not-found ;
: make-jedit-request ( files -- code )
utf8 [
"EditServer.handleClient(false,false,false," write
cwd pprint
"," write
"new String[] {" write
[ pprint "," write ] each
"null});\n" write
] with-byte-writer ;
HOOK: find-jedit-path os ( -- path )
:: send-jedit-request ( request -- )
jedit-server-file jedit-server-info :> ( port auth )
"localhost" port <inet> binary [
auth 4 >be write
request length 2 >be write
request write
] with-client ;
M: object find-jedit-path f ;
: jedit-location ( file line -- )
number>string "+line:" prepend 2array
make-jedit-request send-jedit-request ;
M: macosx find-jedit-path
"org.gjt.sp.jedit" find-native-bundle
dup [ "Contents/MacOS/jedit" append-path ] when ;
: jedit-file ( file -- )
1array make-jedit-request send-jedit-request ;
M: windows find-jedit-path
{ "jedit" } "jedit.exe" find-in-applications ;
: jedit-path ( -- path )
\ jedit-path get-global [
find-jedit-path "jedit" or
] unless* ;
[ jedit-location ] edit-hook set-global
M: jedit editor-command ( file line -- command/f )
[
find-jedit-path ,
[ , ] [ number>string "+line:" prepend , ] bi*
] { } make ;

View File

@ -1,9 +1,9 @@
USING: core-foundation.launch-services editors.vim io.pathnames
io.standard-paths kernel namespaces ;
USING: core-foundation.launch-services editors editors.vim
io.pathnames io.standard-paths kernel namespaces ;
IN: editors.macvim
SINGLETON: macvim
macvim \ vim-editor set-global
TUPLE: macvim < vim ;
T{ macvim } \ editor-class set-global
: find-macvim-bundle-path ( -- path/f )
"org.vim.MacVim" find-native-bundle [
@ -12,8 +12,7 @@ macvim \ vim-editor set-global
f
] if* ;
M: macvim find-vim-path
find-macvim-bundle-path "mvim" or ;
M: macvim find-vim-path find-macvim-bundle-path ;
M: macvim vim-detached? t ;
M: macvim vim-ui? t ;
M: macvim editor-detached? t ;

View File

@ -5,14 +5,14 @@ math.parser namespaces sequences io.files arrays windows.shell32
io.directories.search ;
IN: editors.notepad
SINGLETON: notepad
notepad editor-class set-global
: notepad-path ( -- path )
\ notepad-path get [
windows-directory t
[ "notepad.exe" tail? ] find-file
] unless* ;
: notepad ( file line -- )
drop notepad-path swap 2array run-detached drop ;
[ notepad ] edit-hook set-global
M: notepad editor-command ( file line -- command )
drop [ notepad-path ] dip 2array ;

View File

@ -2,16 +2,17 @@ USING: editors io.files io.launcher kernel math.parser
namespaces sequences windows.shell32 make io.pathnames ;
IN: editors.notepad2
SINGLETON: notepad2
notepad2 editor-class set-global
: notepad2-path ( -- path )
\ notepad2-path get-global [
windows-directory "system32\\notepad.exe" append-path
[ "notepad.exe" ] unless*
] unless* ;
: notepad2 ( file line -- )
M: notepad2 editor-command ( file line -- command )
[
notepad2-path ,
"/g" , number>string , ,
] { } make run-detached drop ;
[ notepad2 ] edit-hook set-global
] { } make ;

View File

@ -2,16 +2,17 @@ USING: editors io.files io.launcher kernel math.parser
namespaces sequences io.directories.search.windows make ;
IN: editors.notepadpp
SINGLETON: notepadpp
notepadpp editor-class set-global
: notepadpp-path ( -- path )
\ notepadpp-path get-global [
"notepad++" [ "notepad++.exe" tail? ] find-in-program-files
[ "notepad++.exe" ] unless*
] unless* ;
: notepadpp ( file line -- )
M: notepadpp editor-command ( file line -- command )
[
notepadpp-path ,
"-n" swap number>string append , ,
] { } make run-detached drop ;
[ notepadpp ] edit-hook set-global
number>string "-n" prepend , ,
] { } make ;

View File

@ -5,6 +5,9 @@ USING: io.files io.launcher kernel namespaces io.directories.search.windows
math math.parser editors sequences make unicode.case ;
IN: editors.scite
SINGLETON: scite
scite editor-class set-global
: scite-path ( -- path )
\ scite-path get-global [
"Scintilla Text Editor"
@ -17,15 +20,10 @@ IN: editors.scite
[ "scite.exe" ] unless*
] unless* ;
: scite-command ( file line -- cmd )
M: scite editor-command ( file line -- cmd )
swap
[
scite-path ,
,
number>string "-goto:" prepend ,
] { } make ;
: scite ( file line -- )
scite-command run-detached drop ;
[ scite ] edit-hook set-global

View File

@ -2,16 +2,17 @@ USING: editors io.files io.launcher kernel math.parser
namespaces sequences io.directories.search.windows make ;
IN: editors.ted-notepad
SINGLETON: ted-notepad
ted-notepad editor-class set-global
: ted-notepad-path ( -- path )
\ ted-notepad-path get-global [
"TED Notepad" [ "TedNPad.exe" tail? ] find-in-program-files
[ "TedNPad.exe" ] unless*
] unless* ;
: ted-notepad ( file line -- )
M: ted-notepad editor-command ( file line -- command )
[
ted-notepad-path ,
number>string "/l" prepend , ,
] { } make run-detached drop ;
[ ted-notepad ] edit-hook set-global
] { } make ;

View File

@ -2,9 +2,9 @@ USING: definitions io.launcher kernel math math.parser parser
namespaces prettyprint editors make ;
IN: editors.textedit
: textedit ( file line -- )
drop
[ "open" , "-a" , "TextEdit", , ] { } make
run-detached drop ;
SINGLETON: textedit
textedit editor-class set-global
[ textedit ] edit-hook set-global
M: textedit editor-command ( file line -- command )
drop
[ "open" , "-a" , "TextEdit", , ] { } make ;

View File

@ -2,8 +2,8 @@ USING: definitions io.launcher kernel math math.parser parser
namespaces prettyprint editors make ;
IN: editors.textmate
: textmate ( file line -- )
[ "mate" , "-a" , "-l" , number>string , , ] { } make
run-detached drop ;
SINGLETON: textmate
textmate editor-class set-global
[ textmate ] edit-hook set-global
M: textmate editor-command ( file line -- command )
[ "mate" , "-a" , "-l" , number>string , , ] { } make ;

View File

@ -3,15 +3,16 @@ namespaces sequences make io.directories.search
io.directories.search.windows ;
IN: editors.textpad
SINGLETON: textpad
textpad editor-class set-global
: textpad-path ( -- path )
\ textpad-path get-global [
"TextPad 5" [ "TextPad.exe" tail? ] find-in-program-files
[ "TextPad.exe" ] unless*
] unless* ;
: textpad ( file line -- )
M: textpad editor-command ( file line -- command )
[
textpad-path , [ , ] [ number>string "(" ",0)" surround , ] bi*
] { } make run-detached drop ;
[ textpad ] edit-hook set-global
] { } make ;

View File

@ -4,10 +4,8 @@ USING: definitions io.launcher kernel parser words sequences
math math.parser namespaces editors make ;
IN: editors.textwrangler
: tw ( file line -- )
[ "edit +" % # " " % % ] "" make run-process drop ;
SINGLETON: textwrangler
textwrangler editor-class set-global
: tw-word ( word -- )
where first2 tw ;
[ tw ] edit-hook set-global
M: textwrangler editor-command ( file line -- command )
[ "edit +" % # " " % % ] "" make ;

View File

@ -2,16 +2,16 @@ USING: editors io.files io.launcher kernel math.parser
namespaces sequences io.directories.search.windows make ;
IN: editors.ultraedit
SINGLETON: ultraedit
ultraedit editor-class set-global
: ultraedit-path ( -- path )
\ ultraedit-path get-global [
"IDM Computer Solutions" [ "uedit32.exe" tail? ] find-in-program-files
[ "uedit32.exe" ] unless*
] unless* ;
: ultraedit ( file line -- )
M: ultraedit editor-command ( file line -- command )
[
ultraedit-path , [ swap % "/" % # "/1" % ] "" make ,
] { } make run-detached drop ;
[ ultraedit ] edit-hook set-global
] { } make ;

View File

@ -5,8 +5,6 @@ IN: editors.vim
ABOUT: { "vim" "vim" }
ARTICLE: { "vim" "vim" } "Vim support"
"This module makes the " { $link edit } " word work with Vim by setting the " { $link edit-hook } " global variable to call " { $link vim } "."
$nl
"The " { $link vim-path } " variable contains the name of the vim executable. The default " { $link vim-path } " is " { $snippet "\"vim\"" } ". Which is not very useful, as it starts vim in the same terminal where you started factor."
{ $list
{ "If you want to use gvim instead or are on a Windows platform use " { $vocab-link "editors.gvim" } "." }

View File

@ -1,33 +1,26 @@
USING: editors io.backend io.launcher kernel make math.parser
namespaces sequences strings system vocabs.loader ;
namespaces sequences strings system vocabs.loader math ;
IN: editors.vim
SYMBOL: vim-editor
SINGLETON: vim
\ vim vim-editor set-global
TUPLE: vim ;
T{ vim } editor-class set-global
SYMBOL: vim-path
HOOK: find-vim-path vim-editor ( -- path )
HOOK: vim-detached? vim-editor ( -- detached? )
HOOK: vim-ui? vim-editor ( -- ui? )
M: vim find-vim-path "vim" ;
M: vim vim-detached? f ;
HOOK: find-vim-path editor-class ( -- path )
HOOK: vim-ui? editor-class ( -- ? )
M: vim vim-ui? f ;
M: vim find-vim-path "vim" ;
: actual-vim-path ( -- path )
\ vim-path get-global [ find-vim-path ] unless* ;
: vim-command ( file line -- command )
M: vim editor-command ( file line -- command )
[
actual-vim-path dup string? [ , ] [ % ] if
vim-ui? [ "-g" , ] when
[ , ] [ number>string "+" prepend , ] bi*
] { } make ;
: vim ( file line -- )
vim-command vim-detached? [ run-detached ] [ run-process ] if drop ;
M: vim editor-detached? f ;
[ vim ] edit-hook set-global

View File

@ -1,14 +1,13 @@
USING: editors io.launcher kernel io.directories.search.windows
math.parser namespaces sequences io.files arrays ;
USING: arrays editors io.standard-paths kernel namespaces ;
IN: editors.wordpad
SINGLETON: wordpad
wordpad editor-class set-global
: wordpad-path ( -- path )
\ wordpad-path get [
"Windows NT\\Accessories"
[ "wordpad.exe" tail? ] find-in-program-files
{ "Windows NT\\Accessories" } "wordpad.exe" find-in-applications
] unless* ;
: wordpad ( file line -- )
drop wordpad-path swap 2array run-detached drop ;
[ wordpad ] edit-hook set-global
M: wordpad editor-command ( file line -- command )
drop [ wordpad-path ] dip 2array ;

View File

@ -150,16 +150,17 @@ M: process-was-killed error.
run-detached
dup detached>> [ dup wait-for-process drop ] unless ;
ERROR: process-failed process code ;
ERROR: process-failed process ;
M: process-failed error.
dup "Process exited with error code " write code>> . nl
"Launch descriptor:" print nl
process>> . ;
[
"Process exited with error code " write process>> status>> . nl
"Launch descriptor:" print nl
] [ process>> . ] bi ;
: wait-for-success ( process -- )
dup wait-for-process dup 0 =
[ 2drop ] [ process-failed ] if ;
dup wait-for-process 0 =
[ drop ] [ process-failed ] if ;
: try-process ( desc -- )
run-process wait-for-success ;

View File

@ -6,16 +6,18 @@ IN: io.standard-paths
HOOK: find-native-bundle os ( string -- path )
HOOK: find-path* os ( string -- path/f )
HOOK: find-in-path* os ( string -- path/f )
: find-path ( string -- path/f )
HOOK: find-in-applications os ( directories filename -- path )
: find-in-path ( string -- path/f )
[ f ]
[ [ find-path* ] keep over [ append-path ] [ 2drop f ] if ]
[ [ find-in-path* ] keep over [ append-path ] [ 2drop f ] if ]
if-empty ;
os {
{ [ dup macosx? ] [ drop "io.standard-paths.macosx" require ] }
{ [ dup unix? ] [ drop "io.standard-paths.unix" require ] }
{ [ dup windows? ] [ "drop io.standard-paths.windows" require ] }
{ [ dup windows? ] [ drop "io.standard-paths.windows" require ] }
} cond

View File

@ -4,7 +4,7 @@ USING: environment fry io.files io.pathnames io.standard-paths
kernel sequences splitting system ;
IN: io.standard-paths.unix
M: unix find-path*
M: unix find-in-path*
[ "PATH" os-env ":" split ] dip
'[ _ append-path exists? ] find nip ;

View File

@ -0,0 +1 @@
windows

View File

@ -0,0 +1,7 @@
! Copyright (C) 2011 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: io.standard-paths io.standard-paths.windows sequences
tools.test ;
IN: io.standard-paths.windows.tests
[ t ] [ "cmd.exe" find-in-path "cmd.exe" tail? ] unit-test

View File

@ -0,0 +1,15 @@
! Copyright (C) 2011 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: environment fry io.directories.search.windows io.files
io.pathnames io.standard-paths kernel sequences splitting
system unicode.case ;
IN: io.standard-paths.windows
M: windows find-in-applications
'[ [ >lower _ tail? ] find-in-program-files ] map
sift ?first ;
M: windows find-in-path*
[ "PATH" os-env ";" split ] dip
'[ _ append-path exists? ] find nip ;