diff --git a/plugins/filefinder/facebox.css b/plugins/filefinder/facebox.css
new file mode 100644
index 000000000..7f165dcc5
--- /dev/null
+++ b/plugins/filefinder/facebox.css
@@ -0,0 +1,79 @@
+#facebox {
+ position:absolute;
+ top:0;
+ left:0;
+ z-index:100;
+ text-align:left;
+}
+
+#facebox .popup{
+ position:relative;
+ border:3px solid rgba(0,0,0,0);
+ -webkit-border-radius:5px;
+ -moz-border-radius:5px;
+ border-radius:5px;
+ -webkit-box-shadow:0 0 18px rgba(0,0,0,0.4);
+ -moz-box-shadow:0 0 18px rgba(0,0,0,0.4);
+ box-shadow:0 0 18px rgba(0,0,0,0.4);
+}
+
+#facebox .content{
+ display:table;
+ width:370px;
+ padding:10px;
+ background:#fff;
+ -webkit-border-radius:4px;
+ -moz-border-radius:4px;
+ border-radius:4px;
+}
+
+#facebox .content > p:first-child{
+ margin-top:0;
+}
+#facebox .content > p:last-child{
+ margin-bottom:0;
+}
+
+#facebox .close{
+ position:absolute;
+ top:5px;
+ right:5px;
+ padding:2px;
+ width:8px;
+ height:8px;
+ opacity:0.3;
+ z-index:10000;
+}
+#facebox .close:hover{
+ opacity:1.0;
+ text-decoration:none;
+}
+
+#facebox .fb-loading{
+ height:32px;
+ text-align:center;
+}
+
+#facebox img{
+ display:block;
+ border:0;
+ margin:0 auto;
+}
+
+#facebox-overlay{
+ position:fixed;
+ top:0px;
+ left:0px;
+ height:100%;
+ width:100%;
+ background-color:#000;
+ z-index:99;
+ display:none;
+}
+
+#facebox .close.inline{
+ background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNpiYGBgEAXivUCsxYAAukC8CyoHlvwPxK+gErpQ9n+oHIrAKzS2LrKRMAkUSSYG3OAvNt1YrSDoSJg3ddG8CRITBQgwALGIIG7dYZgsAAAAAElFTkSuQmCC") top right no-repeat;
+}
+#facebox .fb-loading{
+ background:center url("data:image/gif;base64,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") no-repeat;
+}
diff --git a/plugins/filefinder/facebox.js b/plugins/filefinder/facebox.js
new file mode 100644
index 000000000..6a8b4aa1d
--- /dev/null
+++ b/plugins/filefinder/facebox.js
@@ -0,0 +1,154 @@
+// facebox 2.0
+// MIT Licensed
+// https://github.com/defunkt/facebox
+(function($){
+
+ // jQuery plugin
+ //
+ // $('a[rel*=facebox]').facebox()
+ // $('.js-add-cc').facebox(function() {
+ // $('#facebox .js-thanks, #facebox .rule:first').hide()
+ // })
+ $.fn.facebox = function( callback ) {
+ return this.live('click.facebox', function(){
+ // rel="facebox.my-class" adds my-class to '#facebox .content'
+ var contentClass = ( /facebox\.(\S+)/.exec(this.rel) || [] )[1]
+
+ if ( callback )
+ $(document).one('show.facebox', callback)
+
+ $.facebox({ div: this.href }, contentClass)
+
+ return false
+ })
+ }
+
+ // The Real Deal
+ //
+ // $.facebox('Cool!')
+ $.facebox = function( data, contentClass ) {
+ if ( $('#facebox .fb-loading').length == 0 ) {
+ show('
')
+ $(document).trigger('loading.facebox')
+ }
+
+ $('#facebox .content').addClass(contentClass)
+
+ if ( !data ) return
+
+ // $.facebox('#info') => $.facebox({div: '#info'})
+ if ( /^#/.test(data) )
+ data = { div: data }
+
+ // $.facebox('/some/url') => $.facebox({ajax: '/some/url' })
+ if ( /^\//.test(data) )
+ data = { ajax: data }
+
+ var href = data.ajax || data.image || data.div
+ if ( href ) {
+ // div
+ var div = /#.+$/.exec(href)
+ if ( div ) {
+ show( $(div[0]).html() )
+
+ // image
+ } else if ( data.image || /\.(png|jpe?g|gif)(\?\S*)?$/i.test(href) ) {
+ var image = new Image
+ image.onload = function() {
+ show('
')
+ }
+ image.src = href
+
+ // ajax
+ } else {
+ $.get(href, show)
+ }
+ }
+
+ else if ( $.isFunction(data) )
+ data()
+ else
+ show(data)
+ }
+
+
+ //
+ // Default settings
+ //
+
+ var settings = $.facebox.settings = {
+ opacity : 0.2,
+ overlay : true,
+ faceboxHTML: ''
+ }
+
+
+ //
+ // Methods
+ //
+
+ // Close Facebox
+ var close = $.facebox.close = function(){
+ $(document).trigger('close.facebox')
+ return false
+ }
+
+ // Show the Facebox
+ function show( data ) {
+ // Dim the lights
+ if ( settings.overlay && !$('#facebox-overlay').is(':visible') ) {
+ $('body').append('')
+
+ $('#facebox-overlay')
+ .css('opacity', settings.opacity)
+ .fadeIn(200)
+ .click(close)
+ }
+
+ // Create the Facebox
+ if ( $('#facebox').length == 0 ) {
+ $('body').append( $(settings.faceboxHTML).hide() )
+ $(document).trigger('setup.facebox')
+ }
+
+ // Make that money
+ $('#facebox .content').html(data).show()
+
+ // Position Facebox based on the user's scroll
+ $('#facebox').show().css({
+ top: $(window).scrollTop() + ($(window).height() / 10),
+ left: $(window).width() / 2 - ($('#facebox .popup').outerWidth() / 2)
+ })
+
+ // Fire events if we're not loading.
+ if ( $('.fb-loading:visible').length == 0 )
+ $(document).trigger('show.facebox').trigger('reveal.facebox')
+ }
+
+
+ //
+ // Bindings
+ //
+
+ $(document).bind('close.facebox', function(){
+ $('#facebox').fadeOut(function(){
+ $(this).remove()
+ $(document).trigger('afterClose.facebox')
+ })
+
+ $('#facebox-overlay').fadeOut(200, function(){
+ $(this).remove()
+ })
+ })
+
+ $(document).one('show.facebox', function(){
+ // Click on close image = Close Facebox
+ $('#facebox .close').live('click', close)
+
+ // ESC = Close Facebox
+ $(document).bind('keydown.facebox', function(e){
+ if ( e.keyCode == 27 && $('#facebox:visible').length ) close()
+ return true
+ })
+ })
+})(jQuery);
diff --git a/plugins/filefinder/filefinder.coffee b/plugins/filefinder/filefinder.coffee
new file mode 100644
index 000000000..e818ca760
--- /dev/null
+++ b/plugins/filefinder/filefinder.coffee
@@ -0,0 +1,106 @@
+$ = require 'jquery'
+_ = require 'underscore'
+
+{activeWindow} = require 'app'
+File = require 'fs'
+Pane = require 'pane'
+
+jQuery = $
+facebox = eval File.read require.resolve 'filefinder/facebox'
+require 'filefinder/stringscore'
+
+module.exports =
+class Filefinder extends Pane
+ showing: false
+ files: []
+
+ html: require "filefinder/filefinder.html"
+
+ keymap:
+ 'Command-T': 'toggle'
+ # really wish i could put up/down keyboad shortcuts here
+ # and have them activated when the filefinder is open
+
+ initialize: ->
+ $('#filefinder input').live 'keydown', @onKeydown
+
+ css = File.read require.resolve 'filefinder/facebox.css'
+ head = $('head')[0]
+ style = document.createElement 'style'
+ rules = document.createTextNode css
+ style.type = 'text/css'
+ style.appendChild rules
+ head.appendChild style
+
+ onKeydown: (e) =>
+ keys = up: 38, down: 40, enter: 13
+
+ if e.keyCode is keys.enter
+ @openSelected()
+ else if e.keyCode is keys.up
+ @moveUp()
+ else if e.keyCode is keys.down
+ @moveDown()
+ else
+ @filterFiles()
+
+ toggle: ->
+ if @showing
+ $.facebox.close()
+ else
+ @showFinder()
+ @showing = not @showing
+
+ showFinder: ->
+ $.facebox @html
+ @files = []
+ for file in activeWindow.project.paths()
+ @files.push file.replace "#{activeWindow.project.dir}/", ''
+ @filterFiles()
+
+ findMatchingFiles: (query) ->
+ return [] if not query
+
+ results = []
+ for file in @files
+ score = file.score query
+ if score > 0
+ # Basename matches count for more.
+ if not query.match '/'
+ if name.match '/'
+ score += name.replace(/^.*\//, '').score query
+ else
+ score *= 2
+ results.push [score, file]
+
+ sorted = results.sort (a, b) -> b[0] - a[0]
+ _.map sorted, (el) -> el[1]
+
+ filterFiles: ->
+ if query = $('#filefinder input').val()
+ files = @findMatchingFiles query
+ else
+ files = @files
+ $('#filefinder ul').empty()
+ for file in files[0..10]
+ $('#filefinder ul').append "#{file}"
+ $('#filefinder input').focus()
+ $('#filefinder li:first').addClass 'selected'
+
+ openSelected: ->
+ dir = activeWindow.project.dir
+ file = $('#filefinder .selected').text()
+ activeWindow.open "#{dir}/#{file}"
+ @toggle()
+
+ moveUp: ->
+ selected = $('#filefinder .selected')
+ if selected.prev().length
+ selected.prev().addClass 'selected'
+ selected.removeClass 'selected'
+
+ moveDown: ->
+ selected = $('#filefinder .selected')
+ if selected.next().length
+ selected.next().addClass 'selected'
+ selected.removeClass 'selected'
\ No newline at end of file
diff --git a/plugins/filefinder/filefinder.html b/plugins/filefinder/filefinder.html
new file mode 100644
index 000000000..44dff0048
--- /dev/null
+++ b/plugins/filefinder/filefinder.html
@@ -0,0 +1,17 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/filefinder/index.coffee b/plugins/filefinder/index.coffee
new file mode 100644
index 000000000..2983adaa4
--- /dev/null
+++ b/plugins/filefinder/index.coffee
@@ -0,0 +1,3 @@
+exports.Filefinder = Filefinder = require 'filefinder/filefinder'
+
+new Filefinder
\ No newline at end of file
diff --git a/plugins/filefinder/stringscore.js b/plugins/filefinder/stringscore.js
new file mode 100644
index 000000000..f1f9cabfd
--- /dev/null
+++ b/plugins/filefinder/stringscore.js
@@ -0,0 +1,122 @@
+/*!
+ * string_score.js: String Scoring Algorithm 0.1.9
+ *
+ * http://joshaven.com/string_score
+ * https://github.com/joshaven/string_score
+ *
+ * Copyright (C) 2009-2011 Joshaven Potter
+ * Copyright (C) 2010-2011 Yesudeep Mangalapilly
+ * MIT license: http://www.opensource.org/licenses/mit-license.php
+ *
+ * Date: Tue Mar 1 2011
+*/
+
+/**
+ * Scores a string against another string.
+ * 'Hello World'.score('he'); //=> 0.5931818181818181
+ * 'Hello World'.score('Hello'); //=> 0.7318181818181818
+ */
+String.prototype.score = function(abbreviation, fuzziness) {
+ var total_character_score = 0,
+ abbreviation_length = abbreviation.length,
+ string = this,
+ string_length = string.length,
+ start_of_string_bonus,
+ abbreviation_score,
+ fuzzies=1,
+ final_score;
+
+ // If the string is equal to the abbreviation, perfect match.
+ if (string == abbreviation) {return 1.0;}
+
+ // Walk through abbreviation and add up scores.
+ for (var i = 0,
+ character_score/* = 0*/,
+ index_in_string/* = 0*/,
+ c/* = ''*/,
+ index_c_lowercase/* = 0*/,
+ index_c_uppercase/* = 0*/,
+ min_index/* = 0*/;
+ i < abbreviation_length;
+ ++i) {
+
+ // Find the first case-insensitive match of a character.
+ c = abbreviation[i];
+
+ //index_in_string = __first_valid_index(
+ // string.indexOf(c.toLowerCase()),
+ // string.indexOf(c.toUpperCase())
+ //);
+ // Inlined the above call below.
+ index_c_lowercase = string.indexOf(c.toLowerCase());
+ index_c_uppercase = string.indexOf(c.toUpperCase());
+ min_index = Math.min(index_c_lowercase, index_c_uppercase);
+ index_in_string = (min_index > -1) ?
+ min_index :
+ Math.max(index_c_lowercase, index_c_uppercase);
+ // End inlining.
+
+ if (index_in_string === -1) {
+ if (fuzziness) {
+ fuzzies += 1-fuzziness;
+ break;
+ } else {
+ return 0;
+ }
+ } else {
+ character_score = 0.1;
+ }
+
+ // Set base score for matching 'c'.
+
+ // Same case bonus.
+ if (string[index_in_string] === c) {
+ character_score += 0.1;
+ }
+
+ // Consecutive letter & start-of-string Bonus
+ if (index_in_string === 0) {
+ // Increase the score when matching first character of the
+ // remainder of the string
+ character_score += 0.6;
+ if (i === 0) {
+ // If match is the first character of the string
+ // & the first character of abbreviation, add a
+ // start-of-string match bonus.
+ start_of_string_bonus = 1 //true;
+ }
+ }
+
+ // Acronym Bonus
+ // Weighing Logic: Typing the first character of an acronym is as if you
+ // preceded it with two perfect character matches.
+ if (string.charAt(index_in_string - 1) === ' ') {
+ character_score += 0.8; // * Math.min(index_in_string, 5); // Cap bonus at 0.4 * 5
+ }
+
+ // Left trim the already matched part of the string
+ // (forces sequential matching).
+ string = string.substring(index_in_string + 1, string_length);
+
+ total_character_score += character_score;
+ } // end of for loop
+
+ // Uncomment to weigh smaller words higher.
+ // return total_character_score / string_length;
+
+ abbreviation_score = total_character_score / abbreviation_length;
+ //percentage_of_matched_string = abbreviation_length / string_length;
+ //word_score = abbreviation_score * percentage_of_matched_string;
+
+ // Reduce penalty for longer strings.
+ //final_score = (word_score + abbreviation_score) / 2;
+ final_score = ((abbreviation_score * (abbreviation_length / string_length)) + abbreviation_score) / 2;
+
+ final_score = final_score / fuzzies;
+
+ if (start_of_string_bonus && (final_score + 0.15 < 1)) {
+ final_score += 0.15;
+ }
+
+ return final_score;
+};