#!/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-08-10'
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=$?

# Tving awk og dei andre programma til å
# bruka POSIX-modus (awk treng det for at
# for eksempel søket «[aeiouyæøå]{5}»
# skal verka):
export POSIXLY_CORRECT=1

# 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

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

Viss oppføringa startar med ein bindestrek, må
me bruka «--» for å skilja argument og oppslagsord:
  ordbanken -f -- -aktig


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.

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». Dette finn blant anna ordet «kryssord»:
  ordbanken kr_ss%d

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

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-klammer     --regulært-uttrykk
--eksempel          --ikkje-parentes    -s
-F                  -K                  -snb
-f                  -k                  -snn
--fargekod          --klammer           --sprak
-h                  -P                  --tekst
--hjelp             -p                  -v
--html              --parentes          --versjon
--ikkje-fargekod    -r
(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».)

$ ordbanken -snn -- -aktig [tab]
adj   eint  komp  nøyt  sup
bu    fl    m/f   pos   ub
(Det fungerer altså for suffiks òg.)'
}

# 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\(	<.*\)\{0,1\}$" # 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 -F '\t' '{ 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)"
else
# Men «awk» tolkar som standard både tabulator og mellomrom
# som feltskiljeteikn, så her treng me berre eitt oppslag.
  oppslag="$(awk -F '\t' '{ 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<\{0,1\}$2" | grep "\W<\{0,1\}$3" | grep "\W<\{0,1\}$4" \
| grep "\W<\{0,1\}$5" | grep "\W<\{0,1\}$6" | grep "\W<\{0,1\}$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,\}	\)\([^	]\{1,\}\)/\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/^\([^	<]\{1,\}\)/    <tr><td>\1<\/td>/;'\
's/$/<\/tr>/;'\
's/	\([^	<]\{1,\}\)/<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="\([^"]\{1,\}\)"/<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>'

echo "$html" | sed 's/<td/\
      <td/g;s/<\/tr>/\
      <\/tr>/' # Legg til linjeskift for fin formatering.
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/\(   *[^ ]\{1,\}.*  .*\)\b\(mask\)\b\(.*\)/\1[1;34m\2[0m\3/g' \
| sed 's/\(   *[^ ]\{1,\}.*  .*\)\b\(fem\)\b\(.*\)/\1[1;35m\2[0m\3/g' \
| sed 's/\(   *[^ ]\{1,\}.*  .*\)\b\(m\/f\)\b\(.*\)/\1[1;32m\2[0m\3/g' \
| sed 's/\(   *[^ ]\{1,\}.*  .*\)\b\(nøyt\)\b\(.*\)/\1[1;33m\2[0m\3/g' \
| sed 's/\(   *[^ ]\{1,\}.*  .*\)\b\(klammeform\)\b\(.*\)/\1[0;31m\2[0m\3/g')
fi

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