changeset 4564:ccc005b96103

javascript: added missing helper functions to make templates using codemirror work properly. (Issue #11) * * * imported patch codemirror-whitespacecleanup
author Christian Oyarzun <oyarzun@gmail.com>
date Thu, 13 Nov 2014 10:56:28 -0500
parents c384703b3ae3
children b8efb9a39c73
files kallithea/public/js/base.js kallithea/public/js/codemirror_loadmode.js kallithea/public/js/meta_ext.js kallithea/templates/admin/gists/edit.html kallithea/templates/admin/gists/new.html kallithea/templates/files/files_add.html kallithea/templates/files/files_delete.html kallithea/templates/files/files_edit.html
diffstat 8 files changed, 124 insertions(+), 304 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/public/js/base.js	Thu Nov 13 10:53:38 2014 -0500
+++ b/kallithea/public/js/base.js	Thu Nov 13 10:56:28 2014 -0500
@@ -990,6 +990,8 @@
             indentUnit: 4,
             autofocus: true
         });
+    CodeMirror.modeURL = "/codemirror/mode/%N/%N.js";
+
     $('#reset').click(function(e){
             window.location=resetUrl;
         });
@@ -1012,7 +1014,6 @@
 };
 
 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
-    codeMirrorInstance.setOption("mode", mode);
     CodeMirror.autoLoadMode(codeMirrorInstance, mode);
 }
 
--- a/kallithea/public/js/codemirror_loadmode.js	Thu Nov 13 10:53:38 2014 -0500
+++ b/kallithea/public/js/codemirror_loadmode.js	Thu Nov 13 10:56:28 2014 -0500
@@ -22,7 +22,7 @@
   }
 
   CodeMirror.requireMode = function(mode, cont) {
-    if (typeof mode != "string") mode = mode.name;
+    if (typeof mode != "string") mode = mode.mode;
     if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
     if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
 
@@ -48,7 +48,29 @@
       CodeMirror.requireMode(mode, function() {
         instance.setOption("mode", instance.getOption("mode"));
       });
+    instance.setOption("mode", mode.mime);
   };
+
+  CodeMirror.findExtensionByMode = function(modeInfo) {
+    if (modeInfo.ext) {
+      return modeInfo.ext[0];
+    } else if (modeInfo.mode) {
+      return modeInfo.mode;
+    } else {
+      return "txt";
+    }
+  };
+
+  CodeMirror.getFilenameAndExt = function(filename){
+    var parts = filename.split('.');
+
+    if (parts.length > 1){
+        var ext = parts.pop();
+        var filename = parts.join("");
+    }
+    return {"filename": filename, "ext": ext};
+  };
+
 }());
 
 
--- a/kallithea/public/js/meta_ext.js	Thu Nov 13 10:53:38 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-MIME_TO_EXT = {
-    'application/javascript': ['*.js'],
-    'text/javascript': ['*.js'],
-    'application/json': ['*.json'],
-    'application/postscript': ['*.ps', '*.eps'],
-    'application/x-actionscript': ['*.as'],
-    'application/x-actionscript3': ['*.as'],
-    'application/x-awk': ['*.awk'],
-    'application/x-befunge': ['*.befunge'],
-    'application/x-brainfuck': ['*.bf', '*.b'],
-    'application/x-cheetah': ['*.tmpl', '*.spt'],
-    'application/x-coldfusion': ['*.cfm', '*.cfml', '*.cfc'],
-    'application/x-csh': ['*.tcsh', '*.csh'],
-    'application/x-dos-batch': ['*.bat', '*.cmd'],
-    'application/x-ecl': ['*.ecl'],
-    'application/x-evoque': ['*.evoque'],
-    'application/x-fantom': ['*.fan'],
-    'application/x-genshi': ['*.kid'],
-    'application/x-gettext': ['*.pot', '*.po'],
-    'application/x-jsp': ['*.jsp'],
-    'application/x-mako': ['*.mao'],
-    'application/x-mason': ['*.m', '*.mhtml', '*.mc', '*.mi', 'autohandler', 'dhandler'],
-    'application/x-myghty': ['*.myt', 'autodelegate'],
-    'application/x-php': ['*.phtml'],
-    'application/x-pypylog': ['*.pypylog'],
-    'application/x-qml': ['*.qml'],
-    'application/x-sh': ['*.sh', '*.ksh', '*.bash', '*.ebuild', '*.eclass', '.bashrc', 'bashrc', '.bash_*', 'bash_*'],
-    'application/x-sh-session': ['*.shell-session'],
-    'application/x-shell-session': ['*.sh-session'],
-    'application/x-smarty': ['*.tpl'],
-    'application/x-ssp': ['*.ssp'],
-    'application/x-troff': ['*.[1234567]', '*.man'],
-    'application/x-urbiscript': ['*.u'],
-    'application/xml+evoque': ['*.xml'],
-    'application/xml-dtd': ['*.dtd'],
-    'application/xsl+xml': ['*.xsl', '*.xslt', '*.xpl'],
-    'text/S-plus': ['*.S', '*.R', '.Rhistory', '.Rprofile'],
-    'text/coffeescript': ['*.coffee'],
-    'text/css': ['*.css'],
-    'text/haxe': ['*.hx'],
-    'text/html': ['*.html', '*.htm', '*.xhtml', '*.xslt'],
-    'text/html+evoque': ['*.html'],
-    'text/html+ruby': ['*.rhtml'],
-    'text/idl': ['*.pro'],
-    'text/livescript': ['*.ls'],
-    'text/matlab': ['*.m'],
-    'text/octave': ['*.m'],
-    'text/plain': ['*.txt'],
-    'text/scilab': ['*.sci', '*.sce', '*.tst'],
-    'text/smali': ['*.smali'],
-    'text/x-abap': ['*.abap'],
-    'text/x-ada': ['*.adb', '*.ads', '*.ada'],
-    'text/x-apacheconf': ['.htaccess', 'apache.conf', 'apache2.conf'],
-    'text/x-aspectj': ['*.aj'],
-    'text/x-asymptote': ['*.asy'],
-    'text/x-autohotkey': ['*.ahk', '*.ahkl'],
-    'text/x-autoit': ['*.au3'],
-    'text/x-bmx': ['*.bmx'],
-    'text/x-boo': ['*.boo'],
-    'text/x-c++hdr': ['*.cpp', '*.hpp', '*.c++', '*.h++', '*.cc', '*.hh', '*.cxx', '*.hxx', '*.C', '*.H', '*.cp','*.CPP'],
-    'text/x-c-objdump': ['*.c-objdump'],
-    'text/x-ceylon': ['*.ceylon'],
-    'text/x-chdr': ['*.c', '*.h', '*.idc'],
-    'text/x-clojure': ['*.clj'],
-    'text/x-cmake': ['*.cmake', 'CMakeLists.txt'],
-    'text/x-cobol': ['*.cob', '*.COB', '*.cpy', '*.CPY'],
-    'text/x-common-lisp': ['*.cl', '*.lisp', '*.el'],
-    'text/x-coq': ['*.v'],
-    'text/x-cpp-objdump': ['*.cpp-objdump', '*.c++-objdump', '*.cxx-objdump'],
-    'text/x-crocsrc': ['*.croc'],
-    'text/x-csharp': ['*.cs'],
-    'text/x-cuda': ['*.cu', '*.cuh'],
-    'text/x-cython': ['*.pyx', '*.pxd', '*.pxi'],
-    'text/x-d-objdump': ['*.d-objdump'],
-    'text/x-dart': ['*.dart'],
-    'text/x-dg': ['*.dg'],
-    'text/x-diff': ['*.diff', '*.patch'],
-    'text/x-dsrc': ['*.d', '*.di'],
-    'text/x-duel': ['*.duel', '*.jbst'],
-    'text/x-dylan': ['*.dylan', '*.dyl', '*.intr'],
-    'text/x-dylan-console': ['*.dylan-console'],
-    'text/x-dylan-lid': ['*.lid', '*.hdp'],
-    'text/x-echdr': ['*.ec', '*.eh'],
-    'text/x-elixir': ['*.ex', '*.exs'],
-    'text/x-erl-shellsession': ['*.erl-sh'],
-    'text/x-erlang': ['*.erl', '*.hrl', '*.es', '*.escript'],
-    'text/x-factor': ['*.factor'],
-    'text/x-fancysrc': ['*.fy', '*.fancypack'],
-    'text/x-felix': ['*.flx', '*.flxh'],
-    'text/x-fortran': ['*.f', '*.f90', '*.F', '*.F90'],
-    'text/x-fsharp': ['*.fs', '*.fsi'],
-    'text/x-gas': ['*.s', '*.S'],
-    'text/x-gherkin': ['*.feature'],
-    'text/x-glslsrc': ['*.vert', '*.frag', '*.geo'],
-    'text/x-gnuplot': ['*.plot', '*.plt'],
-    'text/x-gooddata-cl': ['*.gdc'],
-    'text/x-gooddata-maql': ['*.maql'],
-    'text/x-gosrc': ['*.go'],
-    'text/x-gosu': ['*.gs', '*.gsx', '*.gsp', '*.vark'],
-    'text/x-gosu-template': ['*.gst'],
-    'text/x-groovy': ['*.groovy'],
-    'text/x-haml': ['*.haml'],
-    'text/x-haskell': ['*.hs'],
-    'text/x-hybris': ['*.hy', '*.hyb'],
-    'text/x-ini': ['*.ini', '*.cfg'],
-    'text/x-iokesrc': ['*.ik'],
-    'text/x-iosrc': ['*.io'],
-    'text/x-irclog': ['*.weechatlog'],
-    'text/x-jade': ['*.jade'],
-    'text/x-java': ['*.java'],
-    'text/x-java-properties': ['*.properties'],
-    'text/x-julia': ['*.jl'],
-    'text/x-kconfig': ['Kconfig', '*Config.in*', 'external.in*', 'standard-modules.in'],
-    'text/x-koka': ['*.kk', '*.kki'],
-    'text/x-kotlin': ['*.kt'],
-    'text/x-lasso': ['*.lasso', '*.lasso[89]'],
-    'text/x-literate-haskell': ['*.lhs'],
-    'text/x-llvm': ['*.ll'],
-    'text/x-logos': ['*.x', '*.xi', '*.xm', '*.xmi'],
-    'text/x-logtalk': ['*.lgt'],
-    'text/x-lua': ['*.lua', '*.wlua'],
-    'text/x-makefile': ['*.mak', 'Makefile', 'makefile', 'Makefile.*', 'GNUmakefile'],
-    'text/x-minidsrc': ['*.md'],
-    'text/x-markdown': ['*.md'],
-    'text/x-modelica': ['*.mo'],
-    'text/x-modula2': ['*.def', '*.mod'],
-    'text/x-monkey': ['*.monkey'],
-    'text/x-moocode': ['*.moo'],
-    'text/x-moonscript': ['*.moon'],
-    'text/x-nasm': ['*.asm', '*.ASM'],
-    'text/x-nemerle': ['*.n'],
-    'text/x-newlisp': ['*.lsp', '*.nl'],
-    'text/x-newspeak': ['*.ns2'],
-    'text/x-nimrod': ['*.nim', '*.nimrod'],
-    'text/x-nsis': ['*.nsi', '*.nsh'],
-    'text/x-objdump': ['*.objdump'],
-    'text/x-objective-c': ['*.m', '*.h'],
-    'text/x-objective-c++': ['*.mm', '*.hh'],
-    'text/x-objective-j': ['*.j'],
-    'text/x-ocaml': ['*.ml', '*.mli', '*.mll', '*.mly'],
-    'text/x-ooc': ['*.ooc'],
-    'text/x-opa': ['*.opa'],
-    'text/x-openedge': ['*.p', '*.cls'],
-    'text/x-pascal': ['*.pas'],
-    'text/x-perl': ['*.pl', '*.pm'],
-    'text/x-php': ['*.php', '*.php[345]', '*.inc'],
-    'text/x-povray': ['*.pov', '*.inc'],
-    'text/x-powershell': ['*.ps1'],
-    'text/x-prolog': ['*.prolog', '*.pro', '*.pl'],
-    'text/x-python': ['*.py', '*.pyw', '*.sc', 'SConstruct', 'SConscript', '*.tac', '*.sage'],
-    'text/x-python-traceback': ['*.pytb'],
-    'text/x-python3-traceback': ['*.py3tb'],
-    'text/x-r-doc': ['*.Rd'],
-    'text/x-racket': ['*.rkt', '*.rktl'],
-    'text/x-rebol': ['*.r', '*.r3'],
-    'text/x-robotframework': ['*.txt', '*.robot'],
-    'text/x-rpm-spec': ['*.spec'],
-    'text/x-rst': ['*.rst', '*.rest'],
-    'text/x-ruby': ['*.rb', '*.rbw', 'Rakefile', '*.rake', '*.gemspec', '*.rbx', '*.duby'],
-    'text/x-rustsrc': ['*.rs', '*.rc'],
-    'text/x-sass': ['*.sass'],
-    'text/x-scala': ['*.scala'],
-    'text/x-scaml': ['*.scaml'],
-    'text/x-scheme': ['*.scm', '*.ss'],
-    'text/x-scss': ['*.scss'],
-    'text/x-smalltalk': ['*.st'],
-    'text/x-snobol': ['*.snobol'],
-    'text/x-sourcepawn': ['*.sp'],
-    'text/x-sql': ['*.sql'],
-    'text/x-sqlite3-console': ['*.sqlite3-console'],
-    'text/x-squidconf': ['squid.conf'],
-    'text/x-standardml': ['*.sml', '*.sig', '*.fun'],
-    'text/x-systemverilog': ['*.sv', '*.svh'],
-    'text/x-tcl': ['*.tcl'],
-    'text/x-tea': ['*.tea'],
-    'text/x-tex': ['*.tex', '*.aux', '*.toc'],
-    'text/x-typescript': ['*.ts'],
-    'text/x-vala': ['*.vala', '*.vapi'],
-    'text/x-vbnet': ['*.vb', '*.bas'],
-    'text/x-verilog': ['*.v'],
-    'text/x-vhdl': ['*.vhdl', '*.vhd'],
-    'text/x-vim': ['*.vim', '.vimrc', '.exrc', '.gvimrc', '_vimrc', '_exrc', '_gvimrc', 'vimrc', 'gvimrc'],
-    'text/x-windows-registry': ['*.reg'],
-    'text/x-xtend': ['*.xtend'],
-    'text/x-yaml': ['*.yaml', '*.yml'],
-    'text/xml': ['*.xml', '*.xsl', '*.rss', '*.xslt', '*.xsd', '*.wsdl'],
-    'text/xquery': ['*.xqy', '*.xquery', '*.xq', '*.xql', '*.xqm'],
-    'text/apl': [],
-    'text/x-asterisk': [],
-    'text/x-csrc': [],
-    'text/x-c++src': ['*.cpp'],
-    'text/x-coffeescript': ['*.coffee'],
-    'text/x-d': ["*.d"],
-    'text/x-ecl': ['*.ecl'],
-    'text/x-go': ['*.go'],
-    'text/x-haxe': ['*.hx'],
-    'application/x-aspx': ['*.aspx'],
-    'application/x-ejs': [],
-    'message/http': [],
-    'application/x-json': ['*.json'],
-    'application/typescript': ['*.ts'],
-    'jinja2': ['.jinja2'],
-    'text/x-less': ['*.less'],
-    'text/x-livescript': ['*.ls'],
-    'text/mirc': [],
-    'text/n-triples': [],
-    'application/x-httpd-php': ['*.php'],
-    'text/x-pig': [],
-    'text/x-properties': ['*.properties'],
-    'text/x-rsrc': [],
-    'text/x-sh': ['*.sh', '*.ksh', '*.bash', '*.ebuild', '*.eclass', '.bashrc', 'bashrc', '.bash_*', 'bash_*'],
-    'application/sieve': [],
-    'text/x-stsrc': ['*.rs', '*.rc'],
-    'text/x-smarty': ['*.tpl'],
-    'application/x-sparql-query': [],
-    'text/x-mariadb': ['*.sql'],
-    'text/x-stex': [],
-    'text/x-latex': ["*.ltx"],
-    'text/x-tiddlywiki': [],
-    'text/tiki': [],
-    'text/x-vb': ['*.vb'],
-    'text/vbscript': ['*.vb'],
-    'text/velocity': [],
-    'application/xml': ['*.xml', '*.xsl', '*.rss', '*.xslt', '*.xsd', '*.wsdl'],
-    'application/xquery': ['*.xqy', '*.xquery', '*.xq', '*.xql', '*.xqm'],
-    'text/x-z80': [],
-}
--- a/kallithea/templates/admin/gists/edit.html	Thu Nov 13 10:53:38 2014 -0500
+++ b/kallithea/templates/admin/gists/edit.html	Thu Nov 13 10:56:28 2014 -0500
@@ -12,7 +12,6 @@
 <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
 <script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
 <script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
-<script type="text/javascript" src="${h.url('/js/meta_ext.js')}"></script>
 </%def>
 <%def name="css_extra()">
 <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -75,10 +74,7 @@
                     <div style="padding: 10px 10px 10px 26px;color:#666666">
                         <input type="hidden" value="${file.path}" name="org_files">
                         <input id="filename_${h.FID('f',file.path)}" name="files" size="30" type="text" value="${file.path}">
-
-                        <select id="mimetype_${h.FID('f',file.path)}" name="mimetypes">
-                            <option selected="selected" value="plain">${_('plain')}</option>
-                        </select>
+                        <select id="mimetype_${h.FID('f',file.path)}" name="mimetypes"/>
                     </div>
                     <div class="editor_container">
                         <pre id="editor_pre"></pre>
@@ -89,17 +85,23 @@
                 ## dynamic edit box.
                 <script type="text/javascript">
                 var myCodeMirror = initCodeMirror("editor_${h.FID('f',file.path)}", '');
-                CodeMirror.modeURL = "${h.url('/codemirror/mode/%N/%N.js')}";
 
                 //inject new modes
                 var $modes_select = $('#mimetype_${h.FID('f',file.path)}');
                 $modes_select.each(function(){
                     var modes_select = this;
+                    var index = 1;
                     for(var i=0;i<CodeMirror.modeInfo.length;i++) {
                         var m = CodeMirror.modeInfo[i];
                         var opt = new Option(m.name, m.mime);
                         $(opt).attr('mode', m.mode);
-                        modes_select.options[i+1] = opt;
+                        if (m.mime == 'text/plain') {
+                            // default plain text
+                            $(opt).attr('selected', 'selected');
+                            modes_select.options[0] = opt;
+                        } else {
+                            modes_select.options[index++] = opt;
+                        }
                     }
                 });
 
@@ -108,38 +110,34 @@
                 $modes_select.change(function(e){
                     var selected = e.currentTarget;
                     var node = selected.options[selected.selectedIndex];
-                    var mimetype = node.value;
-                    var new_mode = $(node).attr('mode');
-                    setCodeMirrorMode(myCodeMirror, new_mode);
+                    var detected_mode = CodeMirror.findModeByMIME(node.value);
+                    setCodeMirrorMode(myCodeMirror, detected_mode);
 
-                    var proposed_ext = getExtFromMimeType(mimetype);
-                    var file_data = getFilenameAndExt($filename.val());
+                    var proposed_ext = CodeMirror.findExtensionByMode(detected_mode);
+                    var file_data = CodeMirror.getFilenameAndExt($filename.val());
                     var filename = file_data['filename'] || 'filename1';
-                    $(filename_selector).val(filename + proposed_ext);
-                })
+                    $filename.val(filename + '.' + proposed_ext);
+                });
 
                 // on type the new filename set mode
                 $filename.keyup(function(e){
-                    var file_data = getFilenameAndExt(this.value);
+                    var file_data = CodeMirror.getFilenameAndExt(this.value);
                     if(file_data['ext'] != null){
-
-                        var mimetype = getMimeTypeFromExt(file_data['ext']);
-                        var detected_mode = detectCodeMirrorMode(this.value, mimetype);
+                        var detected_mode = CodeMirror.findModeByExtension(file_data['ext']) || CodeMirror.findModeByMIME('text/plain');
 
                         if (detected_mode){
                             setCodeMirrorMode(myCodeMirror, detected_mode);
-                            $modes_select.val(mimetype)
+                            $modes_select.val(detected_mode.mime);
                         }
                     }
-                })
+                });
 
                 // set mode on page load
-                var mimetype = getMimeTypeFromExt("${file.extension}");
-                var detected_mode = detectCodeMirrorMode("${file.path}", mimetype);
+                var detected_mode = CodeMirror.findModeByExtension("${file.extension}");
 
                 if (detected_mode){
                     setCodeMirrorMode(myCodeMirror, detected_mode);
-                    modes_select.val(mimetype)
+                    $modes_select.val(detected_mode.mime);
                 }
 
                 </script>
@@ -170,7 +168,7 @@
                       }
                     }
                   })
-              })
+              });
           </script>
         </div>
     </div>
--- a/kallithea/templates/admin/gists/new.html	Thu Nov 13 10:53:38 2014 -0500
+++ b/kallithea/templates/admin/gists/new.html	Thu Nov 13 10:56:28 2014 -0500
@@ -12,7 +12,6 @@
 <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
 <script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
 <script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
-<script type="text/javascript" src="${h.url('/js/meta_ext.js')}"></script>
 </%def>
 <%def name="css_extra()">
 <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -49,7 +48,7 @@
             <div id="body" class="codeblock">
                 <div style="padding: 10px 10px 10px 26px;color:#666666">
                     ${h.text('filename', size=30, placeholder=_('name this file...'))}
-                    ${h.select('mimetype','plain',[('plain',_('plain'))])}
+                    <select id="mimetype" name="mimetype"/>
                 </div>
                 <div id="editor_container">
                     <pre id="editor_pre"></pre>
@@ -64,17 +63,23 @@
             ${h.end_form()}
             <script type="text/javascript">
             var myCodeMirror = initCodeMirror('editor', '');
-            CodeMirror.modeURL = "${h.url('/codemirror/mode/%N/%N.js')}";
 
             //inject new modes
             var $modes_select = $('#mimetype');
             $modes_select.each(function(){
                 var modes_select = this;
+                var index = 1;
                 for(var i=0;i<CodeMirror.modeInfo.length;i++) {
                     var m = CodeMirror.modeInfo[i];
                     var opt = new Option(m.name, m.mime);
                     $(opt).attr('mode', m.mode);
-                    modes_select.options[i+1] = opt;
+                    if (m.mime == 'text/plain') {
+                        // default plain text
+                        $(opt).attr('selected', 'selected');
+                        modes_select.options[0] = opt;
+                    } else {
+                        modes_select.options[index++] = opt;
+                    }
                 }
             });
 
@@ -83,28 +88,26 @@
             $modes_select.change(function(e){
                 var selected = e.currentTarget;
                 var node = selected.options[selected.selectedIndex];
-                var mimetype = node.value;
-                var new_mode = $(node).attr('mode');
-                setCodeMirrorMode(myCodeMirror, new_mode);
+                var detected_mode = CodeMirror.findModeByMIME(node.value);
+                setCodeMirrorMode(myCodeMirror, detected_mode);
 
-                var proposed_ext = getExtFromMimeType(mimetype);
-                var file_data = getFilenameAndExt($filename.val());
+                var proposed_ext = CodeMirror.findExtensionByMode(detected_mode);
+                var file_data = CodeMirror.getFilenameAndExt($filename.val());
                 var filename = file_data['filename'] || 'filename1';
-                $filename.val(filename + proposed_ext);
+                $filename.val(filename + '.' + proposed_ext);
             });
 
             // on type the new filename set mode
             $filename.keyup(function(e){
-                var file_data = getFilenameAndExt(this.value);
+                var file_data = CodeMirror.getFilenameAndExt(this.value);
                 if(file_data['ext'] != null){
-                    var mimetype = getMimeTypeFromExt(file_data['ext']);
-                    var detected_mode = detectCodeMirrorMode(this.value, mimetype);
+                    var detected_mode = CodeMirror.findModeByExtension(file_data['ext']) || CodeMirror.findModeByMIME('text/plain');
                     if (detected_mode){
                         setCodeMirrorMode(myCodeMirror, detected_mode);
-                        $modes_select.val(mimetype)
+                        $modes_select.val(detected_mode.mime);
                     }
                 }
-            })
+            });
             </script>
         </div>
     </div>
--- a/kallithea/templates/files/files_add.html	Thu Nov 13 10:53:38 2014 -0500
+++ b/kallithea/templates/files/files_add.html	Thu Nov 13 10:56:28 2014 -0500
@@ -11,7 +11,6 @@
 <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
 <script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
 <script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
-<script type="text/javascript" src="${h.url('/js/meta_ext.js')}"></script>
 </%def>
 <%def name="css_extra()">
 <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -55,7 +54,7 @@
             <div id="body" class="codeblock">
             <div class="code-header" id="set_mode_header">
                 <label class="commit" for="set_mode">${_('New file mode')}</label>
-                ${h.select('set_mode','plain',[('plain',_('plain'))])}
+                <select id="set_mode" name="set_mode"/>
             </div>
                 <div id="editor_container">
                     <pre id="editor_pre"></pre>
@@ -72,21 +71,47 @@
             <script type="text/javascript">
             var reset_url = "${h.url('files_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.f_path)}";
             var myCodeMirror = initCodeMirror('editor',reset_url);
-            CodeMirror.modeURL = "${h.url('/codemirror/mode/%N/%N.js')}";
 
             //inject new modes, based on codeMirrors modeInfo object
             $('#set_mode').each(function(){
                 var modes_select = this;
+                var index = 1;
                 for(var i=0;i<CodeMirror.modeInfo.length;i++){
                     var m = CodeMirror.modeInfo[i];
-                    var opt = new Option(m.name, m.mode);
-                    modes_select.options[i+1] = opt
+                    var opt = new Option(m.name, m.mime);
+                    $(opt).attr('mode', m.mode);
+                    if (m.mime == 'text/plain') {
+                        // default plain text
+                        $(opt).attr('selected', 'selected');
+                        modes_select.options[0] = opt;
+                    } else {
+                        modes_select.options[index++] = opt;
+                    }
                 }
             });
             $('#set_mode').change(function(e){
                 var selected = e.currentTarget;
-                var new_mode = selected.options[selected.selectedIndex].value;
-                setCodeMirrorMode(myCodeMirror, new_mode);
+                var node = selected.options[selected.selectedIndex];
+                var detected_mode = CodeMirror.findModeByMIME(node.value);
+                setCodeMirrorMode(myCodeMirror, detected_mode);
+
+                var filenameInput = $('#filename');
+                var proposed_ext = CodeMirror.findExtensionByMode(detected_mode);
+                var file_data = CodeMirror.getFilenameAndExt(filenameInput.val());
+                var filename = file_data['filename'] || 'filename1';
+                filenameInput.val(filename + '.' + proposed_ext);
+            });
+
+            // on type the new filename set mode
+            $('#filename').keyup(function(e){
+                var file_data = CodeMirror.getFilenameAndExt(this.value);
+                if(file_data['ext'] != null){
+                    var detected_mode = CodeMirror.findModeByExtension(file_data['ext']) || CodeMirror.findModeByMIME('text/plain');
+                    if (detected_mode){
+                        setCodeMirrorMode(myCodeMirror, detected_mode);
+                        $('#set_mode').val(detected_mode.mime);
+                    }
+                }
             });
             </script>
         </div>
--- a/kallithea/templates/files/files_delete.html	Thu Nov 13 10:53:38 2014 -0500
+++ b/kallithea/templates/files/files_delete.html	Thu Nov 13 10:56:28 2014 -0500
@@ -7,16 +7,6 @@
     %endif
 </%def>
 
-<%def name="js_extra()">
-<script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
-<script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
-<script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
-<script type="text/javascript" src="${h.url('/js/meta_ext.js')}"></script>
-</%def>
-<%def name="css_extra()">
-<link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
-</%def>
-
 <%def name="page_nav()">
     ${self.menu('repositories')}
 </%def>
--- a/kallithea/templates/files/files_edit.html	Thu Nov 13 10:53:38 2014 -0500
+++ b/kallithea/templates/files/files_edit.html	Thu Nov 13 10:56:28 2014 -0500
@@ -11,7 +11,6 @@
 <script type="text/javascript" src="${h.url('/codemirror/lib/codemirror.js')}"></script>
 <script type="text/javascript" src="${h.url('/js/codemirror_loadmode.js')}"></script>
 <script type="text/javascript" src="${h.url('/codemirror/mode/meta.js')}"></script>
-<script type="text/javascript" src="${h.url('/js/meta_ext.js')}"></script>
 </%def>
 <%def name="css_extra()">
 <link rel="stylesheet" type="text/css" href="${h.url('/codemirror/lib/codemirror.css')}"/>
@@ -60,7 +59,7 @@
                     </div>
                 </div>
                 <label class="commit" for="set_mode">${_('Editing file')}: ${c.file.unicode_path}</label>
-                ${h.select('set_mode','plain',[('plain',_('plain'))])}
+                <select id="set_mode" name="set_mode"/>
             </div>
                 <pre id="editor_pre"></pre>
                 <textarea id="editor" name="content" style="display:none">${h.escape(c.file.content)|n}</textarea>
@@ -80,28 +79,37 @@
 $(document).ready(function(){
     var reset_url = "${h.url('files_home',repo_name=c.repo_name,revision=c.cs.raw_id,f_path=c.file.path)}";
     var myCodeMirror = initCodeMirror('editor',reset_url);
-    CodeMirror.modeURL = "${h.url('/codemirror/mode/%N/%N.js')}";
 
    //inject new modes, based on codeMirrors modeInfo object
-    var modes_select = $('#set_mode');
-    for(var i=0;i<CodeMirror.modeInfo.length;i++){
-        var m = CodeMirror.modeInfo[i];
-        var opt = $('<option></option>').val(m.mode).text(m.name)
-        modes_select.append(opt)
+    $('#set_mode').each(function(){
+        var modes_select = this;
+        var index = 1;
+        for(var i=0;i<CodeMirror.modeInfo.length;i++){
+            var m = CodeMirror.modeInfo[i];
+            var opt = new Option(m.name, m.mime);
+            $(opt).attr('mode', m.mode);
+            if (m.mime == 'text/plain') {
+                // default plain text
+                $(opt).attr('selected', 'selected');
+                modes_select.options[0] = opt;
+            } else {
+                modes_select.options[index++] = opt;
+            }
+        }
+    });
+    // try to detect the mode based on the file we edit
+    var detected_mode = CodeMirror.findModeByExtension("${c.file.extension}");
+    if(detected_mode){
+        setCodeMirrorMode(myCodeMirror, detected_mode);
+        $($('#set_mode option[value="'+detected_mode.mime+'"]')[0]).attr("selected", "selected")
     }
 
-    // try to detect the mode based on the file we edit
-    var detected_mode = detectCodeMirrorMode("${c.file.name}", "${c.file.mimetype}")
-    if(detected_mode){
+    $('#set_mode').on('change', function(e){
+        var selected = e.currentTarget;
+        var node = selected.options[selected.selectedIndex];
+        var detected_mode = CodeMirror.findModeByMIME(node.value);
         setCodeMirrorMode(myCodeMirror, detected_mode);
-        $($('#set_mode option[value="'+detected_mode+'"]')[0]).attr("selected", "selected")
-    }
-
-    $(modes_select).on('change', function(e){
-        var selected = e.currentTarget;
-        var new_mode = selected.options[selected.selectedIndex].value;
-        setCodeMirrorMode(myCodeMirror, new_mode);
-    })
+    });
 })
 </script>
 </%def>