# ruby-mode.tcl - mode stead for editing tcl code
# 
# diam =  Maurice DIAMANTINI (diam@ensta.fr)
# 
# 11/01/2007 (diam) : création minilmaliste (à partir de tcl)
# 

## mode_ruby_init --
# 
proc mode_ruby_init {} {

    global stead
    global EDITPREFS
    
    # Les commandes à exécuter si on quitte ce mode
    set stead(mode,cleanupCmds) [list]

    # définit le préfixe pour le mode matlab (pour mettre en commentaires)
    set EDITPREFS(prefix) "# "
    
    set EDITPREFS(autobreak) 0
    
    # Une liste de fichier fréquement éditer (à personaliser par l'utilisateur)
    # On peut utiliser les métacaracteres ou les variables d'environnement)
    set stead(mode,ruby,favorFiles) {
        /insert/here/you/favorite/list/of/files/modeles
        ~/public_html/bm/pub/ruby/syntaxe_ruby.rb
        ~/.stead/steadrc
    }
    
    # 
    # Définition du menu de navigation A REFONDRE
    # 
    global TE_MODE_SEARCH_STRING TE_MODE_NAVIG_SHOW_TEXT  

    # Définition du menu de navigation
    set TE_MODE_NAVIG_SHOW_TEXT "objects_methods"
   
    # # set method "\n\[ \t\]*(public|class|def)\[^\n\]+"
    # # set metaCommentPat {(^|\n)##\s+(\w+[^\n]*)}
    set method "(^|\n)\[ \t\]*(public|class|def)\[^\n\]+"
    set metaCommentPat {(^|\n)\s*##\s+(\w+[^\n]*)}
    set TE_MODE_SEARCH_STRING $method
  
    proc te:mode:navig_sort_hook {list} {
        return [lsort -command te:mode:sort_command $list]
    }
}

## mode_ruby_defineStyles -
# 
proc mode_ruby_defineStyles {} {
    global stead
    upvar #0 stead(text) w

    lappend stead(mode,cleanupCmds) \
                        [list xtext_style $w delete $stead(mode)]

    # "keylist1"  définit une patterne de reconnaissance des mots clé 
    # "important" (i.e. modif de structure et autre...)
    # 
    xtext_style $w define ruby keylist1 {
        -type wordListLight
        -config {-foreground red}
        -values {
            public protected private public 
            main class module require include def proc
            return exit next break raise 
        }
    }
    # "keylist2"  définit une patterne de reconnaissance des mots clé 
    # "courants" du ruby :
    # 
    xtext_style $w define ruby keylist2 {
        -type wordListLight
        -config {-foreground blue}
        -values { 
            if then else elsif unless while do for case when 
            new each self do begin rescue ensure end
        }
    }
    # "keylist3"  définit une patterne de reconnaissance des mots clé 
    # correspondant à des types ou classes couramment prédéfinis :
    # 
    xtext_style $w define ruby keylist3 {
        -type wordListLight
        -config {-foreground #F0F}
        -values {
            Array Class
            void nil true false
        }
    }


    # Traitement <Control-C> si précédé de "bind" ou de "event"
    # Traitement des guillemets
    # 
    xtext_style $w define ruby {
        quotes {
            -type regexpLight
            -config {-foreground #700}
            -pat {(".*?"|'.*?')}
        }
        instance_var {
            -type regexpLine
            -config {-foreground #707}
            -pat {\W(@@?\w+)(\W|$)}
        }
    }
    # 10/01/2007 remplace {\W(\$\w+)(\W|$)} par {(\$\w+)(\W|$)}
    # car une globale en début de ligne n'était colorée !
    xtext_style $w define ruby {
        global_var {
            -type regexpLine
            -config {-foreground #F00 -background #FF8}
            -pat {\W(\$\w+)(\W|$)}
            -pat {(\$\w+)(\W|$)}
        }
    }
        
    # set pat   {(?:^|;|\[)(?:\s*)(#.*)} ;# pour balance dans stead : \]
    # set pat   {(#.*)} ;# pour balance dans stead : \]
    set pat   {(#[^\{].*)} ;# pour balance dans stead : \]
    set config  "-foreground #070 "
    set stead(tagSpec,shell_comment) [list  \
        -type   regexpLine                  \
        -pat    $pat                        \
        -config $config                     \
    ]
    xtext_style $w define ruby comment   $stead(tagSpec,shell_comment)    

    # MÉTACOMMENT RUBY ("## " suivi de caractères, ert éventuellement précédés
    # d'espace)
    set pat {(?:^\s*)(##\s+\w+[^\n]*)$}
    set config  "-foreground #F00 "
    set stead(tagSpec,metacomment) [list  \
        -type   regexpLine                  \
        -pat    $pat                        \
        -config $config                     \
    ]
    xtext_style $w define ruby metacomment   $stead(tagSpec,metacomment)    


    # Mise en valeur des backslash important (en fin de ligne)
    xtext_style $w define ruby {
        lineEndedBacklash {
            -type regexpLine
            -pat {(\B$)}
            -config {
                -foreground red -font bold
            }
        }
        errorBacklash {
            -type regexpLine
            -pat {(\B[ \t]+$)}
            -config {
                -background red -foreground yellow
            }
        }
    }
    # erreur légère (rose claire)
    # J'en ai mare des tabulations qu'on trouve dans le code source
    # et qui perturbe l'indentation
    xtext_style $w define ruby {
        tabulation {
            -type regexpLight
            -pat {\t}
            -config {
                -background "#FDD"
            }
        }
    }
    
    xtext_style $w enable ruby
    
}



## mode_ruby_getHelp - retourne une chaine d'info spécifique au mode ruby
# 
proc mode_ruby_getHelp {} {

  set help {\

    Aide du mode Ruby :  à compléter !
    
  }
  return $help
}


## mode_ruby_defineSabbrev -
# 
proc mode_ruby_defineSabbrev {} {
    ########################################################################
    # pour simplifier l'ecriture des electric-alias en déclarant :
    #    M : Marque temporaire
    #    B : début de postcommande 
    #    E : fin de postcommande
    #    V : Inclusion d'une variable TCL
    electricAlias-use8bitsCars
        
    ## diam 21/08/00 essai d'un nouvelle API pour les electricAlias
    #  On n'utilise plus que les caractere spéciaux TCL [ ] et $
    # 
    
    set    tmp {[askVar "method name" NAME]}
    append tmp {## [getVar NAME] -- [setStop]\n}
    append tmp {# \n}
    append tmp {# \n}
    append tmp {def [getVar NAME]([setStop])\n}
    append tmp {[i][setStop]\n}
    append tmp {end\n}
    append tmp {[setStop]}
    electricAlias-def ${M}ruby def $tmp
    
    set    tmp {[askVar "procedure name" NAME]}
    append tmp {## [getVar NAME] -- [setStop]\n}
    append tmp {# \n}
    append tmp {# arguments:\n}
    append tmp {# \n}
    append tmp {#   - \n}
    append tmp {# \n}
    append tmp {# results:\n}
    append tmp {# \n}
    append tmp {# \n}
    append tmp {# \n}
    append tmp {# examples\n}
    append tmp {# \n}
    append tmp {# \n}
    append tmp {# \n}
    append tmp {def [getVar NAME]([setStop])\n}
    append tmp {[i][setStop]\n}
    append tmp {end # [getVar NAME]\n}
    append tmp {[setStop]}
    # # # electricAlias-def ${M}ruby proc2 $tmp
    # # # electricAlias-defSol ruby proc2 $tmp
    defAlias -sol ruby def2 $tmp
    
    # pour afficheren ruby :  puts "myVar=#{myVar}"
    electricAlias-def ruby # #\{[setStop]\}
    
    # for
    set t1 {for [setStop]\n[i][setStop]\nend\n}
    set t2 {\}\n[setStop]}
    electricAlias-def ${M}ruby for $t1
    
    # if simple
    set t1 {if [setStop]\n[i][setStop]\nend\n[setStop]}
    electricAlias-def ${M}ruby if $t1

    # case complet    
    set    tmp {case [setStop]\n[i]when [setStop]\n[i]when [setStop]}
    append tmp {\n[i]else [setStop]\nend\n[setStop]}
    # 
    electricAlias-def ${M}ruby case $tmp
    # 
    set    tmp {[insert_usrbinenv_header ruby]}
    electricAlias-def ${M}ruby ruby $tmp
}


## insert_switch_platform_header -
# 
proc insert_switch_platform_header { {idx insert} } {
    set    txt "global tcl_platform\n"
    append txt "[i]switch -exact -- \$tcl_platform(platform) \{\n"
    append txt "[i]  macintosh \{\n"
    append txt "[i]  \} \n"
    append txt "[i]  windows \{\n"
    append txt "[i]  \} \n"
    append txt "[i]  unix \{\n"
    append txt "[i]  \} \n"
    append txt "[i]\} \n"
    append txt \n
    insert $txt $idx
}


## mode_ruby_defineMenu_ruby - défini le menu principale de ruby
# 
# 
proc mode_ruby_defineMenu_ruby {} {
    global stead
    
    set menubutton  .menu.$stead(mode)
    set m           .menu.$stead(mode).m
    
    if {[winfo exists $menubutton]} {
        destroy $menubutton
    }
    # Création d'un bouton de menu (ce qu'on voit)
    menubutton $menubutton \
            -text [string totitle $stead(mode)] \
            -menu .menu.$stead(mode).m
            
    lappend stead(mode,cleanupCmds) [list destroy  $menubutton]

    # On positionne ce bouton
    pack append .menu $menubutton left
  
    # Création d'un menu (ce qui ce déroule quand on clique sur le menubutton)
    set m [menu $m]
    # 
    ####################################################################
    
    
    ## Sous menu pour les fichiers modèles de ce mode
    $m add cascade \
            -label {Fichiers modèles}  \
            -menu "$m.files"
          
    menu $m.files
    foreach pat $::stead(mode,ruby,favorFiles) {
        foreach file [glob -nocomplain  $pat] {
            $m.files add command \
                 -label $file \
                 -command "stead $file"
        }  
    }    

    ## Sous menu pour les fichiers tcl du répertoire courant
    menu:makeEditSubmenuFromDirectory2  $m $m.files[xtcl_uid]  \
           "Current directory Ruby files"  \
           [file dirname $stead(file)]/*.rb
}

## mode_ruby_defineMenu_templates - défini le menu Templates de ruby
# 
# 
proc mode_ruby_defineMenu_templates {} {
    global stead
    
    ###########################################################################
    # On crée le menu template s'il n'existe pas
    # 
    set menubutton  .menu.template
    set m           .menu.template.m
    
    if {[winfo exists $menubutton]} {
        destroy $menubutton
    }
    # Création d'un bouton de menu (ce qu'on voit)
    menubutton $menubutton  \
            -text Templates \
            -menu $m
            
    lappend stead(mode,cleanupCmds) [list destroy  $menubutton]

    # On positionne ce bouton
    pack append .menu $menubutton left
  
    # Création d'un menu (ce qui ce déroule quand on clique sur le menubutton)
    set m [menu $m]
    
    # 
    ##################################################################
      

    $m add command \
            -label "Insérer un separateur \"#...\"" \
            -command {separator 1}
    
    $m add command \
            -label {def...} \
            -command {electricAlias-wrap def}
    
    $m add separator
                   
    $m add separator
    $m add command \
            -label {En-tête "#!/usr/bin/env ruby"} \
            -command {insert_usrbinenv_header ruby}
            
    
    $m add separator
    
    $m add command \
            -label {boucle for} \
            -command {electricAlias-wrap for}
    $m add command \
            -label {if} \
            -command {electricAlias-wrap if}
    
    $m add separator
    
    $m add cascade  -label Alias  -menu $m.alias
    menu $m.alias
    foreach alias [electricAlias-softNames] {
        $m.alias add command   \
             -label $alias \
             -command "electricAlias-insert $stead(text) [te:no_interp $alias]"
    }

}

proc insert_usrbinenv_header { interName {idx 1.0} } {
    global stead
    set w $stead(text)
    
    set    txt "#!/usr/bin/env $interName\n\n"
    xtext_setCursor $w 1.0
    xtext_insert $w -index $idx -- [subst $txt]
}

## stead:modeStart_ruby - lancement du mode ruby
# 
# 
proc stead:modeStart_ruby {} {
    mode_ruby_init
    mode_ruby_defineSabbrev
    mode_ruby_defineMenu_ruby
    mode_ruby_defineMenu_templates
    mode_ruby_defineStyles
}
## stead:modeQuit_gvt - Nettoyage quand on quitte ce mode
# 
proc stead:modeQuit_ruby {} {
    catch {eval [join $::stead(mode,cleanupCmds) ";"]}
}

## Cette procédure est appelé automatiquement (sera refondu)
proc stead:modeCleanup {} {
    stead:modeQuit_ruby
}

# Ceci sera géré automatiquement par stead (via auto_load)
stead:modeStart_ruby

#./
