aboutsummaryrefslogblamecommitdiffstats
path: root/bash_include
blob: e4609c47054f45187d0557072fce9c4e4a6bd970 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                      
 
                            
 

             



                                                                                                           
 
                                                   

                                                        
                                                           
                                            
                                                 


                                              
                                              
                                      

                                              

                                              




                                                 
 
 

                    

                                                                                                                                                                   
 
                        
    



                                                             





                                                                    







                                                                              
                                                                   




                                                                     
                           
    

                                                                     

  











                                                                    










                                                     


                                                                   





                                                     





                                                      






                                                                                                        
 



                                             
 

                       
                                  
                       

                                            
 
                              
                                    
                      

 
                       


                 
                 
                 
                   

 
                               
 



                  
                
                 



                     
                 
                                                 

                                               
                  


                                                            

    
                 
                                                                    



                                                


                                                            
                   
                   






                                     

                  
                                               

                                               
                                    



                                    
                                                  

                                                  
                                       




                                       








                                                                    

                                                                  

                                                                     
 
 
                      
 



                                                                                                                                         








                                             

                                                                                                                                                            

                                               
 
 
















                                                                                                        
                                                                                                                  







                                        
                                                                              
 
                             
 






                                                                     
            

                                                  
          

 
                                  
 

                              

 
                        
 




                                                                               

 
                         
 
                            
                                                    


                                         
         

                        

 


































                                                                               
 




                 
                  
 

                 
                                  
                                                                            
                                                  
                                                                                
                                                   


                                                     
                                                             
                                   


                                                 
                                         
           



                  

                                         


                                                                              







                                                                         
                    
             
                                        
                    
                                                                         









                                                                                







                                                                                                                       


                                      
                                                      


                              

 
                  
 
                           
                        
            







                                                    
          
                                          
                                                                                                        





                                             
                                                    
                                                       


                        
         
                                                   

                                   

 




                                                                                              

                   























                                                                                              

 
                
 










                                                                              
                                                                




                                                             

 
 
                                                                              
 
                             
 

                                                                             
                               
                                            
                                       
                       
                                    


                                                
                         


                                               
                                





                                                                                       
          

                                               
            
                                                 
          
                    

 
                           
 






                                                                 
                                                                              
                    


















                                                                                                 
                                                                                                      

























                                                                                                              
                  


                        

 
                            
 
                                

                                                                         










                                                                                    
 




                                     
 
                   
                                        

                                           
 
                                    

                                                             
 
                                   
          


                                                  
                  


                                                                       
                            

                                                
                          






                                                                       
                            

                                                

                          
 
            

 
                                    
 




                                 
                                                                             



















                                                                                   


 









































































































                                                                                                                       


                                                                              
 







                                       


























































































                                                                                                      
                                                                                                                    







































                                                                                            
                            















                                                                             
                         
 

                                   
 
 
































                                                                                       
                    











































































































                                                                                               

                                                                              

                                





                                                        

                                  





                            
                          

































                                                               

                                 









































                                                                                                

                            






                                



                                  


















                                                                           
                                                   
                                                             







                                     







































































                                                                                                                                             
                          









                                                                                                                  
                                             
                                  
                            










                                                                                                               
                  
















                                                                              
          
 

                                


                                                    
 






                                         
 










                                                                                                                                                                                                               
          




                                               



                     



                                                                              
















                                                                                              
                                                                         
                                                                 
                                                                                            






                        
                  
 

                                             
                            
                    

                                  
                                                                                                     
                    
                                                                                                         


                                


                                                                                   
                    
                                                   

                                                                                                             











                           




                                


                                       
                                                                         











                                                                              











                                                                                                                                                    
                                      








                                                                                                                                                        

                                                          
                                                                                                                                                        

                          
















                                                                                                                                                                                       







                                                         

























                                                                                                                                                                        
                                                                                                                         










                                                                                                                                                                                            


                                             








                                                                              

                 































                                                                                
                          
                                                    
                                    
                                                        

                                  












                                                                                     

                   










































                                                                                
            

 












































                                                                           

                                        





                                                  



                                                       
                                                       
                                                                                           
                                                                                 






                                                                              
 

                                                      
          
                                                                                                 


            
                             
 

























                                                                                                                         

 

                                                                              
 














                                                    















































                                                                                            
                                                













                                                                                    


























                                                           
                        

 
                      
 








                                                                              
               

                                        
          
                    
            

 
                        
 









                                                                              
            
                                         
            
                                          
          




                                             

 


                                                                              

                             
                                                          



                                                          
                                                  
                            
                                                                            



                             
                                         


                                      
                             
 















                                                                              

 
 
                                                                              
 
                           
 
                              
          
                             
                  







                                                                         
                    



                     
 
      


                           
                          
                                  



                                          
                             

 
                       














                                    
                                   


                                                                  
                                                                  

                 
 
                                





                                                                      
 
                                   




                                                   



                                                     





                               
                             
                                                                            
                                                                  


                                                                               
                                                                               

                                                                
 
                                          
                                   
                                                          
                                     

                         
                                        












                                                 

                           
                                               
                                                  
                             






                                
                                                               





                                
                           


                 



                                                    
 
                              






                                  
                     
                     
                     


                                

                                  
                             
                                  

                                                   
                            
                                   
 




                                                  

                                                          



                                                                    





                                                                           










                                                                 
          
                              





                                                              
                                                                                            




                                            
                                                                                            




                                                                                            







                                                                       
 
                 
 

          
                           
    



                                                      
                                             
                                            
                                           
                               
                               
                                                                                                                                                                        
                                  
                                
                                                                                                                                                                          


                                  

                                                    
  
 
                                                                             
 
                   





                     

                              







                                          












                                                          
                                   
 
                             
                                                          

                                                                                                        





                                              
                   
                                                



                                                                           
#!/this/script/can/only/be/run/in/bash
#
# vim: ft=sh ts=4 sw=4 noet:
#
# -- UTF-8 --
#
# 設定用外部檔案:
#     (1) 若 .bash_title 存在且未設定自動修改視窗標題,則依照本檔案內定規則修改
#     (2) 若 .bash_addps 存在,則第一行的的內容會加到 colorprompting 變數,第二
#         行的內容會加到 nocolorprompting 變數

if [[ "$-" == *i* ]] ; then interactive_shell=1; fi

[ "$interactive_shell" ] && echo "Running .bash_include"
[ "$interactive_shell" ] && default_tty_setting="`stty -g`"
[ "$interactive_shell" ] && TTY="`tty`" && \
    if [[ "$TTY" =~ "/dev/tty"[1-9]+ ]]; then
        tty_short="#v${TTY:8}"
    elif [[ "$TTY" == "/dev/tty"* ]]; then
        tty_short="#${TTY:8}"
    elif [[ "$TTY" == "/dev/pty"* ]]; then
        tty_short="#p${TTY:8}"
    elif [[ "$TTY" == "/dev/hvc"* ]]; then
        tty_short="#h${TTY:8}"
    elif [[ "$TTY" == "/dev/pts"* ]]; then
        tty_short="#p${TTY:9}"
    elif [[ "$TTY" == "/dev/console" ]]; then
        tty_short="#c${TTY:12}"
    else
        unset tty_short
    fi


# Internal Variables

colorprompting='\[\e[1;31m\]\!\[\e[m\] \[\e[35m\]$tty_short\[\e[m\][\[\e[1;33m\]\u\[\e[m\]@\[\e[1;32m\]\h\[\e[m\] \[\e[1;36m\]\w\[\e[m\]]\[\e[44;37m\] \j \[\e[m\]'
nocolorprompting='\! $tty_short[\u@\h \w] \j '

if [ "$SSH_CONNECTION" ]
then
    colorprompting="\[\e[1;44m\]*\[\e[m\]$colorprompting"
    nocolorprompting="*$nocolorprompting"
fi

if [ "$EPREFIX" ]
then
    colorprompting="$colorprompting[\[\e[1;35m\]Prefix\[\e[m\]]"
    nocolorprompting="$nocolorprompting[Prefix]"
fi

if [ "$X_SCLS" ]
then
    scl_enabled="`echo "$X_SCLS" | sed 's/ *$//' | tr ' ' ','`"
    colorprompting="$colorprompting[\[\e[1;35m\]SCL:$scl_enabled\[\e[m\]]"
    nocolorprompting="$nocolorprompting[SCL:$scl_enabled]"
    unset scl_enabled
fi

if [ "$UNDER_JHBUILD" = "true" ] || [ "$CERTIFIED_GNOMIE" = "yes" ]
then
    colorprompting="$colorprompting[\[\e[1;35m\]JHBuild\[\e[m\]]"
    nocolorprompting="$nocolorprompting[JHBuild]"
fi

if [ "$ANDROID_BUILD_TOP" ]
then
    colorprompting="$colorprompting[\[\e[1;35m\]Android\[\e[m\]]"
    nocolorprompting="$nocolorprompting[Android]"
fi

if [ "$OSTYPE" = "cygwin" ]
then
    colorprompting="$colorprompting[\[\e[1;35m\]Cygwin\[\e[m\]]"
    nocolorprompting="$nocolorprompting[Cygwin]"
fi

if [ "$OSTYPE" = "msys" ]
then
    colorprompting="$colorprompting[\[\e[1;35m\]MSYS\[\e[m\]]"
    nocolorprompting="$nocolorprompting[MSYS]"
fi

if [ -f "$HOME/.bash_addps" ]
then
    exec 3< "$HOME/.bash_addps"
    read -u 3 -r oneline
    colorprompting="$oneline $colorprompting"
    read -u 3 -r oneline
    nocolorprompting="$oneline $nocolorprompting"
    exec 3<&-
    unset oneline
fi

colorprompting="${colorprompting}"'\[\e[41;37m\]$lasterror\[\e[m\]'
nocolorprompting="${nocolorprompting}"'$lasterror'

if [ "$WINDOW" ]
then
    colorprompting="$colorprompting<$WINDOW>"
    nocolorprompting="$nocolorprompting<$WINDOW>"
fi

if [ "$TMUX_PANE" ]
then
    colorprompting="$colorprompting$TMUX_PANE"
    nocolorprompting="$nocolorprompting$TMUX_PANE"
fi

if [[ "$PROMPT_COMMAND" != "S="* ]]; then
    if [ "$PROMPT_COMMAND" ]
    then
        PROMPT_COMMAND="; $PROMPT_COMMAND"
    fi
    PROMPT_COMMAND='S="$?"; [ "$S" != "0" ] && lasterror="($S)" || unset lasterror'"$PROMPT_COMMAND"
fi

colorprompting="${colorprompting}"'\$ '
nocolorprompting="${nocolorprompting}"'\$ '
colorsecondprompting="\[\e[36m\]-->\[\e[m\] "
nocolorsecondprompting="--> "

HISTSIZE=2147483647
HISTFILESIZE=2147483647
HISTCONTROL=ignoredups:ignorespace
HISTTIMEFORMAT="%F %T "
historycountfile="$HOME/.bash_history.count"
historybackupfile="$HOME/.bash_history.bak"

realpath_program="readlink -f"
bgrunfiledir="$HOME/tmp/bgrun-$USER"
trashdir="$HOME/trash"


# Environment Variables

export EDITOR=vim
export FCEDIT=vim
export VISUAL=vim
export PAGER=less
export GCC_COLORS=1


# Aliases: Replace common tools

alias ll='ls -lF'
alias lh='ls -lFh'
alias la='ls -lFa'
alias lA='ls -lFA'
alias rm='rm -i'
alias cp='cp -pi'
alias mv='mv -i'
alias jobs='jobs -l'
alias less='less -RS'

case "$OSTYPE" in
    *gnu*|*cygwin*|*msys*|*solaris*|*darwin*)
        alias ls='ls --color=always -F'
        ;;
    *freebsd*)
        alias ls='CLICOLOR=1 CLICOLOR_FORCE=1 ls -F'
        export LSCOLORS='ExGxFxdxCxDxDxhbadacad'
        ;;
esac

case "$OSTYPE" in
    *gnu*|*cygwin*|*msys*|*freebsd*|*netbsd*|*solaris*|*darwin*)
        alias grep='grep --color=always'
        ;;
esac


# Aliases: Non-aliased common tools (safe for use in script)

alias safe_ls='\ls'
alias safe_ln='\ln'
alias safe_cp='\cp'
alias safe_mv='\mv'
alias safe_rm='\rm'
alias safe_jobs='\jobs'
alias safe_less='\less'
alias safe_grep='GREP_OPTIONS= \grep'

case "$OSTYPE" in
    *openbsd*)
        alias safe_cp_verbose='safe_cp'
        alias safe_mv_verbose='safe_mv'
        alias safe_ln_verbose='safe_ln'
        safe_cp_verbose='cp'
        safe_mv_verbose='mv'
        safe_ln_verbose='ln'
        ;;
    *)
        alias safe_cp_verbose='safe_cp -v'
        alias safe_mv_verbose='safe_mv -v'
        alias safe_ln_verbose='safe_ln -v'
        safe_cp_verbose='cp -v'
        safe_mv_verbose='mv -v'
        safe_ln_verbose='ln -v'
        ;;
esac


# Aliases: Command Prompt

alias startcolor='PS1=$colorprompting; PS2=$colorsecondprompting'
alias stopcolor='PS1=$nocolorprompting; PS2=$nocolorsecondprompting'


# Aliases: Language

alias cccc='LANG=C;LANGUAGE=C;LC_ALL=C'
alias enus='LANG=en_US.UTF-8;LANGUAGE=en_US:en;LC_ALL=en_US.UTF-8'
alias big5='LANG=zh_TW.Big5;LANGUAGE=zh_TW:zh:en;LC_ALL=zh_TW.Big5'
alias zhtw='LANG=zh_TW.UTF-8;LANGUAGE=zh_TW:zh:en;LC_ALL=zh_TW.UTF-8'


# Aliases: Nice Format

alias ndate='date +%H:%M:%S---%A---%x'
alias npasswd="getent passwd | awk 'BEGIN {FS=\":\"} {printf \"%24s%3s%6s%6s %-28s%-18s>> %s\\n\",\$1,\$2,\$3,\$4,\$6,\$7,\$5}' | $PAGER"
alias ngroup="getent group | awk 'BEGIN {FS=\":\"} {printf \"%24s%3s%6s >> %s\\n\",\$1,\$2,\$3,\$4}' | $PAGER"


# Aliases: Terminal

alias savetty='default_tty_setting=`stty -g`'
alias resetty='stty $default_tty_setting'


# Aliases: Git, GNU Screen, Vim

alias git_log='git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=iso'
alias git_log_color='git log --color --graph --pretty=format:"%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%C(bold blue)<%an>%Creset" --abbrev-commit'
alias screen256='screen -T screen-256color'
alias vimhtml='vim -c "set ts=2" -c "set sw=2"'


# Functions: Overrided external commands to prevent misuse ###################

function git ()
{
    if [ "$1" = "commit" ]; then
        if [ "`command git config user.name`" = "LAN-TW" ]; then
            printf '==> \e[1;31mBASHRC ERROR\e[m: STOP USING THIS CRYPTIC NAME!\n'
            return 1
        fi
        if command git config user.name | safe_grep ' ' >/dev/null; then :;
        else
            printf '==> \e[1;31mBASHRC ERROR\e[m: Your real name does not contain spaces!\n'
            return 1
        fi
        if [[ "$PWD" == *gnome* ]] || [[ "$PWD" == *jhbuild* ]]; then
            if [[ "`command git config user.email`" == *gnome* ]]; then :;
            else
                printf '==> \e[1;31mBASHRC ERROR\e[m: Please use GNOME email in GNOME projects!\n'
                return 2
            fi
        fi
    fi
    command git "$@"
}


# Functions: Shared Internal Functions #######################################

function createdir_askmode ()
{
    newdir_mode="$2"
    if mkdir -p "$1"
    then
        echo "Directory $1 is created."
        printf "Change the mode of the directory... "
        read -i "$newdir_mode" -p ">>> Mode: " -e newdir_mode
        chmod "$newdir_mode" "$1"
    else
        echo "Cannot create directory $1!"
        return 1
    fi
}

function check_command_existent ()
{
    type "$1" &> /dev/null
    return $?
}

function is_file_type ()
{
    local filename="$1"
    local typename="$2"
    shift 2
    [ "`"$@" find "$filename" -maxdepth 0 -type "$typename"`" ] && return 0
    return 1
}

function get_file_size ()
{
    split_arguments "$@"
    "${prefixlist[@]}" du -s "${arglist[@]}" | {
        read -d "   " dirsize
        echo "$dirsize"
        read throwaway
    }
    unset arglist
    unset prefixlist
}

function get_executable_extension ()
{
    local lsloc="`command which ls`"
    local lsalt="`echo ${lsloc}.* | cut -d ' ' -f 1`"
    cmp "$lsloc" "$lsalt" &> /dev/null && echo ${lsalt:${#lsloc}} && return
}

function split_arguments ()
{
    local argcount=$#
    local -i i=0
    local prefix_start=0
    while [ "$1" ]
    do
        if [ "$prefix_start" = "0" ]
        then
            if [ "$1" = "--" ]
            then
                prefix_start=1
                i=0
                shift
                continue
            else
                arglist[$i]="$1"
            fi
        else
            prefixlist[$i]="$1"
        fi
        i=$i+1
        shift
    done
}


# Group: Background Tasks ####################################################

alias bgr=bgrun
alias bgv=bgview
alias bgl=bglist
alias bgc=bgcount
alias bgls=bglist
alias bgrm=bgclean

function bgrun ()
{
    [ "$#" = "0" ] && return 1
    [ '!' -d "$bgrunfiledir" ] && createdir_askmode "$bgrunfiledir" 0750
    local current_time=`date "+%Y%m%d-%H%M%S"`
    local cmdname=`echo "$1" | sed -e 's/-/_/g' -e 's/\\//_/g' -e 's/ /_/g'`
    if [ "`echo "$cmdname" | cut -c 1`" = "_" ]
    then
        cmdname=`echo "$cmdname" | cut -c 2-`
    fi
    local filename="$bgrunfiledir/$current_time-$cmdname"
    echo "Writing to $filename"
    {
        echo -n "$BASHPID " > "$filename"
        echo "$@" >> "$filename"
        exec "$@" &>> "$filename"
    } &
}

function bglist ()
{
    local viewtime=0
    [ "$1" = "--full" ] && viewtime=1
    {
        for i in `find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort`
        do
            [ "$viewtime" = "1" ] && echo "$i"
            head -n 1 "$i" | {
                local procpid
                local cmdline
                read -d ' ' procpid
                read cmdline
                printf "(%5d) %s\n" "$procpid" "$cmdline"
            }
        done
    } | {
        if [ "$viewtime" = "1" ]
        then
            echo " INDEX         TIME          PID   COMMAND"
            local readstat=0
            local -i i=1
            while true
            do
                local dateandtime_long
                local cmdline
                read dateandtime_long
                read cmdline
                [ "$?" '!=' "0" ] && break
                local dateandtime=`basename "$dateandtime_long"`
                local part_year="${dateandtime:0:4}"
                local part_month="${dateandtime:4:2}"
                local part_date="${dateandtime:6:2}"
                local part_hour="${dateandtime:9:2}"
                local part_minute="${dateandtime:11:2}"
                local part_second="${dateandtime:13:2}"
                printf '%6d' "$i"
                echo " $part_year-$part_month-$part_date $part_hour:$part_minute:$part_second $cmdline"
                i=$i+1
            done
        else
            echo " INDEX    PID   COMMAND"
            cat -n
        fi
    } | $PAGER
}

function bgview ()
{
    local -i yourchoice
    if [ "$1" = "" ]
    then
        yourchoice=`bgcount`
    else
        if [ "$1" -le "0" ]
        then
            yourchoice=$((`bgcount`+$1))
        else
            yourchoice=$1
        fi
    fi
    echo "Your choice is $yourchoice."
    local realfilename=`find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort | sed -n ${yourchoice}p`
    head -n 1 "$realfilename" | {
        read -d ' ' procpid
        read cmdline
        echo "PID: $procpid"
        echo "Command Line: $cmdline"
    }
    read -e -p "View '$realfilename' ? " confirm
    if [ "$confirm" = "n" ] || [ "$confirm" = "N" ]
    then
        return 1
    fi
    {
        printf "===> Process Information: "
        cat "$realfilename"
    } | $PAGER
}

function bgcount ()
{
    find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | cut -d - -f 2,3 | wc | awk '{print $2}'
}

function bgclean ()
{
    if [ "$1" = "all" ]
    then
        echo "Removing the directory $bgrunfiledir"
        rm -rf "$bgrunfiledir" &
        return 0
    else
        split_arguments "$@"
        local -i i=0
        while [ "${arglist[$i]}" ]
        do
            arglist[$i]="-e ${arglist[$i]}p"
            i=$i+1
        done
        local oneline
        find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort | sed -n ${arglist[*]} | {
            while read oneline
            do
                echo "Removing $oneline"
                rm -f "$oneline"
            done
        }
    fi
    unset arglist
    unset prefixlist
}

function bgdu ()
{
    local -i j=1
    {
        echo " INDEX     SIZE   PID   COMMAND"
        for i in `find "$bgrunfiledir" -maxdepth 1 -mindepth 1 | sort`
        do
            head -n 1 "$i" | {
                local procpid
                local cmdline
                read -d ' ' procpid
                read cmdline
                printf "%6d %8d (%5d) %s\n" "$j" \
                    "`get_file_size "$i"`" \
                    "$procpid" "$cmdline"
            }
            j=$j+1
        done
    } | $PAGER
}


# Group: Configuration Files #################################################

function fetch_remote_file ()
{
    local rval
    printf "==> Fetch remote file \e[1;33m$2\e[m as \e[1;35m$1\e[m ...\n"
    # cURL - cross-platform
    if check_command_existent curl; then
        curl -L -f -o "$1" "$2"
        rval=$?
    # wget - GNU, cross-platform
    elif check_command_existent wget; then
        wget --progress=dot -O "$1" "$2"
        rval=$?
    # fetch - FreeBSD
    elif check_command_existent fetch; then
        fetch -o "$1" "$2"
        rval=$?
    # ftp - NetBSD / OpenBSD
    elif check_command_existent ftp; then
        ftp -o "$1" "$2"
        rval=$?
    else
        echo "<== Sorry, I don't know how to fetch remote files on your system"
        return 1
    fi
    if [ "$rval" = "0" ]; then
        printf "<== \e[1;32mDone\e[m\n"
    else
        printf "<== \e[1;31mFailed\e[m\n"
    fi
    return $rval
}

function fetch_and_merge ()
{
    local merge_cmd
    local merge_cmd_prog
    local local_file="$1"
    local remote_file="$2"
    if fetch_remote_file "${local_file}.new" "${remote_file}"
    then
        if [ '!' -e "${local_file}" ]; then
            safe_mv_verbose -f "${local_file}.new" "${local_file}"
        else
            while true
            do
                echo ""
                cmp "${local_file}" "${local_file}.new" &> /dev/null && \
                    echo "Downloaded file is the same as installed one." && \
                    break
                printf "Configuration files update tool: "
                printf "Updating \e[1;35m${local_file}\e[m\n"
                echo ""
                echo " Install: Install the new version"
                echo " Keep:    Keep the old version"
                echo " Retry:   Give up downloaded file and try the next mirror"
                echo ""
                echo " Diff:    View the difference between versions"
                echo " Merge:   Merge two files by yourself"
                echo ""
                read -e -p "[I]nstall/(K)eep/(R)etry/(D)iff/(M)erge ? " merge_cmd
                case "${merge_cmd}" in
                    ''|I|i)
                        safe_mv_verbose -f "${local_file}.new" "${local_file}"
                        break
                        ;;
                    K|k)
                        rm -f "${local_file}.new"
                        break
                        ;;
                    R|r)
                        rm -f "${local_file}.new"
                        return 1
                        ;;
                    D|d)
                        diff -u "${local_file}" "${local_file}.new" | $PAGER
                        ;;
                    M|m)
                        read -e -p "Merge tool: " -i "$merge_cmd_prog" merge_cmd_prog
                        if $merge_cmd_prog "${local_file}" "${local_file}.new"; then
                            break
                        else
                            echo "Command is exited with error. Please try again."
                        fi
                        ;;
                    *)
                        printf " \e[33m*** Unknown command ***\e[m \n"
                        ;;
                esac
            done
        fi
        return 0
    fi
    return 1
}

function configfile_fetch ()
{
    local cgit_mirror_list=(
        "http://www.tfcis.org/~lantw44/cgit/configfile/plain"
        "http://phantom.tfcis.org/~lantw44/cgit/configfile/plain"
        "http://master.lant.com.tw/~lantw44/cgit/cgit.cgi/configfile/plain")
    local github_mirror_list=(
        "https://raw.github.com/lantw44/configfile"
        "http://raw.github.com/lantw44/configfile")
    local args
    local file_url
    local file_version
    local completed
    local -a file_name
    local -i i
    local -i j

    if [ "$1" ]; then
        file_version="$1"
    else
        file_version="master"
    fi

    args=("$@")
    for((i=1, j=0; i<$#; i++, j++)){
        file_name[$j]="${args[$i]}"
    }

    if [ -z "$file_name" ]; then
        file_name=("bash_include" "vimrc" "screenrc")
    fi

    for file in ${file_name[@]}
    do
        completed="false"

        for site in ${cgit_mirror_list[@]}
        do
            [ "$completed" = "true" ] && break
            file_url="$site/$file?id=$file_version"
            if fetch_and_merge "$HOME/.${file}" "$file_url"
            then
                completed="true"
                break
            fi
        done

        for site in ${github_mirror_list[@]}
        do
            [ "$completed" = "true" ] && break
            file_url="$site/$file_version/$file"
            if fetch_and_merge "$HOME/.${file}" "$file_url"
            then
                completed="true"
                break
            fi
        done

    done
}

function configfile_initial_setup ()
{
    cat >> ~/.bashrc << "EOF"
if [ -f ~/.bash_include ]; then
    . ~/.bash_include
fi
EOF
    if [[ "$OSTYPE" == *freebsd* ]] || [[ "$OSTYPE" == *FreeBSD* ]]; then
        cat >> ~/.bash_login << "EOF"
GET_TTY_NAME=`tty | cut -c 9`
[ "$GET_TTY_NAME" = 'v' ] && echo "Login from local virtual terminal: `tty`"
[ "$GET_TTY_NAME" = 'p' ] && echo "Login from pseudo terminal: `tty`"
[ "$GET_TTY_NAME" = '/' ] && echo "Login from pseudo terminal: `tty`"
unset GET_TTY_NAME
EOF
    fi
    cat >> ~/.bash_login << "EOF"
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
EOF
    echo "Completed. Type \`help_function' to know how to use!"
    for i in ~/.bashrc ~/.bash_login ~/.bash_profile ~/.shrc ~/.profile
    do
        grep -q -e HISTSIZE -e HISTFILESIZE "$i" 2>/dev/null && \
            echo "Warning: HISTSIZE or HISTFILESIZE is set in $i!" && \
            echo "History file features may not work"
    done
}


# Group: Fontconfig Tools ####################################################

function fontconfig_get_supported_lang ()
{
    local font_file
    local fc_query_cmd="fc-query"

    fc-list "$1" | cat -n
    read -e -p "  $1 >>> " choice
    font_file="`fc-list "$1" | sed -n ${choice}p | cut -d ':' -f 1`"
    echo "  $1 >>> $font_file"

    if [ "`fc-query "$font_file" | safe_grep '^ lang: ' | wc -l`" -gt 1 ]; then
        echo ''
        echo "  $font_file contains more than one font ..."
        fc-query "$font_file" | safe_grep '^    fullname: ' | (
            declare -i i=0
            while read oneline; do
                printf "%6d %s\n" "$i" "$oneline"
                i=i+1
            done )
        read -e -p "  Index of $1 >>> " choice
        fc_query_cmd="fc-query -i $choice"
    fi

    fontconfig_supported_lang="`$fc_query_cmd "$font_file" | safe_grep '^   lang: ' | cut -d : -f 2 | sed 's/ //'`"
}

function fontconfig_set_alias ()
{
    local alias_name="$1"
    local main_font="$2"
    local fallback_font="$3"
    local use_match
    local choice

    fontconfig_get_supported_lang "$main_font"
    local main_font_lang="$fontconfig_supported_lang"

    echo ''
    echo ''

    fontconfig_get_supported_lang "$fallback_font"
    local fallback_font_lang="$fontconfig_supported_lang"

    echo ''
    echo ''

    read -p 'Use <match> or <alias> ? ' choice
    case "$choice" in
        *M*|*m*)
            use_match="true"
            ;;
        *)
            use_match="false"
            ;;
    esac

    echo ''
    echo ''

    if [ "$use_match" = "true" ]; then
        echo '<match>'
        echo '  <test name="family"><string>'"$alias_name"'</string></test>'
        echo '  <edit name="family" mode="prepend" binding="strong">'
        echo '    <string>'"$main_font"'</string>'
        echo '  </edit>'
        echo '</match>'
    else
        echo '<alias>'
        echo '  <family>'"$alias_name"'</family>'
        echo '  <prefer><family>'"$main_font"'</family></prefer>'
        echo '</alias>'
    fi

    echo ''

    diff -u \
        <(echo "$main_font_lang" | tr '|' '\n' | sort) \
        <(echo "$fallback_font_lang" | tr '|' '\n' | sort) | \
        sed -e '/@@/d' -e '/---/d' -e '/+++/d' | \
        safe_grep  '\+' | sed 's/+//' | (

        while read lang; do
            if [ "$use_match" = "true" ]; then
                echo '<match>'
                echo '  <test name="family"><string>'"$alias_name"'</string></test>'
                echo '  <test name="lang" compare="contains"><string>'"$lang"'</string></test>'
                echo '  <edit name="family" mode="prepend" binding="strong">'
                echo '    <string>'"$fallback_font"'</string>'
                echo '  </edit>'
                echo '</match>'
            else
                echo '<alias>'
                echo '  <family>'"$alias_name"'</family>'
                echo '  <test name="lang" compare="contains"><string>'"$lang"'</string></test>'
                echo '  <prefer><family>'"$fallback_font"'</family></prefer>'
                echo '</alias>'
            fi
        done
    )

    unset fontconfig_supported_lang
}


# Group: New PATH Editor #####################################################

function newpath_init ()
{
    unset newpath
    local pathsp="$pathorgval"
    local pathentry
    local -i i
    eval pathsp='"${pathsp// /\\}"'
    pathsp="${pathsp//:/ }"
    i=0
    for pathentry in $pathsp
    do
        newpath[$i]="${pathentry//\\/ }"
        i=$i+1
    done
}

function newpath_gen ()
{
    local -i i
    pathmodval=""
    i=0
    while [ "${newpath[$i]}" ]
    do
        if [ "$i" != 0 ]; then pathmodval+=":"; fi
        pathmodval+="${newpath[$i]}"
        i=$i+1
    done
}

function path_editor ()
{
    local newpathvarname
    local badcommand
    local command
    local command_sub
    local command_sub2
    local should_continue="yes"
    local -i i

    if [ -z "$1" ]
    then
        newpathvarname="PATH"
    else
        newpathvarname="$1"
    fi

    eval pathorgval=\${${newpathvarname}}
    newpath_init

    while [ "$should_continue" ]
    do
        i=0
        echo -n $'\e[2J\e[0;0H'
        if [ "$badcommand" = "yes" ]; then
            printf " \e[33m*** Command \`$command' is unknown ***\e[m \n"
            badcommand=""
        fi
        echo "        New PATH Editor for BASH        "
        echo "========================================"
        echo "Environment Variable: $newpathvarname"
        echo "----------------------------------------"
        while [ "${newpath[$i]}" ]
        do
            echo "$i: ${newpath[$i]}"
            i=$i+1
        done
        [ "$i" = '0' ] && echo "(Empty or not declared)"
        echo "========================================"
        read -e -p "[A]ppend/(I)nsert/(D)elete/(E)dit/(M)ove/(S)wap/(R)eset/(Q)uit ? " command
        case "$command" in
            ''|A|a)
                read -e -p "Type a new entry: " newpath[$i]
                ;;
            I|i)
                read -e -p "Type a new entry: " command_sub
                if [ -z "$command_sub" ]; then continue; fi
                newpath_tmp=( "${newpath[@]}" )
                unset newpath
                newpath="$command_sub"
                i=0
                while [ "${newpath_tmp[$i]}" ]
                do
                    newpath[$i+1]="${newpath_tmp[$i]}"
                    i=$i+1
                done
                unset newpath_tmp
                ;;
            D|d)
                read -e -p "Index: " command_sub
                if [ -z "$command_sub" ]; then continue; fi
                i="$command_sub"
                i=$i+1
                while [ "${newpath[$i]}" ]
                do
                    newpath[$i-1]="${newpath[$i]}"
                    i=$i+1
                done
                unset newpath[$i-1]
                ;;
            E|e)
                read -e -p "Index: " command_sub
                read -e -p "Modify this entry: " -i "${newpath[$command_sub]}" newpath[$command_sub]
                ;;
            M|m)
                read -e -p "From: " command_sub
                read -e -p "To: " command_sub2
                if [ "$command_sub" -eq "$command_sub2" ]; then continue; fi
                cmdsubval="${newpath[$command_sub]}"
                if [ "$command_sub" -gt "$command_sub2" ]; then
                    i="$command_sub"
                    while [ "$i" -gt "$command_sub2" ]
                    do
                        newpath[$i]="${newpath[$i-1]}"
                        i=$i-1
                    done
                    newpath[$command_sub2]="$cmdsubval"
                else
                    i="$command_sub"
                    while [ "$i" -lt "$command_sub2" ]
                    do
                        newpath[$i]="${newpath[$i+1]}"
                        i=$i+1
                    done
                    newpath[$command_sub2]="$cmdsubval"
                fi
                unset cmdsubval
                ;;
            S|s)
                read -e -p "First entry: " command_sub
                read -e -p "Second entry: " command_sub2
                swaptmp="${newpath[$command_sub]}"
                newpath[$command_sub]="${newpath[$command_sub2]}"
                newpath[$command_sub2]="$swaptmp"
                unset swaptmp
                ;;
            R|r)
                read -e -p "Discard all changes [y/N] ? " command_sub
                if [ "$command_sub" = "y" ]; then
                    eval pathorgval=\${${newpathvarname}}
                    newpath_init
                fi
                ;;
            Q|q)
                newpath_gen
                eval export ${newpathvarname}=\"$pathmodval\"
                echo "${newpathvarname}=$pathmodval"
                history -s "${newpathvarname}=$pathmodval"
                should_continue=''
                ;;
            *)
                badcommand="yes"
                ;;
        esac
    done
    unset newpath
    unset pathorgval
    unset pathmodval
}

function ldpath_editor ()
{
    path_editor LD_LIBRARY_PATH
}


# Group: Trash ###############################################################

alias trash_put=trash_mv
alias trash_add=trash_mv
alias trash_list=trash_ls
alias trash_ct=trash_count
alias trash_restore=trash_recover
alias trash_rc=trash_recover
alias trash_drop=trash_rm
alias trash_clean=trash_rm

function trash_mv ()
{
    [ "$#" = "0" ] && return 1
    [ '!' -d "$trashdir" ] && createdir_askmode "$trashdir" 0700
    local original_path
    local current_time
    local -i i=0
    split_arguments "$@"
    while [ "${arglist[$i]}" ]
    do
        original_path="`"${prefixlist[@]}" $realpath_program "${arglist[$i]}"`"
        current_time=`date "+%Y%m%d-%H%M%S"`
        better_time=`date "+%Y-%m-%d %H:%M:%S"`
        dirname="`basename "${arglist[$i]}" | sed -e 's/-/_/g' -e 's/ /_/g'`"
        fulldirname="$trashdir/$current_time-$dirname"
        mkdir -p "$fulldirname"
        echo "Move: ${arglist[$i]} -> $fulldirname"
        "${prefixlist[@]}" mv "${arglist[$i]}" "$fulldirname"
        if [ "$?" = "0" ]
        then
            echo "$better_time" > "$fulldirname/information.date"
            echo "$original_path" > "$fulldirname/information.path"
        else
            rmdir "$fulldirname"
        fi
        i=$i+1
        shift
    done
    unset arglist
    unset prefixlist
}

function trash_ls ()
{
    local -i i=1
    local oneline
    find "$trashdir" -mindepth 1 -maxdepth 1 | sort | {
        while read oneline
        do
            printf "%6d %s %s\n" "$i" \
                "$(< "$oneline/information.date")" \
                "$(< "$oneline/information.path")"
            i=$i+1
        done
    } | $PAGER
}

function trash_cd ()
{
    [ -z "$1" ] && return 1
    cd `find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n $1p`
}

function trash_pushd ()
{
    [ -z "$1" ] && return 1
    pushd `find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n $1p`
}

function trash_recover ()
{
    [ -z "$1" ] && return 1
    split_arguments "$@"
    local -i i=0
    while [ "${arglist[$i]}" ]
    do
        arglist[$i]="-e ${arglist[$i]}p"
        i=$i+1
    done
    find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n ${arglist[*]} | {
        while read oneline
        do
            local fromfile="$oneline/`basename "$(< "$oneline/information.path")"`"
            local tofile="`dirname "$(< "$oneline/information.path")"`"
            if [ -e "$(< "$oneline/information.path")" ]
            then
                echo "Destination file exists."
                continue
            fi
            echo "Move: $fromfile -> $tofile"
            "${prefixlist[@]}" mv -f "$fromfile" "$tofile"
            if [ "$?" = "0" ]
            then
                echo "Remove: $oneline"
                rm -rf "$oneline"
            fi
        done
    }
    unset arglist
    unset prefixlist
}

function trash_rm ()
{
    split_arguments "$@"
    local -i i=0
    while [ "${arglist[$i]}" ]
    do
        arglist[$i]="-e ${arglist[$i]}p"
        i=$i+1
    done
    trash_dirname=`find "$trashdir" -mindepth 1 -maxdepth 1 | sort | sed -n ${arglist[*]} `
    echo 'Type rm -rf $trash_dirname to remove them.'
    unset arglist
    unset prefixlist
}

function trash_count ()
{
    find "$trashdir" -mindepth 1 -maxdepth 1 | wc | awk '{print $2}'
}

function trash_du ()
{
    split_arguments "$@"
    local oneline
    local -i i=1
    find "$trashdir" -maxdepth 1 -mindepth 1 | sort | {
        while read oneline
        do
            printf "%6d %8d %s\n" "$i" \
                "`get_file_size "$oneline" -- "${prefixlist[@]}"`" \
                "$(< "$oneline/information.path")"
            i=$i+1
        done
    } | $PAGER
    unset arglist
    unset prefixlist
}


# Group: Windows Executable Helpers ##########################################

function windows_exe_get_deps ()
{
    : ${OBJDUMP:="objdump"}
    LANG=C LC_ALL=C LANGUAGE= ${OBJDUMP} -p "$1" | \
        safe_grep 'DLL Name' | \
        sed 's|[    ]*DLL Name: \(.*\)$|\1|'
}

function windows_dll_is_builtin ()
{
    local builtin_dlls=(
        advapi32.dll
        comctl32.dll
        comdlg32.dll
        crypt32.dll
        dnsapi.dll
        dwmapi.dll
        gdi32.dll
        gdiplus.dll
        imm32.dll
        iphlpapi.dll
        kernel32.dll
        msimg32.dll
        msvcpp.dll
        msvcrt.dll
        mpr.dll
        netapi32.dll
        ntdll.dll
        ole32.dll
        oleaut32.dll
        opengl32.dll
        rpcrt4.dll
        setupapi.dll
        shell32.dll
        shlwapi.dll
        user32.dll
        usp10.dll
        version.dll
        winmm.dll
        winspool.drv
        ws2_32.dll
    )
    local i
    for ((i=0; i<"${#builtin_dlls[@]}"; i++)) {
        if [ "${1,,}" = "${builtin_dlls[$i],,}" ]; then
            return 0
        fi
    }
    return 1
}

function windows_exe_find_dlls ()
{
    local thisfile="$1"
    local verbose="$2"
    local level="$3"
    local found
    local i

    for dll in `windows_exe_get_deps "$1"`; do
        if windows_dll_is_builtin "$dll"; then
            continue
        fi

        found="false"

        if [ "${windows_exe_needed_dlls[$dll]}" ]; then
            if [ "$verbose" = "true" ]; then
                repeat "$level" echo -n '  '
                echo "$dll => ${windows_exe_needed_dlls[$dll]}"
            fi
            continue
        fi

        for ((i=0; i<"${#windows_exe_dll_dirs[@]}"; i++)) {
            if [ -f "${windows_exe_dll_dirs[$i]}/$dll" ]; then
                if [ "$verbose" = "true" ]; then
                    repeat "$level" echo -n '  '
                    echo "$dll => ${windows_exe_dll_dirs[$i]}/$dll"
                fi
                windows_exe_needed_dlls[$dll]="${windows_exe_dll_dirs[$i]}/$dll"
                windows_exe_find_dlls "${windows_exe_dll_dirs[$i]}/$dll" \
                    "$verbose" "$(( $level + 1 ))"
                found="true"
                break
            fi
        }

        if [ "$verbose" = "true" ] && [ "$found" = "false" ]; then
            repeat "$level" echo -n '  '
            echo "$dll => not found"
        fi
    done
}

function windows_exe_copy ()
{
    local dry_run="false"
    local verbose="false"

    if [ "$1" = "-n" ]; then
        dry_run="true"
        verbose="true"
        shift
    elif [ "$1" = "-p" ]; then
        dry_run="true"
        verbose="false"
        shift
    fi

    local exefile="$1"
    local destdir="$2"
    shift 2

    declare -a windows_exe_dll_dirs=("$@")
    declare -A windows_exe_needed_dlls

    if [ "$verbose" = "true" ]; then
        echo "$exefile"
    fi
    windows_exe_find_dlls "$exefile" "$verbose" "1"

    for i in "${!windows_exe_needed_dlls[@]}"; do
        if [ "$dry_run" = "false" ]; then
            echo "Copying ${windows_exe_needed_dlls[$i]} ..."
            mkdir -p "$destdir"
            safe_cp "${windows_exe_needed_dlls[$i]}" "$destdir"
        elif [ "$verbose" = "false" ]; then
            echo "${windows_exe_needed_dlls[$i]}"
        fi
    done

    unset windows_exe_dll_dirs
    unset windows_exe_needed_dlls
}


# Tools: Background Notify Daemon ############################################

function check_dmesg ()
{
    [ "$#" = "0" ] && return 1

    while true
    do
        cdm_previous_dmesg_buf="$cdm_current_dmesg_buf"
        cdm_current_dmesg_buf="`dmesg`"
        [ "$cdm_previous_dmesg_buf" '!=' "$cdm_current_dmesg_buf" ] && \
            [ "$cdm_first_run" = "0" ] && \
            echo '===> You should check the system message buffer <==='
        sleep $1
        [ "$?" '!=' "0" ] && return 1
        cdm_first_run=0
    done
}

function check_system_status ()
{
    [ "$#" = "0" ] && return 1

    filename_mail="$MAIL"
    filename_messages="/var/log/messages"
    filename_audit="/var/log/audit/audit.log"

    while true
    do
        previous_dmesg_buf="$current_dmesg_buf"
        current_dmesg_buf="`dmesg`"
        previous_mail_info="$current_mail_info"
        current_mail_info="`ls -l "$filename_mail"`"
        previous_messages_info="$current_messages_info"
        current_messages_info="`ls -l "$filename_messages"`"
        previous_audit_info="$current_audit_info"
        current_audit_info="`ls -l "$filename_audit"`"
        if [ "$first_run" = "0" ]
        then
            [ "$previous_dmesg_buf" '!=' "$current_dmesg_buf" ] && echo "===> The system message buffer is modified (dmesg) <==="
            [ "$previous_mail_info" '!=' "$current_mail_info" ] && echo "===> Your mailbox $filename_mail is modified <==="
            [ "$previous_messages_info" '!=' "$current_messages_info" ] && echo "===> $filename_messages is modified <==="
            [ "$previous_audit_info" '!=' "$current_audit_info" ] && echo "===> $filename_audit is modified <==="
        fi
        sleep $1
        first_run=0
    done
}


# Tools: Backup ##############################################################

function backup_file ()
{
    split_arguments "$@"
    local current_time=`date +%Y%m%d`
    local rootfilename
    local -i i=0
    local -i j
    while [ "${arglist[$i]}" ]
    do
        if [ '!' -f "${arglist[$i]}" ]
        then
            printf "\e[1;31mError\e[m: ${arglist[$i]} does not exist or it is not a regular file.\n"
            i=$i+1
            continue
        fi
        rootfilename="${arglist[$i]}.$current_time"
        if [ -e "$rootfilename" ]
        then
            j=0
            while [ "$j" -lt "10" ]
            do
                if [ -e "$rootfilename.$j" ]
                then
                    j=$j+1
                    continue
                else
                    history -s "$FUNCNAME" "$@"
                    "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename.$j"
                    history -s "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename.$j"
                    "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename.$j"
                    history -s "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename.$j"
                    break
                fi
            done
            if [ '!' "$j" -lt "10" ]
            then
                printf "\e[1;31mError\e[m: Can not create a backup file for ${arglist[$i]}.\n"
                printf "\e[1;33mPlease delete some backup file because I only use 0 - 9.\e[m\n"
            fi
        else
            history -s "$FUNCNAME" "$@"
            "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename"
            history -s "${prefixlist[@]}" \cp -p "${arglist[$i]}" "$rootfilename"
            "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename"
            history -s "${prefixlist[@]}" touch -r "${arglist[$i]}" "$rootfilename"
        fi
        i=$i+1
    done
    unset arglist
    unset prefixlist
}


# Tools: Compatibility #######################################################

function fbterm_chewing ()
{
    if [ -z "$1" ]; then
        fbterm -s 14 -- uim-fep -u chewing
    else
        local font_size="$1"
        shift
        fbterm -s "$font_size" "$@" -- uim-fep -u chewing
    fi
}
function gen_ms_inet_shortcut ()
{
    [ "$#" != "2" ] && {
        echo "Usage: $FUNCNAME filename url"
    } && return 1

    {
        echo "[InternetShortcut]"
        echo "URL=$2"
    } > "$1"
}

function unzip_nomac ()
{
    unzip "$@" -x '__MACOSX/*' '*.DS_Store'
    return $?
}


# Tools: GNU Screen ##########################################################

function mkscreenacl ()
{
    local screen_permit_command="select windowlist other meta detach reset hardcopy info redisplay lastmsg next prev xon xoff windows suspend help colon copy paste writebuf readbuf displays stuff attach"
    while [ "$1" '!=' '' ]
    do
        for i in $screen_permit_command
        do
            echo "aclchg $1 +x $i"
        done
        echo "aclchg $1 -rw \"\#?\""
        shift
    done
}




# Tools: Interactive #########################################################

function editlink ()
{
    local newdest
    local orgdest
    split_arguments "$@"
    local -i i=0
    while [ "${arglist[$i]}" ]
    do
        if is_file_type "${arglist[$i]}" "l" "${prefixlist[@]}"; then
            orgdest="`${prefixlist[@]} readlink "${arglist[$i]}"`"
            read -e -p "EditLink: ${arglist[$i]} -> " -i "$orgdest" newdest
        else
            printf "\e[1;33mWarning\e[m: ${arglist[$i]} is not a symbolic link.\n"
            i=$i+1
            continue
        fi
        if [ "$newdest" ] && [ "$newdest" '!=' "$orgdest" ]; then
            "${prefixlist[@]}" rm -f "${arglist[$i]}"
            "${prefixlist[@]}" ${safe_ln_verbose} -s "$newdest" "${arglist[$i]}"
        fi
        i=$i+1
    done
    unset arglist
    unset prefixlist
}

function mvfile ()
{
    local nocheck=0
    [ "$1" = "-n" ] && nocheck=1 && shift
    split_arguments "$@"
    local -i i=0
    while [ "${arglist[$i]}" ]
    do
        if [ "$nocheck" = "0" ] && [ '!' -e "${arglist[$i]}" ] && [ '!' -h "${arglist[$i]}" ]
        then
            printf "\e[33mWarning\e[m: ${arglist[$i]} does not exist. (Use -n to override)\n"
            i=$i+1
            continue
        fi
        echo "Old name: ${arglist[$i]}"
        read -p "New name: " -e -i "${arglist[$i]}" new_file_name
        if [ "$new_file_name" ] && [ "${arglist[$i]}" != "$new_file_name" ]
        then
            history -s "$FUNCNAME" "$@"
            "${prefixlist[@]}" ${safe_mv_verbose} -i "${arglist[$i]}" "$new_file_name"
            history -s "${prefixlist[@]}" ${safe_mv_verbose} -i "${arglist[$i]}" "$new_file_name"
        fi
        i=$i+1
    done
    unset arglist
    unset prefixlist
    unset new_file_name
}

function varset ()
{
    local varoldvalue
    local varnewvalue
    local noecho
    if [ "$1" = "-p" ]; then
        noecho="-s"
        shift
    fi
    while [ "$1" ]
    do
        eval varoldvalue=\${$1}
        read -r -e -p "$1=" -i "$varoldvalue" $noecho varnewvalue
        eval "$1"='"$varnewvalue"'
        shift
    done
}


# Tools: Memory ##############################################################

function get_memory_info ()
{
    case "$OSTYPE" in
        *linux*|*gnu*)
            local memtotal="`  safe_grep '^MemTotal:'  /proc/meminfo | awk '{print $2}'`"
            local memfree="`   safe_grep '^MemFree:'   /proc/meminfo | awk '{print $2}'`"
            local membuffers="`safe_grep '^Buffers:'   /proc/meminfo | awk '{print $2}'`"
            local memcached="` safe_grep '^Cached:'    /proc/meminfo | awk '{print $2}'`"
            local memslab="`   safe_grep '^Slab:'      /proc/meminfo | awk '{print $2}'`"
            local swaptotal="` safe_grep '^SwapTotal:' /proc/meminfo | awk '{print $2}'`"
            local swapfree="`  safe_grep '^SwapFree:'  /proc/meminfo | awk '{print $2}'`"
            test -z "$memslab" && memslab="0" # GNU/Hurd compatibility
            local memoldused=$(( $memtotal - $memfree ))
            local memused=$(( $memtotal - $memfree - $membuffers - $memcached - $memslab ))
            local swapused=$(( $swaptotal - $swapfree ))
            echo "Memory: $(( $memoldused / 1024 )) / $(( $memtotal / 1024  )) MB (`printf %2d $(( $memoldused * 100 / $memtotal  ))`%)"
            echo "Detail:"
            echo "    Used:    `printf %6d $(( $memused             / 1024 ))` MB (`printf %2d $(( $memused    * 100 / $memtotal  ))`%)"
            echo "    Buffers: `printf %6d $(( $membuffers          / 1024 ))` MB (`printf %2d $(( $membuffers * 100 / $memtotal  ))`%)"
            echo "    Cached:  `printf %6d $(( $memcached           / 1024 ))` MB (`printf %2d $(( $memcached  * 100 / $memtotal  ))`%)"
            if [ "$memslab" = "0" ]; then
                echo "    Slab:      not available"
            else
                echo "    Slab:    `printf %6d $(( $memslab         / 1024 ))` MB (`printf %2d $(( $memslab    * 100 / $memtotal  ))`%)"
            fi
            if [ "$swaptotal" = "0" ]; then
                echo "Swap: not available"
            else
                echo "Swap: $(( $swapused / 1024 )) / $(( $swaptotal / 1024 )) MB (`printf %2d $(( $swapused   * 100 / $swaptotal ))`%)"
            fi
            ;;
        *freebsd*)
            local mempagesize="` sysctl -n hw.pagesize`"
            local mempagecount="`sysctl -n vm.stats.vm.v_page_count`"
            local memactive="`   sysctl -n vm.stats.vm.v_active_count`"
            local meminactive="` sysctl -n vm.stats.vm.v_inactive_count`"
            local memwire="`     sysctl -n vm.stats.vm.v_wire_count`"
            local memcache="`    sysctl -n vm.stats.vm.v_cache_count`"
            local membuffer="`   sysctl -n vfs.bufspace`"
            local memfree="`     sysctl -n vm.stats.vm.v_free_count`"
            local swapenabled="` sysctl -n vm.swap_enabled`"
            echo "Memory (Active):   `printf %6d $(( $memactive    * $mempagesize / 1048576))` MB (`printf %2d $(( $memactive   * 100 / $mempagecount ))`%)"
            echo "Memory (Inactive): `printf %6d $(( $meminactive  * $mempagesize / 1048576))` MB (`printf %2d $(( $meminactive * 100 / $mempagecount ))`%)"
            echo "Memory (Wired):    `printf %6d $(( $memwire      * $mempagesize / 1048576))` MB (`printf %2d $(( $memwire     * 100 / $mempagecount ))`%)"
            echo "Memory (Cache):    `printf %6d $(( $memcache     * $mempagesize / 1048576))` MB (`printf %2d $(( $memcache    * 100 / $mempagecount ))`%)"
            echo "Memory (Buffer):   `printf %6d $(( $membuffer                   / 1048576))` MB (`printf %2d $(( $membuffer   * 100 / $mempagecount / $mempagesize ))`%)"
            echo "Memory (Free):     `printf %6d $(( $memfree      * $mempagesize / 1048576))` MB (`printf %2d $(( $memfree     * 100 / $mempagecount ))`%)"
            echo "Total Memory:      `printf %6d $(( $mempagecount * $mempagesize / 1048576))` MB"
            if [ "$swapenabled" = "1" ]; then
                echo ""
                echo "Swap devices:"
                swapinfo -m
            else
                echo "Swap: not enabled"
            fi
            ;;
        *netbsd*)
            local mempagesize="` sysctl -n hw.pagesize`"
            local mempagecount="`vmstat -t | tail -n 1                            | awk '{print $5}'`"
            local memactive="`   vmstat -s | safe_grep 'pages active$'            | awk '{print $1}'`"
            local meminactive="` vmstat -s | safe_grep 'pages inactive$'          | awk '{print $1}'`"
            local memwired="`    vmstat -s | safe_grep 'pages wired$'             | awk '{print $1}'`"
            local memexec="`     vmstat -s | safe_grep 'cached executable pages$' | awk '{print $1}'`"
            local memfile="`     vmstat -s | safe_grep 'cached file pages$'       | awk '{print $1}'`"
            local memfree="`     vmstat -s | safe_grep 'pages free$'              | awk '{print $1}'`"
            echo "Memory (Active):   `printf %6d $(( $memactive    * $mempagesize / 1048576))` MB (`printf %2d $(( $memactive   * 100 / $mempagecount ))`%)"
            echo "Memory (Inactive): `printf %6d $(( $meminactive  * $mempagesize / 1048576))` MB (`printf %2d $(( $meminactive * 100 / $mempagecount ))`%)"
            echo "Memory (Wired):    `printf %6d $(( $memwired     * $mempagesize / 1048576))` MB (`printf %2d $(( $memwired    * 100 / $mempagecount ))`%)"
            echo "Memory (Exec):     `printf %6d $(( $memexec      * $mempagesize / 1048576))` MB (`printf %2d $(( $memexec     * 100 / $mempagecount ))`%)"
            echo "Memory (File):     `printf %6d $(( $memfile      * $mempagesize / 1048576))` MB (`printf %2d $(( $memfile     * 100 / $mempagecount ))`%)"
            echo "Memory (Free):     `printf %6d $(( $memfree      * $mempagesize / 1048576))` MB (`printf %2d $(( $memfree     * 100 / $mempagecount ))`%)"
            echo "Total Memory:      `printf %6d $(( $mempagecount * $mempagesize / 1048576))` MB"
            echo ""
            echo "Swap devices"
            swapctl -lm
            ;;
        *openbsd*)
            local mempagesize="` sysctl -n hw.pagesize`"
            local mempagecount="`vmstat -s | safe_grep 'pages managed$'           | awk '{print $1}'`"
            local memactive="`   vmstat -s | safe_grep 'pages active$'            | awk '{print $1}'`"
            local meminactive="` vmstat -s | safe_grep 'pages inactive$'          | awk '{print $1}'`"
            local memwired="`    vmstat -s | safe_grep 'pages wired$'             | awk '{print $1}'`"
            local memcache="`    top -n | grep '^Memory:' | sed -n -e '1s/.*Cache: \([0-9]*\)M.*/\1/' -e 1p`"
            local memfree="`     vmstat -s | safe_grep 'pages free$'              | awk '{print $1}'`"
            echo "Memory (Active):   `printf %6d $(( $memactive    * $mempagesize / 1048576))` MB (`printf %2d $(( $memactive   * 100 / $mempagecount ))`%)"
            echo "Memory (Inactive): `printf %6d $(( $meminactive  * $mempagesize / 1048576))` MB (`printf %2d $(( $meminactive * 100 / $mempagecount ))`%)"
            echo "Memory (Wired):    `printf %6d $(( $memwired     * $mempagesize / 1048576))` MB (`printf %2d $(( $memwired    * 100 / $mempagecount ))`%)"
            echo "Memory (Cache):    `printf %6d $(( $memcache                             ))` MB (`printf %2d $(( $memcache    * 104857600 / $mempagecount / $mempagesize))`%)"
            echo "Memory (Free):     `printf %6d $(( $memfree      * $mempagesize / 1048576))` MB (`printf %2d $(( $memfree     * 100 / $mempagecount ))`%)"
            echo "Total Memory:      `printf %6d $(( $mempagecount * $mempagesize / 1048576))` MB"
            echo ""
            echo "Swap devices"
            swapctl -lk
            ;;
        *solaris*)
            top -n | sed -n -e 5p
            ;;
        *)
            echo "Unsupported operating system."
            ;;
    esac
}


# Tools: Packages ############################################################

function rpmdu ()
{
    local div_base=1
    local div_name="KB"
    local total=0
    if [ "`echo "$1" | cut -c 1`" = "-" ]
    then
        local optname=`echo "$1" | cut -c 2-`
        case "$optname" in
            "k")
                ;;
            "m")
                div_base=1024
                div_name=MB
                ;;
            "g")
                div_base=1048576
                div_name=GB
                ;;
            *)
                echo "Usage: $FUNCNAME [OPTION] package_name..."
                echo "    -k KB"
                echo "    -m MB"
                echo "    -g GB"
                return 1
                ;;
        esac
        shift
    fi

    while [ "$1" ]
    do
        rpm -ql "$1" | {
            while read oneline
            do
                if [ -f "$oneline" ]
                then
                    du -k "$oneline"
                fi
            done
        } | {
            while read -d $'\t' filesize
            do
                total=$((${total}+${filesize}))
                read
            done
            printf "%9d %s %s\n" "$(($total/$div_base))" "$div_name" "$1"
        }

        shift
    done
}

function rpmsize ()
{
    local div_base=1
    local div_name="Bytes"
    local total=0
    local filesize
    if [ "`echo "$1" | cut -c 1`" = "-" ]
    then
        optname=`echo "$1" | cut -c 2-`
        case "$optname" in
            "b")
                ;;
            "k")
                div_base=1024
                div_name=KB
                ;;
            "m")
                div_base=1048576
                div_name=MB
                ;;
            "g")
                div_base=1073741824
                div_name=GB
                ;;
            *)
                echo "Usage: $FUNCNAME [OPTION] package_name..."
                echo "    -b Byte"
                echo "    -k KB"
                echo "    -m MB"
                echo "    -g GB"
                return 1
                ;;
        esac
        shift
    fi
    while [ "$1" ]
    do
        total=0
        filesize=`rpm -q "$1" --queryformat "%{SIZE} "`
        for i in $filesize
        do
            total=$((${total}+${i}))
        done
        printf "%12d %s %s\n" "$(($total/$div_base))" "$div_name" "$1"
        shift
    done
}

function rpm_source_repackage ()
{
    local tmptop="`mktemp --tmpdir -d rpm_source_repackage.XXXXXXXXXX`"
    local args=("$@")
    local srpm="$1"
    local -a cmd
    local -i i

    echo "==> Installing source packages: $1"
    rpm --define "_topdir $tmptop" -ivh "$1"
    safe_cp "$tmptop/SPECS"/*.spec "$tmptop/SOURCES"

    echo "==> Entering directory: $tmptop/SOURCES"
    pushd "$tmptop/SOURCES" >/dev/null

    for((i=1; i<$#; i++)) {
        if [ "${args[$i]}" = "--" ]; then
            if [ "$cmd" ]; then
                echo "==> Running command: ${cmd[@]}"
                "${cmd[@]}"
                cmd=()
            fi
        else
            cmd+=("${args[$i]}")
        fi
    }

    if [ "$cmd" ]; then
        echo "==> Running command: ${cmd[@]}"
        "${cmd[@]}"
    fi

    safe_cp "$tmptop/SOURCES"/*.spec "$tmptop/SPECS"

    echo "==> Rebuilding source packages"
    rpmbuild --define "_topdir $tmptop" -bs "$tmptop/SPECS"/*.spec

    echo "==> Leaving directory: $tmptop/SOURCES"
    popd >/dev/null

    echo "==> Copying built source packages"
    safe_cp_verbose -i "$tmptop/SRPMS"/*.src.rpm .
    rm -rf "$tmptop"
}

function freebsd_ports_should_rebuild ()
{
    if [ -f "/var/db/pkg/local.sqlite" ]; then
        WITH_PKGNG="true"
        pkg_which_cmd="pkg which -q"
    else
        pkg_which_cmd="pkg_info -q -W"
    fi
    reqcomp=$(ldd -f '%a %o %p\n' \
        /usr/local/bin/* /usr/local/sbin/* \
        /usr/local/lib/* /usr/local/libexec/* \
        /usr/local/libexec/*/* \
        2>/dev/null | safe_grep 'not found' | \
        { while read oneline; do echo ${oneline} | cut -d ' ' -f 1; done; } | uniq)
    reqpkg=$({ for i in $reqcomp; do $pkg_which_cmd $i; done } | sort | uniq)
    echo $reqpkg
}


# Tools: Personal Files ######################################################

function check_important_files ()
{
    important_files="$HOME/.screenrc $HOME/.vimrc"
    for i in $important_files
    do
        [ '!' -f "$i" ] && printf "\e[1;31mWarning\e[m: \e[1;33m$i\e[m does not exist.\n"
    done
}

function prehistory_backup ()
{
    echo "Checking your current history file"
    local -i currentcount="`wc -l < "$HISTFILE"`"
    currentcount="${currentcount/ */}"
    [ '!' -f "$historycountfile" ] && touch "$historycountfile"
    local -i previoushistorycount="$(< "$historycountfile")"
    if [ "$currentcount" -lt "$previoushistorycount" ]
    then
        printf "\e[1;31mWarning\e[m: Your $HISTFILE may be TRUNCATED OR OVERWRITTEN BY OTHER PROGRAMS!\n"
        printf "Note: \e[1;33m$currentcount\e[m < $previoushistorycount\n"
        echo "Your $historycountfile and $historybackupfile will not be overwritten until this problem is fixed."
        echo " 1. Check your $HISTFILE."
        echo " 2. Edit your $HISTFILE manually if some unexpected changes are found."
        echo "    (You may need $historybackupfile to do it) "
        echo " 3. Remove the file $historycountfile."
        echo " 4. Run the command \`prehistory_backup' again."
        return 3
    fi
    echo -n "Backing up your current history file ($previoushistorycount -> $currentcount, "
    if [ "$previoushistorycount" = "$currentcount" ]
    then
        echo "no modification)"
    else
        echo "+$[$currentcount-$previoushistorycount])"
    fi
    echo "$currentcount" > "$historycountfile"
    safe_cp -f "$HISTFILE" "$historybackupfile"
}


# Tools: Programming #########################################################

function chr ()
{
    printf $(printf '\\%03o\\n' "$1")
}

function hex ()
{
    printf "0x%02x\n" "$1"
}

function ord ()
{
    printf "%d 0x%02x 0%03o\n" "'$1" "'$1" "'$1"
}

function argv0 ()
{
    local execname="$1"
    local argv0="$2"
    shift 2
    ( exec -a "$argv0" "$execname" "$@" )
}

function compile_all ()
{
    local noask=0
    local mycc="${CC}"
    local mycxx="${CXX}"
    local myexe="`get_executable_extension`"
    local newCFLAGS
    local newCXXFLAGS
    local newLDFLAGS
    [ "$1" = '' ] && echo "Which file(s) do you want to compile? " && return 1
    [ "$1" = "-n" ] && noask=1
    if [ "$noask" = "0" ]; then
        read -e -p "CFLAGS: " -i "$CFLAGS" newCFLAGS
        read -e -p "CXXFLAGS: " -i "$CXXFLAGS" newCXXFLAGS
        read -e -p "LDFLAGS: " -i "$LDFLAGS" newLDFLAGS
        [ "$newCFLAGS" '!=' '' ] && CFLAGS=$newCFLAGS
        [ "$newCXXFLAGS" '!=' '' ] && CXXFLAGS=$newCXXFLAGS
        [ "$newLDFLAGS" '!=' '' ] && LDFLAGS=$newLDFLAGS
    else
        shift
    fi
    [ -z "${mycc}" ] && mycc=cc
    [ -z "${mycxx}" ] && mycxx=c++
    while [ "$1" '!=' '' ]
    do
        local targetfile="`echo "$1" | sed 's|\(.*\)\..*|\1|'`$myexe"
        local suffix="`echo "$1" | sed 's|.*\.\(.*\)|\1|'`"
        if [ -f "$1" ]; then
            true
        else
            printf \
            "\e[1;33mWarning\e[0m: $1 Non-existent file or not a regular file\n"
            shift ; continue
        fi
        [ "$targetfile" = "$1" ] && shift && continue
        case "$suffix" in
            c)
                echo "[${mycc}] $1 -> $targetfile"
                ${mycc} $CFLAGS "$1" $LDFLAGS -o "$targetfile"
                ;;
            cpp|CPP|cp|cxx|cc|c++|C)
                echo "[${mycxx}] $1 -> $targetfile"
                ${mycxx} $CXXFLAGS "$1" $LDFLAGS -o "$targetfile"
                ;;
            *)
                printf "$1: Unknown suffix (\e[1;33mskipped\e[0m)\n"
                ;;
        esac
        [ "$?" '!=' "0" ] && printf \
            '\e[1;31mError\e[0m while compiling file\n'
        shift
    done
    return 0
}

function cc_define ()
{
    local -i i
    local mycpp="${CPP}"
    if [ -z "${mycpp}" ]; then
        if [ -z "${CC}" ]; then
            mycpp="cpp"
        else
            mycpp="${CC} -E"
        fi
    fi

    split_arguments "$@"

    {
        (( i = 0 ))
        while [ "${prefixlist[$i]}" ]; do
            echo "#include <${prefixlist[$i]}>"
            (( i++ ))
        done
        (( i = 0 ))
        while [ "${arglist[$i]}" ]; do
            echo "${arglist[$i]}"
            (( i++ ))
        done
    } | ${mycpp} - | tail -n "${#arglist[@]}"
    unset arglist
    unset prefixlist
}

function cxx_define ()
{
    CPP="${CXXCPP}" CC="${CXX:-c++ -x c++}" cc_define "$@"
}


# Tools: Repeated Tasks ######################################################

function repeat ()
{
    local repeat_times="$1"
    local i
    shift
    for ((i=0; i<repeat_times; i++))
    do
        "$@"
    done
}

function wait_success ()
{
    local i=1
    until "$@"; do echo "Failed ... $i"; ((i++)) ; done
}


# Tools: Security ############################################################

function keep_sudo_credential ()
{
    if [ "$1" ]
    then
        update_sudo_interval="$1"
    else
        update_sudo_interval="280"
    fi
    while true
    do
        sudo -v
        sleep "$update_sudo_interval"
    done
}


# Tools: Terminal ############################################################

function get_terminal_size ()
{
    # ESC 7              = 儲存游標位置和屬性
    # ESC [r             = 啟用全螢幕捲動
    # ESC [{row};{col}H  = 移動游標
    # ESC 6n             = 回報目前游標位置
    # ESC 8              = 還原游標位置和屬性
    echo -n $'\e7\e[r\e[999;999H\e[6n\e8' 1>&2
    read -s -d R getsize
    echo $getsize | sed 's#..\([0-9]*\);\([0-9]*\)#LINES=\1 COLUMNS=\2#'
}

function set_terminal_size ()
{
    eval "export `get_terminal_size`"
    stty cols $COLUMNS rows $LINES
}

function set_console_title ()
{
    case "$TERM" in
        screen*)
            printf "\033]0;"
            echo -n "$*"
            printf "\033\\"
            ;;
        xterm*)
            printf "\033]0;"
            echo -n "$*"
            printf "\007"
            ;;
        *)
            echo "Your terminal may not have the hardstatus line."
            echo "Note: TERM=$TERM"
            ;;
    esac
}


# Tools: Web #################################################################

function convert_to_html ()
{
    while [ "$1" '!=' '' ]
    do
        for i in "$1"
        do
            vim $i -c 'set background=dark' \
                -c 'highlight PreProc ctermfg=darkcyan' \
                -c "$BEFORE_CONVERT_TO_HTML" \
                -c "$BEFORE_CONVERT_TO_HTML1" \
                -c "$BEFORE_CONVERT_TO_HTML2" \
                -c TOhtml \
                -c :w \
                -c :qa
        done
        shift
    done
}


# Help

alias helpf='help_function'
alias helpm='help_myself'
alias helpa='help_aliases'
alias help_aliases='help_function'

function print_iconv ()
{
    [ "$1" = "$2" ] && cat && return 0
    iconv -f "$1" -t "$2"
}

function help_myself ()
{
    echo "argc = $#"
    echo "argv[0] = $0"
    i=1
    while [ "$1" ]
    do
        echo "argv[$i] = $1"
        i=$(($i+1))
        shift
    done
}

function help_function ()
{
    [ "$#" = "0" ] && {
        cat << "ENDHELPMSG"
 <<< Help >>>
    help_myself [arguments ...]                            (helpm)
    help_function [functions ...]                          (helpf)
    help_aliases                                           (helpa)
    help_obsolete
 x  print_iconv

 <<< Group: Background Tasks >>>
    bgrun command [arguments ...]                          (bgr)
    bglist [--full]                                        (bgl, bgls)
    bgview [number]                                        (bgv)
    bgclean [all | numbers ...]                            (bgrm)
    bgcount                                                (bgc)
    bgdu

 <<< Group: Configuration Files >>>
    configfile_fetch [git_tag [file_name_list ...]]
    configfile_initial_setup
 x  fetch_remote_file local_file_name remote_url
 x  fetch_and_merge local_file_name remote_url

 <<< Group: Fontconfig Tools >>>
    fontconfig_set_alias name main_font fallback_font
 x  fontconfig_get_supported_lang font_name

 <<< Group: New PATH Editor >>>
    path_editor [variable]
    ldpath_editor
 x  newpath_init
 x  newpath_gen

 <<< Group: Trash Manager >>>
    trash_mv [filenames ...] [-- sudo_prefix ...]     (trash_put, trash_add)
    trash_ls                                          (trash_list)
    trash_cd number
    trash_pushd number
    trash_recover numbers ... [-- sudo_prefix ...]    (trash_restore, trash_rc)
    trash_rm numbers ...                              (trash_drop, trash_clean)
    trash_count                                       (trash_ct)
    trash_du [-- sudo_prefix ...]

 <<< Group: Windows Executable Helpers >>>
    windows_exe_get_deps dll_or_exe
    windows_exe_copy [-n|-p] dll_or_exe destdir libdir ...
 x  windows_dll_is_builtin dll_or_exe
 x  windows_exe_find_dlls

 <<< Tools: Background Notify Daemon >>>
    check_dmesg seconds
    check_system_status seconds

 <<< Tools: Backup >>>
    backup_file filename ... [-- sudo_prefix ...]

 <<< Tools: Compatibility >>>
    fbterm_chewing [size] [arguments ...]
    gen_ms_inet_shortcut filename url
    unzip_nomac filenames ...

 <<< Tools: GNU Screen >>>
    mkscreenacl usernames ...

 <<< Tools: Interactive >>>
    editlink filenames ... [-- sudo_prefix ...]
    mvfile [-n] filenames ... [-- sudo_prefix ...]
    varset [-p] variables ...

 <<< Tools: Memory >>>
    get_memory_info

 <<< Tools: Packages >>>
    rpmdu [-kmg] packages ...
    rpmsize [-bkmg] packages ...
    rpm_source_repackage srpm -- command1 ... [-- command2 ...]
    freebsd_ports_should_rebuild

 <<< Tools: Personal Files >>>
    check_important_files
    prehistory_backup

 <<< Tools: Programming >>>
    chr number
    hex number
    ord character
    argv0 executable arguments ... (include argv[0])
    compile_all [-n] filenames ...
    cc_define macro [-- included_headers ...]
    cxx_define macro [-- included_headers ...]

 <<< Tools: Repeated Tasks >>>
    repeat times arguments ...
    wait_success arguments ...

 <<< Tools: Security >>>
    keep_sudo_credential [seconds]

 <<< Tools: Terminal >>>
    get_terminal_size
    set_terminal_size
    set_console_title

 <<< Tools: Web >>>
    convert_to_html filename ...

 <<< Shared Internal Functions >>>
 x  createdir_askmode dirname
 x  check_command_existent program
 x  is_file_type filename type [-- sudo_prefix ...]
 x  get_file_size filename [-- sudo_prefix ...]
 x  get_executable_extension
 x  split_arguments [arguments ...]

 <<< Aliases: Command Prompt >>>
    startcolor    - Enable colorful PS1 prompting
    stopcolor     - Disable colorful PS1 prompting

 <<< Aliases: Git >>>
    git_log       - Show git log in a more compact format
    git_log_color - Show git log in a more colorful format

 <<< Aliases: GNU Screen >>>
    screen256     - Start GNU Screen and set TERM to screen-256color

 <<< Aliases: Language >>>
    big5          - Set Language and character sets to Taiwan Chinese Big5
    cccc          - Set Language and character sets to 7-bit ASCII
    enus          - Set Language and character sets to US English UTF-8
    zhtw          - Set Language and character sets to Taiwan Chinese UTF-8

 <<< Aliases: Nice Format >>>
    ndate         - Format the output of `date'
    npasswd       - Format the output of `getent passwd'
    ngroup        - Format the output of `getent group'

 <<< Aliases: Terminal >>>
    savetty       - Save current terminal mode
    resetty       - Reset to last saved terminal mode

 <<< Aliases: Vim >>>
    vimhtml       - Start Vim and set tabstop and shiftwidth to 2
ENDHELPMSG
    } | $PAGER && return 0
    local current_charset=`echo "$LC_ALL" | cut -d . -f 2`
    local -i i
    while [ "$1" ]
    do
        case "$1" in
            help_myself|helpm)
                cat << "ENDHELPMSG" | print_iconv "UTF-8" "$current_charset"
help_myself
    一個測試命令列的小函式
ENDHELPMSG
                ;;
            help_function|helpf)
                cat << "ENDHELPMSG" | print_iconv "UTF-8" "$current_charset"
help_function
    顯示 .bash_include 提供的額外函式清單
    註:前方加上「x」符號者表示此為內部使用的函式,不宜直接使用
ENDHELPMSG
                ;;
            *)
                echo "Help message for $1 is not found"
                ;;
        esac
        shift
    done
}


# Doing something

umask 0022

if [ "$interactive_shell" ]
then
    echo "Running interactive shell configuration"
    check_important_files
    startcolor
    prehistory_backup
    bind '"\e[A":history-search-backward'
    bind '"\e[B":history-search-forward'
    if [ -e "$HOME/.bash_title" ]; then
        case "$TERM" in
            xterm*)
                PROMPT_COMMAND="$PROMPT_COMMAND"'; printf "\033]0;%s@%s:%s (%s)\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" "`date "+%H:%M:%S"`"'
                ;;
            screen*)
                PROMPT_COMMAND="$PROMPT_COMMAND"'; printf "\033]0;%s@%s:%s (%s)\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}" "`date "+%H:%M:%S"`"'
                ;;
        esac
    fi
    [ "$TERM" = xterm ] && TERM=xterm-256color
    [ "$TERM" = screen ] && TERM=screen-256color
fi

[ "$interactive_shell" ] && echo "Setting shell options, completions, limits"

shopt -s histappend
shopt -s checkwinsize
shopt -s checkjobs
shopt -s checkhash
shopt -s cmdhist
shopt -s mailwarn

complete -A alias helpa
complete -A alias help_aliases
complete -A command check_command_existent
complete -A directory createdir_askmode
complete -A function helpf
complete -A function help_function
complete -A variable varset
complete -A variable path_editor
complete -A user mkscreenacl

if check_command_existent _command; then
    complete -F _command wait_success
fi

if check_command_existent _screen; then
    complete -F _screen screen256
fi

if check_command_existent _rpmdev_installed_packages; then
    complete -F _rpmdev_installed_packages rpmdu
    complete -F _rpmdev_installed_packages rpmsize
fi

ulimit -S -c unlimited 2> /dev/null

[ "$interactive_shell" ] && {
    if [ "$WINDOW" ] && type screen &> /dev/null; then
        if [ "`screen --version | sed 's/^Screen version 4\.\([0-9]*\).*$/\1/'`" -ge "1" ]; then
            echo "Setting options for GNU screen >= 4.1.0"
            screen -X cjkwidth off
        fi
    fi
}

[ "$interactive_shell" ] && {
    echo "Done"
    if [ "$UID" = "0" ] || [ "$EUID" = "0" ]
    then
        printf "\nNote: You may be \e[1;32mprivileged\e[m now!\n\n"
    fi
}