#!/bin/sh
# ordbanken – oppslag i Norsk ordbank etter ord som tilfredstiller visse kriterium.
#
# Copyright © 2008, 2009, 2010 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).
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='2012-09-01'
copyar='2008, 2009, 2010, 2011, 2012'

# 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.
  -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

For verb kan ein velja mellom e- og a-infinitiv:
  ordbanken hoppe
  ordbanken hoppa
Merk at resultata vert litt forskjellige,
då eit oppslag på «hoppa» ikkje vil finna
substantivet «hoppe» (ein hohest), berre
verbet og avleidde adjektivformer.

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:
  ordbanken --ikkje-fargekod annan

Same som over, berre mindre å skriva:
  ordbanken -F 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.
Skjer berre viss SPRAK_ORDBANKEN ikkje
er definert.)

$ 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                  --html              -snn
--eksempel          --ikkje-fargekod    --sprak
-f                  -r                  --tekst
--fargekod          --regulært-uttrykk  -v
--hjelp             -snb                --versjon
(Liste over alle moglege argument vart vist.)

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

$ ordbanken --sprak nn hoppe [tab]
adj        fem        m/f        pres-part  verb
appell     fl         nøyt       pret       
bu         imp        perf-part  subst      
eint       inf        pres       ub         
(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:ehvfFr" \
      --longoptions="sprak:,eksempel,hjelp,versjon,fargekod,ikkje-fargekod,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 ;;
    -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

# 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' \
                              -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.
hentOppslag() {
  if [ $regular = 1 ]
  then
    oppslagstekst="$(awk -F '\t' '{ if ( $1 ~ '/"$1"/') {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
    oppslagstekst="$(LC_ALL=C $LOOK_PROG -- "$1	" $ordbok)"
  else
    oppslagstekst="$(awk -F '\t' '{ if ( $1 == '\""$1"\"') {print $0}}' $ordbok)"
  fi
  echo "$oppslagstekst"
}

oppslag=$(hentOppslag "$ord")
everb="$(echo $ord | sed -e 's/a$/e/')"
if [ "$everb" != "$ord" ]
then
  oppslagVerb=$(hentOppslag "$everb" | awk -F'\t' \
                '{if ( $3 == "verb" || ($3 == "adj" && $4 ~ /<(perf|pres)-part>/) ) {print $0}}')
  oppslag="$oppslag
$oppslagVerb"
fi


# Forklaring på kommandoane nedanfor:
#  grep: Filtrer oppføringar etter dei opptil seks kriteria.
#  grep: Filtrer oppføringar etter dei opptil seks kriteria.
#  sort: Sorter først etter ord (nyttig ved oppslag på ord som «i»,
#        og ved regulære uttrykk), og så etter ordklassar (på ein lur måte).
#  sed:  Fjern kodar («ord» utan <>) som startar med tal (interne/uforståelige kodar).
#  uniq: Fjern duplikatlinjer som kjem etter kvarandre.
resultat=$(echo "$oppslag" \
| 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" \
| sort -k1,1 -k3,3 -k4,4 -k6,6 -k7,7 -k8,8 -k5,5 -s "-t	" \
| uniq)

# 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"/;')

# 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; }'
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')
fi

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