#!/bin/sh
# ordbanken – oppslag i Norsk ordbank etter ord som tilfredstiller visse kriterium.
#
# Copyright © 2008, 2009 Karl Ove Hufthammer <karl@huftis.org>.
#
#     This file is part of Ordbanken.
#
#     Ordbanken is free software: you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
#
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Nokre nødvendige variablar, samt standardverdiar.
mappe="/usr/local/share/ordbanken"
fargekod=1   # Fargelegg resultatet.
fargetvang=0 # Men ikkje fargelegg dersom utdata går til eit
             # røyr (med mindre brukaren tvingar det gjennom).
klammer=1    # Vis òg klammeformer.
parentes=1   # Legg klammeparentes rundt klammeformene.
html=0       # Vis tekst og ikkje HTML.
regular=0    # Ikkje bruk regulære uttrykk.

sprak=$SPRAK_ORDBANKEN
if [ -z "$sprak" ] # Nynorsk som standardspråk viss ikkje noko anna er valt.
then
  sprak=nn
fi

# Versjonsnummer og copyright-år.
versjon='2009-06-07'
copyar='2008, 2009'

# Namn og adresse for feilrapportar.
adresse='Karl Ove Hufthammer <karl@huftis.org>'

# Sjekk om verktøyet «look» finst.
LOOK_PROG=$(command -v look)
LOOK_FINST=$?

# Vis informasjon om korleis skriptet skal brukast.
bruk() {
echo -e 'Bruk: ordbanken [VAL] grunnord [KRITERIUM1] [KRITERIUM2] ...
Slår opp ordet «grunnord» i fullformsordlista til Norsk ordbank,
med eventuell filtrering etter eitt eller fleire kriterium.\n'

echo \
'Verdiar for VAL:
  -s, --sprak=SPRÅKKODE	Vel ordliste, der SPRÅKKODE er nn for
  	nynorsk (standard) eller nb for bokmål.
  -e, --eksempel	Vis eksempel på bruk, samt nokre tips.
  -f, --fargekod	Fargekod resultatet (standard).
  -F, --ikkje-fargekod	Ikkje fargekod resultatet.
  -k, --klammer	Vis òg klammeformer (standard).
  -K, --ikkje-klammer	Vis ikkje klammeformer.
  -p, --parentes	Vis klammeparentesar rundt klammeformer (standard).
  -P, --ikkje-parentes	Ikkje vis klammeparentesar rundt klammeformer.
  -r, --regulært-uttrykk	Oppslagsteksten er eit regulært uttrykk.
      --tekst	Vis resultatet som rein tekst (standard).
      --html	Vis resultatet som HTML.
  -h, --hjelp	Vis denne hjelpeteksten.
  -v, --versjon	Vis programversjon og lisensinformasjon.' | column -t -s"	"

echo ""
echo "Meld frå om feil til $adresse."
}

# Vis nokre eksempel på bruk av skriptet.
versjon() {
echo "Ordbanken versjon $versjon.

Programmet er Copyright © $copyar $adresse
Ordlistene er Copyright © $copyar Universitetet i Oslo

Ordbanken er fri programvare, og kjem UTAN NOKON GARANTIAR.
Du må gjerne gje programmet vidare, under visse vilkår.

Lisensvilkår: GPLv3+ – GNU GPL versjon 3 eller seinare
<http://www.gnu.org/licenses/gpl.html>.

Programmet er skrive er Karl Ove Hufthammer, og
ordlistene er utvikla av, og vert vedlikehaldne av,
Universitetet i Oslo."
}

# Vis nokre eksempel på bruk av skriptet.
eksempel() {
echo 'Her er nokre eksempel på bruk av programmet.
Merk at oppslagsordet må vera fullstendig, men
det held å bruka starten av eventuelle kodar.

Bøying av ordet «å lese» på standardspråket:
  ordbanken lese

Berre perfektum partisipp-former:
  ordbanken lese perf

Ordet «hoppe», men berre som substantiv:
  ordbanken hoppe subst

Ordet «på», samt uttrykk (idiom) der førsteleddet
er «på»:
  ordbanken på

Bøying av «å finnes» på bokmål:
  ordbanken --sprak=nb finnes

Fleirtal av substantivet «hoppe» på bokmål:
  ordbanken -snb hoppe su fl

Ordet «annan», med fargekoding (som er standard):
  ordbanken --fargekod annan

Same, men no utan fargekoding, og utan klammeformer:
  ordbanken --ikkje-fargekod --ikkje-klammer annan

Same som over, berre mindre å skriva:
  ordbanken -FK annan

Lagra resultatet som HTML i fila «annan.html»:
  ordbanken --html annan > annan.html


Me kan òg bruka jokerteikn viss me berre kjenner
til delar av ordet (for eksempel ved kryssordløysing).
Jokerteikna er dei same som for Nynorskordboka og
Bokmålsordboka på nett, «%» for null eller fleire
vilkårlege bokstavar, og «_» for éin vilkårleg
bokstav. Her er eit enkelt eksempel, som blant
anna finn ordet «kryssord»:

Vis alle (grunn)orda som startar på «kr», etterfølgd
av éin vilkårleg bokstav, så bokstavane «ss», så
eventuelt nokre vilkårlege bokstavar, og til slutt
ein «d»:
  ordbanken kr_ss%d

Programmet støttar òg regulære uttrykk, med
kommandolinjevala «--regulært-uttrykk»/«-r».
Desse er mykje kraftigare enn enkle jokerteikn,
men kan vera noko vanskelegare å læra seg.

Dei tre orda «hei», «heim» og «heit»:
  ordbanken --regulært-uttrykk "^hei[mt]?$"

Ord som startar på «dr» og sluttar på «ev»:
  ordbanken -r "^dr.*ev$"

Ord som sluttar på «rama», men ikkje på «drama:
  ordbanken -r [^d]rama$

Ord der første bokstav er «k», neste er «r»
eller «u», tredje siste er «o» og siste er «d»:
  ordbanken -r ^k[ru]...o.d$

Bokmålsord med minst 5 etterfølgjande vokalar:
  ordbanken -snb -r [aeiouyæøå]{5}


Om ikkje anna er valt, vert nynorsk brukt som
standardspråk, men du kan òg definera standard-
språket i miljøvariabelen SPRAK_ORDBANKEN.

Legg for eksempel
  export SPRAK_ORDBANKEN=nb
til i fila ~/.bashrc for å bruka bokmål som standard.


Programmet støttar òg autofullføring via bash
completion. Viss du har installert og slått
på bash completion, kan du bruka tabulator-
tasten slik:

$ ordbanken [tab]
ordbanken --sprak
(Valet «--sprak» vart automatisk lagt til.)

$ ordbanken --sprak [tab]
nb nn
ordbanken --sprak n
(Liste med vala «nb» og «nn» vart vist,
og bokstaven «n» vart lagd til.)

$ ordbanken -[tab]
-e                --ikkje-fargekod  --parentes
--eksempel        --ikkje-klammer   -s
-F                --ikkje-parentes  -snb
-f                -K                -snn
--fargekod        -k                --sprak
-h                --klammer         --tekst
--hjelp           -P                -v
--html            -p                --versjon
(Liste over alle moglege argument vart vist.)

$ ordbanken --sprak nn ym[tab]
ym         ymislig    ymse       ymsing
ymis       ymisskap   ymsefinna  ymt
ymiskvar   ymist      ymsen      ymte
ymisleg    ymje       ymsesidig  ymting
(Liste over alle nynorskord som startar med «ym» vart vist.)

$ ordbanken --sprak nn hoppe [tab]
adj         fem         klammeform  pres        ub
appell      fl          m/f         pret        verb
bu          imp         nøyt        st-form
eint        inf         perf-part   subst
(Liste over alle filtreringskriterium (ordklassar)
ein kan bruka for nynorskordet «hoppe».)'
}

# Hent kommandolinjevala.
val=$(getopt -n "$0" --options="s:ehvkKfFpPr" \
      --longoptions="sprak:,eksempel,hjelp,versjon,fargekod,ikkje-fargekod,klammer,ikkje-klammer,parentes,ikkje-parentes,regulært-uttrykk,tekst,html" -- "$@")
ret=$?

eval set -- "$val"

# Vis hjelpeteksten og avslutt dersom getopt avslutta med feil.
if [ $ret -ne 0 ]
then
  bruk
  exit 1;
fi

# Tolk kommandolinjevala.
while true; do
  case $1 in
    -h | --hjelp )  bruk; exit 0 ;;
    -v | --versjon )  versjon; exit 0 ;;
    -e | --eksempel )  eksempel; exit 0 ;;
    -f | --fargekod) fargekod=1; fargetvang=1 ;;
    -F | --ikkje-fargekod ) fargekod=0 ;;
    -k | --klammer ) klammer=1;;
    -K | --ikkje-klammer ) klammer=0 ;;
    -p | --parentes ) parentes=1 ;;
    -P | --ikkje-parentes ) parentes=0 ;;
    -r | --regulært-uttrykk ) regular=1 ;;
    -s | --sprak ) shift; sprak=$1 ;;
    --tekst ) html=0;;
    --html ) html=1 ;;
    -- ) shift; break ;;
    * ) echo "Feil: Ugyldig argument: $1"; bruk; exit 1;;
  esac
  shift
done

# Ord som skal slåast opp.
ord=$1

# Må ha eit oppslagsord. Avslutt viss me ikkje har det.
if [ ! -n "$ord" ]
then
  bruk
  exit 1
fi

# Eventuelt filter for utfiltrering av klammeformer.
# Klammeformkoden kjem alltid heilt på slutten, eller
# har ein kode som startar på «<» etter seg (eksempel:
# orda «forgjeve» og «blåse»).
klammekode="klammeform\(	<.*\)\?$" # Identifikator for klammeformlinjer.
if [ $klammer = 1 ]
then
  klammer="#ingafiltrering#"
else
  klammer="$klammekode"
fi

# Eventuell utbytingstekst som legg til klammeparentes rundt klammeformer.
if [ $parentes = 1 ]
then
  partekst='\[\2\]'
else
  partekst='\2'
fi

# Intern språkkode (ordbanken brukar «bm» for bokmål, merkelig nok).
case $sprak in
  nb ) isprak=bm; spraknamn="bokmål";;
  nn ) isprak=nn; spraknamn="nynorsk";;
  * ) echo "Feil: Språkkoden «$sprak» er ikkje gyldig."; echo "Bruk «nn» (for nynorsk) eller «nb» (for bokmål)."; exit 1;;
esac

# Ordbankfilene ligg i SVN.
ordbok=$mappe/fullform_$isprak.dat


# Støtte for jokerteikn.
# Skriv feilmelding viss det er brukt feil jokerteikn.
if [ $regular = 0 ] && (echo "$ord" | grep -q '[*?]')
then
  echo "Du har brukt feil jokerteikn. Bruk:"
  echo "  % for null eller fleire vilkårlege teikn."
  echo "  _ for eitt vilkårleg teikn."
  exit 1
fi

# Skriv om eventuelle uttrykk med jokerteikn til eit regulært uttrykk.
if [ $regular = 0 ]
then
  if (echo "$ord" | grep -q '[%_]')
  then
    ord="^$(echo "$ord" | sed -e 's/%/.*/g' -e 's/_/./g')$" # Byt ut «%» og «_» med høvesvis «.*» og «.».
    regular=1                                               # Tolk så uttrykket som eit regulært uttrykk.
  fi
fi

# Sjølve utveljinga.
#
# Viss me har eit regulært uttrykk, bruk «awk» (som er mykje
# tregare enn «look», som me kan bruka elles.
if [ $regular = 1 ]
then
  oppslag="$(awk -W posix '{ if ( $1 ~ '/$ord/') {print $0}}' $ordbok)"
elif [ $LOOK_FINST -eq 0 ] # Viss me ikkje har eit regulært uttrykk,
                           # bruk «look» om det finst, og «awk» elles.
then
# Tillat både tabulatorteikn og mellomrom som ordskiljar;
# derfor to oppslag for «look»-kommandoen». Nyttig ved
# uttrykk med fleire ord, som «på kryss og tvers»
# (oppslagsordet «på»).
  oppslag="$(LC_ALL=C $LOOK_PROG "$ord " $ordbok)
$(LC_ALL=C $LOOK_PROG "$ord	" $ordbok)"
else
# Men «awk» tolkar som standard både tabulator og mellomrom
# som feltskiljeteikn, så her treng me berre eitt oppslag.
  oppslag="$(awk '{ if ( $1 == '\"$ord\"') {print $0}}' $ordbok)"
fi

# Forklaring på kommandoane nedanfor:
#  grep: Filtrer eventuelt vekk klammeformer.
#  grep: Filtrer oppføringar etter dei opptil seks kriteria.
#  grep: Filtrer oppføringar etter dei opptil seks kriteria.
#  sed:  Legg til 0 på starten av linjer med klammeformer, og
#        1 på dei utan. Vert brukt til å sortera klammeformene
#        til toppen (innanfor kvart oppslagsord).
#  sort: Sorter først etter ord (nyttig ved oppslag på ord som «i»,
#        og ved regulære uttrykk), så etter om det er klammeform
#        eller ikkje, og til slutt etter ordklassar (på ein lur måte).
#  cut:  Fjern klammeformmarkøren 0 eller 1 på starten av linjene.
#  sed:  Fjern kodar («ord» utan <>) som startar med tal (interne/uforståelige kodar).
#  sed:  Gjer om to etterfølgjande «klammeform»-kodar til éin.
#  uniq: Fjern duplikatlinjer som kjem etter kvarandre.
#  sed:  Legg eventuelt til klammeparentes rundt klammeformene.
resultat=$(echo "$oppslag" \
| grep -v "$klammer" \
| grep "\W<\?$2" | grep "\W<\?$3" | grep "\W<\?$4" \
| grep "\W<\?$5" | grep "\W<\?$6" | grep "\W<\?$7" \
| sed -e "/$klammekode/s/^/0	/" -e "/$klammekode/!s/^/1	/" \
| sort -k2,2 -k1,1 -k4,4 -k5,5 -k7,7 -k8,8 -k9,9 -k6,6 -s "-t	" \
| cut -f2- \
| sed 's/	klammeform	klammeform\b/	klammeform/' \
| uniq \
| sed '/.*	.*	.*klammeform/s/^\([^	]\+	\)\([^	]\+\)/\1'"$partekst"'/g')

# Skriv til slutt ut resultatet. Anten i HTML-format:
if [ $html = 1 ]
then
# Lag tabell av resultatet.
html=$(echo "$resultat" \
| sed \
's/</\&lt;/;'\
's/^\([^	<]\+\)/    <tr><td>\1<\/td>/;'\
's/$/<\/tr>/;'\
's/	\([^	<]\+\)/<td>\1<\/td>/g;')

# Legg til klassar for seinare fargelegging. Grunnen til
# dei litt kompliserte uttrykka er at for eksempel ordet
# «fem» ikkje skal reknast som eit hokjønnsord.
html=$(echo "$html" | sed \
'/\(<td>.*\)\{3,\}<td>mask<\/td>/s/<tr/<tr class="mask"/;'\
'/\(<td>.*\)\{3,\}<td>fem<\/td>/s/<tr/<tr class="fem"/;'\
'/\(<td>.*\)\{3,\}<td>m\/f<\/td>/s/<tr/<tr class="mf"/;'\
'/\(<td>.*\)\{3,\}<td>nøyt<\/td>/s/<tr/<tr class="noyt"/;'\
'/\(<td>.*\)\{3,\}<td>klammeform<\/td>/{
s/<tr class="\([^"]\+\)"/<tr class="klamme \1"/;
s/<tr>/<tr class="klamme">/;}')

# HTML-koden før og etter tabellen.
html=$(
echo \
'<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="'$sprak'" xml:lang="'$sprak'">

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Fullformsordliste'" ($spraknamn): $*"'</title>
  <style type="text/css">
    body    { color: black; background: white; }
    td + td { padding-left: 2em; }
    .klamme { font-style: italic; }'
if [ $fargekod = 1 ] # Eventuelt legg til CSS-kode for fargelegging.
then
echo \
'    .mask   { color: blue; }
    .fem    { color: red; }
    .mf     { color: green; }
    .noyt   { color: orange; }'
fi
echo \
'  </style>
</head>

<body>'
if [ -n "$resultat" ] # Ikkje legg til tabell om han er tom.
then
echo '  <table>'
linjefiks='s/<td/\n      <td/g;s/<\/tr>/\n    <\/tr>/' # sed-kode for linjeskift.
echo "$html" | sed "$linjefiks"                        # Oppføringane.
echo '  </table>'
fi
echo \
'</body>

</html>'
)
echo "$html"

else # html = 0, altso tekstvising.
resultat=$(echo "$resultat" | column -t -s"	") # Formater som ein fin tabell.

# Eventuell fargekoding. Igjen litt komplisert for å unngå
# at for eksempel grunnordet «fem» (og tilhøyrande bøying)
# skal markerast som hokjønn.

# Sjekk om utdata vert send i eit røyr. Viss ja, berre vis
# fargar viss det er eksplisitt bedt om det.
if [ ! -t 1 ]
then
  if [ $fargetvang = 0 ]
  then
    fargekod=0;
  fi
fi

if [ $fargekod = 1 ]
then
resultat=$(echo "$resultat" \
| sed 's/\(   *[^ ]\+.*  .*\)\b\(mask\)\b\(.*\)/\1[1;34m\2[0m\3/g' \
| sed 's/\(   *[^ ]\+.*  .*\)\b\(fem\)\b\(.*\)/\1[1;35m\2[0m\3/g' \
| sed 's/\(   *[^ ]\+.*  .*\)\b\(m\/f\)\b\(.*\)/\1[1;32m\2[0m\3/g' \
| sed 's/\(   *[^ ]\+.*  .*\)\b\(nøyt\)\b\(.*\)/\1[1;33m\2[0m\3/g' \
| sed 's/\(   *[^ ]\+.*  .*\)\b\(klammeform\)\b\(.*\)/\1[0;31m\2[0m\3/g')
fi

# Skriv til slutt ut resultat.
echo "$resultat" | grep -v ^$
fi
