Comando custom help / man-like (para lembretes)

2

Muitas vezes acabo em uma situação em que não uso um comando por um tempo, mas de repente preciso usá-lo; e preciso percorrer várias páginas de ajuda até construir a linha de comando que desejo. Caso em questão: ocasionalmente eu preciso usar nmcli ; e, em seguida, preciso verificar novamente nmcli nm help e nmcli con help várias vezes, até que eu me lembre de que tipo de comando eu preciso.

O que eu fiz então, é basicamente documentar um pouco disso em um arquivo de texto; o problema é que, em geral, eu salvo no Desktop; então de vez em quando eu limpo os arquivos do Desktop, então eu acabo pensando "ah, eu realmente não uso nmcli-examples.txt tanto assim, deixe-me mover este aqui também"; então quando eu precisar dele novamente, eu tenho que emitir um achado primeiro (desde que eu possa lembrar o nome do arquivo para procurar).

Então, eu estava pensando - criar um script que: teria um conjunto de locais padrão (por exemplo, ~/customhelp ), onde seria possível manter especificamente esses tipos de arquivos de texto de lembrete; e listaria os arquivos nesse diretório após a conclusão inteligente de bash para o primeiro argumento de comando; e abriria um nome de arquivo fornecido na linha de comando em less (ou no editor de texto da GUI padrão se um switch de linha de comando for fornecido) não deve ser muito difícil.

Mas eu prefiro não tentar reinventar a roda, então eu estava me perguntando - se algum tipo de comando para um esquema de uso como descrito já existe em um sistema GNU / Linux típico?

    
por sdaau 11.03.2014 / 12:33

2 respostas

3

Expandir o comentário de @SamiLaine para usar man - uma das razões pelas quais não gostei, foi porque eu esperava que fosse tedioso configurar, e acho que este post mostrará isso; mas parece funcionar. Primeiro, alguma introdução pode ser encontrada aqui:

Primeiro, vamos criar o diretório e adicioná-lo ao MANPATH:

mkdir ~/myreminderhelp
echo 'MANPATH=$MANPATH:'$(echo ~/myreminderhelp) >> ~/.bashrc

Vamos testar se ele é encontrado: feche o terminal, abra um novo terminal; e depois:

manpath -d 2>&1 | grep myrem

Infelizmente, isso não informa nada para mim; mesmo se echo $MANPATH disser :~/myreminderhelp .

Experimentando com% global/etc/bash.bashrc (após excluir a linha no local ~/.bashrc e reiniciar o terminal novamente):

sudo bash -c "echo 'MANPATH=$MANPATH:'$(echo ~/myreminderhelp)" # check home dir printout
sudo bash -c "echo 'MANPATH=$MANPATH:'$(echo ~/myreminderhelp) >> /etc/bash.bashrc"

Reinicie o terminal; ainda manpath não reporta este diretório. Vamos agora tentar isso:

sudo bash -c "echo 'MANDATORY_MANPATH  '$(echo ~/myreminderhelp) >> /etc/manpath.config"

Feche e reabra o terminal novamente; finalmente, conseguimos:

$ manpath 
/usr/local/man:/usr/local/share/man:/usr/share/man:/media/extern/texlive/2011/bin/i386-linux/man:~/myreminderhelp

Na verdade, depois de encontrar isso, apaguei a linha de /etc/bash.bashrc e manpath ainda relata o diretório. Então, eu acho que editar /etc/manpath.config é tudo que é necessário.

Ok, vamos criar um exemplo de arquivo de lembrete personalizado aqui:

echo "Just a bit of a reminder...

Use nmcli con --help" >> ~/myreminderhelp/nmcli-reminder.txt

Em seguida, use txt2man para obter um arquivo man formatado e gzip:

cat ~/myreminderhelp/nmcli-reminder.txt | txt2man > ~/myreminderhelp/nmcli-reminder.1
gzip ~/myreminderhelp/nmcli-reminder.1

Reinicie o terminal novamente, tente digitar man nm e pressione TAB - autocompletion mostra nmcli-reminder não encontrado ...

Então, vamos tentar colocar nossos arquivos em uma subpasta man section; os links acima indicam a seção 7 seria apropriada; então:

mkdir ~/myreminderhelp/man7
mv ~/myreminderhelp/nmcli-reminder.* ~/myreminderhelp/man7/
tree ~/myreminderhelp # to check - ok

Reinicie o terminal novamente; tente digitar man nm e pressione TAB - autocompletion finalmente funciona:

$ man nmcli # and here press TAB:
nmcli           nmcli-reminder

... mas agora temos esse problema:

$ man nmcli-reminder 
No manual entry for nmcli-reminder

Droga. Pode ser que atualmente, nosso arquivo seja nmcli-reminder.1.gz indicando a seção 1 - vamos renomeá-lo:

mv ~/myreminderhelp/man7/nmcli-reminder.1.gz ~/myreminderhelp/man7/nmcli-reminder.7.gz
man nmcli-reminder

... e finalmente o comando man funciona!

Portanto, para este caso de uso, provavelmente é melhor manter os arquivos de origem .txt diretamente em ~/myreminderhelp/ e, em seguida, gerar páginas man na subpasta apropriada - como em:

$ tree ~/myreminderhelp/
~/myreminderhelp/
├── man7
│   └── nmcli-reminder.7.gz
└── nmcli-reminder.txt

... os comandos de geração apropriados para este ser:

cat ~/myreminderhelp/nmcli-reminder.txt | txt2man > ~/myreminderhelp/man7/nmcli-reminder.7
gzip ~/myreminderhelp/man7/nmcli-reminder.7

E aqui está um script ~/myreminderhelp/buildreminders.sh :

#!/usr/bin/env bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

for ix in $DIR/*.txt; do
  bx=$(basename $ix)
  isn=${bx%%.txt}
  echo Processing $isn;
  set -x
  # txt2man -t "$isn" -s 7 $ix > $DIR/man7/${isn}.7
  pandoc -f markdown -t man -s -o $DIR/man7/${isn}.7 $ix
  gzip --force $DIR/man7/${isn}.7
  { set +x; } 2>/dev/null
done

tree -a $DIR

EDIT: Acontece que é muito difícil obter txt2man deixando o código-fonte literal sem formatação, já que ele tende a extrair informações automaticamente como man (sub) seções, etc. Eu modifiquei o script acima para use pandoc (via WritingManPages - HerzbubeWiki ) - pelo menos com pandoc com uma entrada Markdown, você tem algum controle sobre o que é literal texto pré-formatado, e o que não é ...

No entanto, essas duas ferramentas irão recuar o conteúdo, como é típico para uma página man (já que os títulos das seções não são recuados, o resto do conteúdo do texto como em parágrafos, é). E eu não tenho certeza se eu acabo gostando demais ...

    
por 11.03.2014 / 19:39
0

Certo, aqui está também um script com autocompletar, conforme descrito no OP; você pode armazená-lo no diretório ~/myreminderhelp/ como na resposta man e, em seguida, criar uma ligação simbólica para /usr/bin . Ele deve ler todos os arquivos *.txt em seu diretório e disponibilizá-los (sem as extensões) por meio do preenchimento automático; espaços em nomes de arquivos devem ser manipulados. Então você poderia ligar:

$ help-remind #[TAB] here:
nmcli-reminder  test reminder   
$ help-remind test\ reminder # 'less' starts here

... ou você poderia usar algo assim para abrir os arquivos em um editor de texto:

scite "$(help-remind --getpath test\ reminder2)"

... que também abrirá arquivos não existentes, para que você possa começar a editá-los.

Aqui está o código para help-remind.sh :

#!/usr/bin/env bash

# sdaau, mar 2014

# symlink this script as:
# sudo ln -s $(readlink -f help-remind.sh) /usr/bin/help-remind

# http://stackoverflow.com/a/246128/277826
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"

# declare here all options:
opts="--dumpopts --getdir --getpath"

function main() {
  [ ! -f /etc/bash_completion.d/help-remind ] &&
    generate_bash_completion ;
  # regex check of arguments - if contain "--getdir":
  [[ "$@" =~ --getdir ]]; REC=$?;
  if [[ $REC == 0 ]] ; then
    getdir
    exit
  fi
  [[ "$@" =~ --dumpopts ]]; REC=$?;
  if [[ $REC == 0 ]] ; then
    echo "$opts"
    exit
  fi
  [[ "$@" =~ --getpath ]]; REC=$?;
  if [[ $REC == 0 ]] ; then
    # expecting name without .txt here as second arg;
    # but handle also if it is given
    tfile="${2%%.txt}.txt"
    trlfile=$(readlink -f "$DIR"/"$tfile") ; #echo ${trlfile}
    # printf quoted too (so spaces are escaped):
    echo $(printf '%q' "$trlfile")
    exit
  fi
  if [[ "$@" == "" ]]; then
    echo "An argument is needed"
    exit
  fi
  # if we got here, we expect the text file name as the first argument
  tfile="${1%%.txt}.txt"
  trlfile=$(readlink -f "$DIR"/"$tfile") ; #echo ${trlfile}
  # open it in 'less'
  less "$trlfile"
}

function getdir() {
  echo $DIR
}


function generate_bash_completion() {

# note, this requires terminal restart, each time the file is generated

sudo -s <<-'EOM'
cat > /etc/bash_completion.d/help-remind <<'EOF'

_help-remind()
{
    local cur prev opts
    local hrdir hrfiles hri thrf
    local IFS=$'\n'
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="$(help-remind --dumpopts)"
    # to array:
    IFS=' ' read -a opts <<< "$opts"
    # back to LF separated string:
    opts="$(printf '%s\n' "${opts[@]}")"
    hrdir="$(help-remind --getdir)"
    hrfiles=()
    hri=0
    hrfilestr=""

    # create list of candidate text files; only basenames, no ext
    for file in "${hrdir}"/*.txt; do
      thrf=$(basename "$file")
      thrf="${thrf%%.txt}"
      hrfiles[hri++]="${thrf}"
      hrfilestr=$(printf "%s\n${hrfilestr}" "${thrf}")
    done
    #hrfilestr="$(printf '%s\n' "${hrfiles[@]}")"

    shopt -s extglob

    # just for --getpath, also match candidate text files:
    # compopt -o filenames to get spaces to be escaped once chosen via tab
    case $prev in
      --getpath)
        #_filedir
        compopt -o filenames 2>/dev/null
        COMPREPLY=( $(compgen -W "${hrfilestr}" -- ${cur}) )
        return 0
        ;;
    esac

    # show options, only if $cur starts with a -
    if [[ ${cur} =~ ^- ]] ; then
      COMPREPLY=( $(echo; compgen -W "${opts}" -- ${cur}) )
      return 0
    # else match candidate text files:
    # compopt -o filenames to get spaces to be escaped once chosen via tab
    elif [[ ${cur} == * ]] ; then
      compopt -o filenames 2>/dev/null
      COMPREPLY=( $(compgen -W "${hrfilestr}" -- ${cur}) )
      return 0
    fi
}
complete -F _help-remind help-remind

EOF
EOM

}

# $@ has to be quoted to handle spaces in filenames
main "$@"



# see also:
# http://unix.stackexchange.com/questions/77009/custom-autocomplete-deal-with-spaces-in-filenames
# http://stackoverflow.com/questions/10652492/bash-autocompletion-how-to-pass-this-array-to-compgen-without-significant-whit
# http://www.linuxquestions.org/questions/linux-software-2/escape-string-in-bash-script-so-it-can-be-used-in-command-line-360664/
    
por 12.03.2014 / 02:19