Implement io.standard-paths on Windows.
{ $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" }
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" } "." } ;
! 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 ;
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 ;
: edit-summary ( vocab -- )
dup vocab-summary-path vocab-append-path 1 edit-location ;
-
-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 ;
-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
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 ;
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 ]
: emacs ( word -- )
where first2 emacsclient ;
-[ emacsclient ] edit-hook set-global
-
os windows? [ "editors.emacs.windows" require ] when
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 ;
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
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 ;
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
! 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 ;
-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 [
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 ;
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 ;
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 ;
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 ;
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"
[ "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
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 ;
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 ;
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
\ No newline at end of file
+M: textmate editor-command ( file line -- command )
+ [ "mate" , "-a" , "-l" , number>string , , ] { } make ;
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 ;
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 ;
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 ;
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" } "." }
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
-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 ;
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 ;
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
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 ;
--- /dev/null
+windows
\ No newline at end of file
--- /dev/null
+! 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
--- /dev/null
+! 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 ;
+