Ιεραρχία ή επίπεδο; (utility)

Κώδικας, πληροφορίες, ερωτήσεις και απαντήσεις σχετικές με την JavaScript.

Συντονιστές: WebDev Moderators, Super-Moderators

Απάντηση
Άβαταρ μέλους
skeftomilos
Script Master
Δημοσιεύσεις: 2888
Εγγραφή: 07 Ιαν 2005 07:22
Τοποθεσία: Αθήνα

Ιεραρχία ή επίπεδο; (utility)

Δημοσίευση από skeftomilos » 15 Ιαν 2006 01:36

Δεν πρόκειται για διακήρυξη στο όνομα της Δημοκρατίας, ούτε κάλεσμα για την Επανάσταση των μαζών. Το θέμα μας είναι απλά η οργάνωση των αρχείων του σκληρού μας δίσκου. Αν έχετε ένα σύνολο ετερόκλητων αρχείων προτιμάτε να τα ρίξετε όλα φύρδην μίγδην σε ένα φάκελο, ή τα ταχτοποιείτε με προσοχή σε ξεχωριστούς υποφακέλους κατά είδος; Κάθε προσέγγιση έχει τα δικά της πλεονεκτήματα και μειονεκτήματα, και ασφαλώς η επιλογή μας αντανακλά σε ένα βαθμό το χαρακτήρα μας. Για να μη μιλάμε στον αέρα ας δούμε ένα παράδειγμα:

Εικόνα

Έχουμε μόλις ξεκινήσει ένα νέο project, που περιλαμβάνει αρχεία ascx, aspx, cs και jst. Μέχρι στιγμής η κατάσταση είναι υπό έλεγχο, αλλά καθώς τα αρχεία θα πολλαπλασιάζονται η ζωή μας ολοένα θα δυσκολεύει. Επειδή λοιπόν είμαστε προνοητικοί τύποι αποφασίζουμε να βάλουμε μια τάξη στο χάος όσο είναι ακόμα καιρός:

Εικόνα

Βάλαμε τα αρχεία cs (C#) στο φάκελο components, τα jst (JavaScript Templates) στον templates, τα ascx (Web User Controls) στον wucs, και αφήσαμε τα aspx (ASP.NET σελίδες) στον κύριο φάκελο. Όλα μοιάζουν πολύ ειδυλλιακά, αλλά υπάρχει ένα τίμημα. Για να ανοίξουμε ένα αρχείο προστέθηκε ένα επιπλέον στάδιο, η μετάβαση στον σχετικό υποφάκελο. Όσο πιο συχνά ανοίγουμε τα διάφορα αρχεία, τόσο πιο πολύ θα μας ταλαιπωρήσει αυτό το επιπλέον στάδιο. Κάποια στιγμή είναι βέβαιο πώς θα νοσταλγήσουμε την επίπεδη δομή που είχε αρχικά ο φάκελος. Άραγε υπάρχει τρόπος να συνδυάσουμε τα θετικά στοιχεία των δύο κόσμων;

Μία πιθανή λύση είναι το Folders panel του Windows Explorer:

Εικόνα

Για κάποιο άγνωστο λόγο ποτέ δεν συμπάθησα αυτό το panel. Μιά άλλη λύση μπορεί να είναι ο ενσωματωμένος File manager του αγαπημένου μας editor:

Εικόνα

Εικόνα

Αν για οποιοδήποτε λόγο δε μας ικανοποιεί ούτε αυτό, τότε υπάρχει ακόμα μία λύση, τα shortcuts. Μπορούμε για κάθε αρχείο που βρίσκεται σε κάποιο υποφάκελο να δημιουργήσουμε ένα shortcut στον κύριο φάκελο. Έτσι θα καταφέρουμε να έχουμε ταυτόχρονα και τις δύο δομές, την ιεραρχία και το επίπεδο. Ας το δοκιμάσουμε στην πράξη για να δούμε πώς θα φαίνεται:

Εικόνα

Έβαλα ένα πρόθεμα στην αρχή του ονόματος του κάθε shortcut, ώστε με την ταξινόμηση κατά όνομα να γίνει μια οπτική ομαδοποίηση. Δεν ξέρω πώς σας φαίνεται η ιδέα, για το λίγο διάστημα που τη δοκίμασα τη βρήκα βολική. Προκύπτει βέβαια ένα νέο θέμα, ότι τώρα για κάθε αρχείο που δημιουργούμε ή μετονομάζουμε θα πρέπει να φροντίζουμε για το αντίστοιχο shortcut. Εδώ ακριβώς είναι που μπορεί να βοηθήσει την κατάσταση λίγο scripting. Θα φτιάξουμε ένα script που θα αναλάβει όλη τη φροντίδα για το συγχρονισμό των shortcuts. Θα δημιουργεί όσα shortcuts είναι απαραίτητα και θα διαγράφει όσα έπαψαν πλέον να είναι χρήσιμα. Θα χωρίσουμε το script σε δύο μέρη, το πρώτο θα περιέχει δεδομένα για τη διαδικασία και το δεύτερο θα έχει τον κώδικα:

_flatten.wsf

Κώδικας: Επιλογή όλων

<!-- Μετατροπή ιεραρχικής οργάνωσης αρχείων σε επίπεδη. -->
<job>
  <script language="JScript">
    var TREE = &#91;
//    &#91;'φάκελος',    'αρχεία', 'πρόθεμα', 'επίθεμα'&#93;,
      &#91;'components', 'cs',     '&#123;',       '&#125;'&#93;,
      &#91;'templates',  'jst',    '+'&#93;,
      &#91;'wucs',       'ascx',   '~'&#93;,
    &#93;

    var DELETE_IRRELEVANT_LINKS = true
  </script>
  <script language="JScript" src="D&#58;\Utilities\flatten-core.js"/>
</job>
Το πρώτο αρχείο θα το βάλουμε μέσα στο φάκελο της εφαρμογής για να το έχουμε πρόχειρο. Το δεύτερο πρέπει να τοποθετηθεί σε κάποια σταθερή και αμετάβλητη θέση του δίσκου, για παράδειγμα στη θέση D:\Utilities\flatten-core.js.

flatten-core.js

Κώδικας: Επιλογή όλων

var TREE, DELETE_IRRELEVANT_LINKS

if &#40;!TREE&#41; &#123;
  WScript.Echo&#40;'Το script δεν τρέχει stand-alone.\nΠρέπει να γίνει included σε ένα wsf αρχείο.'&#41;
  WScript.Quit&#40;&#41;
&#125;

var fso = WScript.CreateObject&#40;'Scripting.FileSystemObject'&#41;
var shell = WScript.CreateObject&#40;'WScript.Shell'&#41;

// Root φάκελος θεωρείται ο φάκελος που βρίσκεται το script.
var rootFolderName = fso.GetParentFolderName&#40;WScript.ScriptFullName&#41;
var rootFolder = fso.GetFolder&#40;rootFolderName&#41;

// Αν ο root φάκελος δεν περιέχει κανένα link, μάλλον είναι η πρώτη φορά που τρέχει το script.
if &#40;!searchFolderForLinks&#40;rootFolder&#41;&#41; &#123;
  // Ας ζητήσουμε επιβεβαίωση από το χρήστη.
  var folders = &#91;&#93;
  for &#40;var i = 0, entry; entry = TREE&#91;i&#93;; i++&#41; folders.push&#40;entry&#91;0&#93;&#41;
  var msg = 'Δημιουργία shortcuts για αρχεία ' + &#40;folders.length == 1 ? 'ενός φακέλου' &#58; folders.length + ' φακέλων'&#41; + '&#58;'
  if &#40;folders.length&#41; msg += '\n\n- ' + folders.join&#40;'\n- '&#41;
  msg += '\n\nΕπιβεβαίωση;'
  var res = shell.Popup&#40;msg, 0, 'Flatten', 4 + 32&#41; // Yes-No
  if &#40;res != 6&#41; WScript.Quit&#40;&#41;
&#125;

var links = &#91;&#93;
var createdLinks = &#91;&#93;
var deletedLinks = &#91;&#93;

// Δημιουργία των links.
for &#40;var i = 0, entry; entry = TREE&#91;i&#93;; i++&#41; &#123;
  var folderName = entry&#91;0&#93;
  var extension = entry&#91;1&#93;.toLowerCase&#40;&#41;
  var prefix = entry&#91;2&#93; || ''
  var suffix = entry&#91;3&#93; || ''

  var folderPath = fso.BuildPath&#40;rootFolderName, folderName&#41;
  if &#40;!fso.FolderExists&#40;folderPath&#41;&#41; &#123;
    WScript.Echo&#40;'Ο φάκελος ' + folderName + ' δε βρέθηκε.'&#41;
    WScript.Quit&#40;&#41;
  &#125;
  var folder = fso.GetFolder&#40;folderPath&#41;
  for &#40;var e = new Enumerator&#40;folder.Files&#41;; !e.atEnd&#40;&#41;; e.moveNext&#40;&#41;&#41; &#123;
    var file = e.item&#40;&#41;
    if &#40;fso.GetExtensionName&#40;file.Name&#41;.toLowerCase&#40;&#41; == extension&#41; &#123;
      var linkName = prefix + file.Name + suffix + '.lnk'
      var linkPath = fso.BuildPath&#40;rootFolderName, linkName&#41;
      links.push&#40;linkName&#41;
      if &#40;!fso.FileExists&#40;linkPath&#41;&#41; &#123;
        var link = shell.CreateShortcut&#40;linkPath&#41;
        link.TargetPath = file.Path
        link.Save&#40;&#41;
        createdLinks.push&#40;linkPath&#41;
      &#125;
    &#125;
  &#125;
&#125;

links = arrayToSet&#40;links&#41;  // Μετατροπή σε Set.

if &#40;DELETE_IRRELEVANT_LINKS&#41; &#123;
  // Αναζήτηση και διαγραφή περιττών links.
  for &#40;var e = new Enumerator&#40;rootFolder.Files&#41;; !e.atEnd&#40;&#41;; e.moveNext&#40;&#41;&#41; &#123;
    var file = e.item&#40;&#41;
    if &#40;fso.GetExtensionName&#40;file.Name&#41;.toLowerCase&#40;&#41; == 'lnk'&#41; &#123;
      if &#40;!links&#91;file.Name&#93;&#41; &#123;
        deletedLinks.push&#40;file.Path&#41;
      &#125;
    &#125;
  &#125;
  for &#40;var i = 0; i < deletedLinks.length; i++&#41; &#123;
    fso.DeleteFile&#40;deletedLinks&#91;i&#93;&#41;
    deletedLinks&#91;i&#93; = fso.GetFileName&#40;deletedLinks&#91;i&#93;&#41;
  &#125;
&#125;

// Εμφάνιση αποτελεσμάτων.
var msg = ''
if &#40;!createdLinks.length && !deletedLinks.length&#41; &#123;
  msg += 'Nothing to do!'
&#125; else &#123;
  if &#40;createdLinks.length&#41; &#123;
    if &#40;createdLinks.length == 1&#41; &#123;
      msg += 'Δημιουργήθηκε ένα shortcut.'
    &#125; else &#123;
      msg += 'Δημιουργήθηκαν ' + createdLinks.length + ' shortcuts.'
    &#125;
  &#125;
  if &#40;deletedLinks.length&#41; &#123;
    if &#40;msg&#41; msg += '\n\n'
    if &#40;deletedLinks.length == 1&#41; &#123;
      msg += 'Διαγράφηκε ένα shortcut&#58;'
    &#125; else &#123;
      msg += 'Διαγράφηκαν ' + deletedLinks.length + ' shortcuts&#58;'
    &#125;
    msg += '\n\n- ' + deletedLinks.join&#40;'\n- '&#41;
  &#125;
&#125;

shell.Popup&#40;msg, 0, 'Flatten'&#41; // Τέλος του script.

// Συνάρτηση μετατροπής array σε Set.
function arrayToSet&#40;array&#41; &#123;
  var o = &#123;&#125;
  for &#40;var i = 0; i < array.length; i++&#41; o&#91;array&#91;i&#93;&#93; = true
  return o
&#125;

// Απαντά αν ένας φάκελος περιέχει ένα τουλάχιστον link.
function searchFolderForLinks&#40;folder&#41; &#123;
  for &#40;var e = new Enumerator&#40;folder.Files&#41;; !e.atEnd&#40;&#41;; e.moveNext&#40;&#41;&#41; &#123;
    var file = e.item&#40;&#41;
    if &#40;fso.GetExtensionName&#40;file.Name&#41;.toLowerCase&#40;&#41; == 'lnk'&#41; return true
  &#125;
  return false
&#125;
Ας το δοκιμάσουμε στην πράξη να δούμε αν δουλεύει. Διαγράφουμε πρώτα τα shortcuts που φτιάξαμε πριν λίγο με το χέρι, και κάνουμε διπλό κλικ στο αρχείο _flatten.wsf:

Εικόνα

Εικόνα

Οι ρυθμίσεις που πρέπει να κάνουμε είναι αρκετά προφανείς. Για παράδειγμα η γραμμή...

Κώδικας: Επιλογή όλων

&#91;'components', 'cs', '&#123;', '&#125;'&#93;,
...σημαίνει ότι για όλα τα αρχεία του φακέλου components που έχουν κατάληξη cs θα δημιουργηθεί από ένα shortcut με πρόθεμα { και επίθεμα }. Μία ακόμα δοκιμή θα μας πείσει ότι το script δουλεύει σωστά. Προσθέτουμε ένα αρχείο customers.cs στο φάκελο components και ξανατρέχουμε το script:

Εικόνα

Μένει να δούμε αν το ίδιο το script έχει τίποτα ενδιαφέρον να συζητήσουμε. Το πιο ουσιώδες τμήμα του κώδικα είναι αυτό που δημιουργεί τα shortcuts:

Κώδικας: Επιλογή όλων

var link = shell.CreateShortcut&#40;linkPath&#41;
link.TargetPath = file.Path
link.Save&#40;&#41;
Τα shortcuts των Windows δεν είναι παρά binary αρχεία με ειδική κατάληξη. Ποια είναι αυτή; Στην πραγματικότητα υπάρχουν δύο καταλήξεις, η .lnk για shortcuts των τοπικών αρχείων και .url για Internet shortcuts. Πιθανότατα πότε δεν έχετε δει με τα μάτια σας αυτές τις καταλήξεις, και ο λόγος είναι μια σχετική ρύθμιση στο Registry:

Εικόνα

Αν για κάποιο λόγο θέλετε να βλέπετε αυτές τις καταλήξεις, διαγράψτε τη ρύθμιση NeverShowExt. Ένας λόγος που μπορεί να χρειαστεί να το κάνετε είναι αν σας έρθει ποτέ η ατυχής έμπνευση να αλλάξετε την κατάληξη ενός χρήσιμου αρχείου σε .lnk. Η κατάληξη ξαφνικά θα χαθεί και δε θα μπορείτε πια να τη διορθώσετε!

Εκτός από την ιδιότητα TargetPath υπάρχουν και άλλες χρήσιμες ιδιότητες για τα αντικείμενα WshShortcut, όπως WindowStyle, Hotkey, IconLocation, Description και WorkingDirectory. Στη δική μας περίπτωση δε χρειάστηκε να τις πειράξουμε. Για να φτιάξουμε Internet shortcuts καλούμε πάλι τη μέθοδο CreateShortcut() του WshShell, αλλά αυτή τη φορά με όρισμα ένα file path με κατάληξη .url. Μας επιστρέφεται ένα αντικείμενο WshUrlShortcut, ορίζουμε την TargetPath και το σώζουμε με Save().
The pure and simple truth is rarely pure and never simple. Ο μη νους δε σκέπτεται μη σκέψεις για το τίποτα.

Cmg__
Δημοσιεύσεις: 1710
Εγγραφή: 29 Μαρ 2005 22:40

Ιεραρχία ή επίπεδο; (utility)

Δημοσίευση από Cmg__ » 18 Ιαν 2006 22:47

:clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap: :clap:



Πραγματικά πολύ χρήσιμο. I'll use it.. .:D

Απάντηση

Επιστροφή στο “JavaScript και Frameworks”

Μέλη σε σύνδεση

Μέλη σε αυτήν τη Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 1 επισκέπτης