Преглед на файлове

Add filepath completion for `cat`, `cd` and `ls`

Also try restricting the site to 840px, because 1200px is too large.
Maybe smaller than 960px is better for what this page contains.
Weiyi Lou преди 9 години
родител
ревизия
cf56984792
променени са 2 файла, в които са добавени 43 реда и са изтрити 19 реда
  1. 4 1
      css/style.css
  2. 39 18
      js/pgsh.js

+ 4 - 1
css/style.css

@@ -1,4 +1,4 @@
-/* pgs-cli styles */
+/* pgs-cli stylesheet */
 * {
   color: #DDD;
   font-family: 'Courier New', Courier, Monospace;
@@ -37,3 +37,6 @@ div.console-inner { overflow-y: auto; }
   ::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.1); }
   ::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.5); }
 }
+
+/* Keep to 840px. 1200px is too wide. */
+.container{ max-width: 840px }

+ 39 - 18
js/pgsh.js

@@ -21,7 +21,7 @@ function pgsh(ev) {
   ev.on('mount', function() {
     document.getElementById(ev.id).onkeydown = function(e) {
       var code = e.keyCode || e.which
-      // Tab
+      // Tab for file path completion
       if (code == 9) {
         var input = ev.tags['command-line'].command.value.trim().split(' ')
         var command = input.shift()
@@ -29,7 +29,7 @@ function pgsh(ev) {
           var args = input.join(' ').trim()
           var isFile = (command == 'cat') ? true : false;
           var path = completePath(args, isFile)
-          if (path) { ev.trigger('cmd_set', cmd + ' ' + path) }
+          if (path) { ev.trigger('cmd_set', command + ' ' + path) }
         }
         e.preventDefault()
       }
@@ -137,7 +137,7 @@ function pgsh(ev) {
       }
       show('\n' + content + '\n\n')
     } else {
-      show("cd: " + arg + ": no such file")
+      show("cat: " + arg + ": no such file")
     }
   }
   this.cd = function(args) {
@@ -198,18 +198,14 @@ function pgsh(ev) {
     var path = resolveAbsPath(folder)
     if (pathExists(path)) {
       var contents = getContents(path)
-      var items = []
-      for (var item in contents) {
-        items.push(item)
-      }
-      items.sort()
       var dstat = 'drwxr-xr-x <span style="color:#268bd2">'
       var fstat = '-rw-r--r-- '
-      items.forEach(function(item, key, items) {
+      var items = []
+      for (var item in contents) {
         var prefix = (typeof contents[item] === 'string') ? fstat : dstat
         var suffix = (typeof contents[item] === 'string') ? '' : '</span>'
-        items[key] = prefix + item + suffix
-      })
+        items.push(prefix + item + suffix)
+      }
       items.unshift(dstat + '..</span>')
       items.unshift('total ' + items.length)
       show(items.join('\n'))
@@ -260,7 +256,7 @@ function pgsh(ev) {
     }
   }
   this.version = function(args) {
-    show('Parsley Gardens Shell (pgsh) 1.1.0 Built with ' +
+    show('Parsley Gardens Shell (pgsh) 1.1.0\nBuilt with: ' +
          '<a target="_blank" href="http://riotjs.com">Riot</a> ' +
          '<a target="_blank" href="https://skeleton-framework.github.io">Skeleton</a> ' +
          '<a target="_blank" href="https://highlightjs.org">highlight.js</a>')
@@ -313,15 +309,40 @@ function pgsh(ev) {
     parts.forEach(function(part) {
       if (part) { tree = tree[part] }
     })
+    // Sort JS object. TODO not a great way.
+    if (typeof tree === 'object') {
+      var keys = []
+      for (key in tree) {
+        keys.push(key)
+      }
+      keys.sort()
+      var temp = {}
+      keys.forEach(function(key) {
+        temp[key] = tree[key]
+      })
+      tree = temp
+    }
     return tree
   }
 
-  var completePath = function(path, isFile) {
-    // check if we are doing partial name completion
-      // ending slash means completing first content
-      // not ending slash means word completion - cut off bit for completion
-    // first get right directory with absolute path
-    console.log('completing')
+  var completePath = function(input, isFile) {
+    // Extract file fragment and get actual path.
+    var slash = input.lastIndexOf('/') + 1
+    var frag = input.substring(slash)
+    var base = input.substring(0, slash)
+    var path = resolveAbsPath(base)
+    // Complete fragments
+    if (pathExists(path)) {
+      var contents = getContents(path)
+      var found = ''
+      for (var name in contents) {
+        if (!isFile && typeof contents[name] === 'string') { continue }
+        if (!frag) { found = name; break }
+        if (name.indexOf(frag) == 0) { found = name }
+      }
+      var end = typeof contents[found] === 'object' ? '/' : ''
+      return base + found + end
+    }
     return ''
   }
 }