package git include GitBehaviour.feather include GitStatus.feather class GitFile( val file : File, val folder : File ) { } class Git : SimpleComponent(), TextToContexts { /** * Write the commit message in this file. */ class var commitFilename = ".commit.txt" /** * If the commitFile doesn't exist, should we create it? */ class var autoCreateCommitFile = true class val GIT_FILE = "GitFile" // ==== Register ==== override meth register() { registerTextSelectionToContexts() val forNone= SimpleFeatureSet( Context.NONE ).apply { val openGit = Action( "Git", ::openGitAction ).icon("git") menus( MenuFeature( "Project", openGit ) ) toolbar( spacer, openGit ) } val forGitFile = SimpleFeatureSet( GIT_FILE ).apply { val checkout = contextAction( "Checkout", ::confirmCheckoutAction ) contextMenu( checkout) } val forTextFile = SimpleFeatureSet( Context.TEXT_FILE ).apply { val diff = contextAction( "Diff", ::diffFileAction ) val diffTool = contextAction( "Diff Tool", ::diffToolFileAction ) contextMenu( diff, diffTool ) } add( forNone ) add( forGitFile ) add( forTextFile ) } // ==== Project Actions ==== func openGitAction() { openGit( projectFolder() ) } // ==== GitFile Actions ==== func diffFileAction( context : Context ) { val file = context.value as File $( git diff '${file}' ) .dir( file.parentFile ) .runToTextBehaviour( "git diff" ).openTab() } func diffToolFileAction( context : Context ) { val file = context.value as File $( git difftool '${file}' & ) .dir( file.parentFile ) .run() } func confirmCheckoutAction( context : Context ) { val gitFile = context.value as GitFile val file = gitFile.file confirm( "Checkout?", "Checkout file : ${file.name}", ::checkout.curry(file) ) } // ==== API ===== func openGit( folder : File ) { GitBehaviour( folder ).openBehaviour() } func checkout( file : File ) { $( git checkout '${file}' ).dir( file.parentFile ).run() } override meth selectionToContexts( sourceContexts : List, selection : String ) : List = null /** * A special case for .gitignore. Unlike BasicFile, the text is always treated as a path relative to * .gitignore's parent folder. * Also, we compare the whole of `line`, and ignore `column`. */ override meth caretToContexts( sourceContexts : List, line : String, column : int) : List { for (context in sourceContexts) { if (context.type == Context.FILE) { val textFile = context.value as File if (textFile.name == ".gitignore") { val relativeFile = File( textFile.parentFile, line ) if ( relativeFile.exists() ) { return contextsForFile(relativeFile) } } } } return null } }