3 #======================================================================
5 #======================================================================
6 # pitches (rhythms, ...) contains the pitch names used in the file, plus
7 # "s" and "r" pitch_keys is a (user-defined) variable list of keyboard keys
8 # to go with the various pitch names pitchmap gives the current translation
9 # between keyb. input and output to document:
10 # pitchmap["a"] = "c". The dictionary is initialized with default values,
11 # but will be changed along the way, to store the current values at any
12 # time, so that after a "is" is added to "c", pitchmap["a"] = "cis"
18 loaded
= vim
.eval("g:loaded_lyqi")
23 global pitches
, pitch_keys
, pitchmap
24 pitches
= ( "c", "d", "e", "f", "g", "a", "b", "s", "r", "R" )
25 pitch_keys
= ( "a", "s", "d", "f", "w", "e", "r", "q", "g", "G" )
26 pitchmap
= dict(zip(pitch_keys
, pitches
))
27 vim
.command("let g:loaded_lyqi = 0")
32 acc_keys
= ( "c", "v" )
33 accmap
= dict(zip(acc_keys
, accs
))
35 caut_keys
= ( "!", "?" )
36 cautmap
= dict(zip(caut_keys
, cauts
))
38 oct_keys
= ( "u", "i" )
39 octmap
= dict(zip(oct_keys
, octs
))
40 durs
= ( "128", "64", "32", "16", "8", "4", "2", "1", "\\breve", "\\longa", "\\maxima" )
41 dur_keys
= ( "P", "O", "p", "o", "l", "k", "j", "h", "b", "L", "M" )
42 durmap
= dict(zip(dur_keys
, durs
))
46 valid_note
= ("pitch", "acc", "caut", "oct", "dur", "dot", "art", "add")
61 # RE for parsing an input string representing a note name. The RE-string
62 # matches everything from "a" to "ases!,,\maxima...^\f", and also takes
63 # care of the syntactic inconsistency which allows both "es/as" and
66 notestring
= r
"""^(?P<pitch>[a-g])
67 (?P<acc>(((ses)|(s))|((es){1,2})|((is){1,2}))?)
70 (?P<dur>(1|2|4|8|(16)|(32)|(64)|(\\breve)|(\\longa)|(\\maxima))?)
76 #======================================================================
78 #======================================================================
80 #======================================================================
82 input_key
= vim
.eval("b:input_key")
84 #======================================================================
93 elif key
in caut_keys
:
100 vim
.command("normal a" + key
)
103 #======================================================================
104 def parse(input_string
):
105 parsed_note
= re
.compile(notestring
, re
.VERBOSE
)
106 match_obj
= parsed_note
.search(input_string
)
108 current
[i
] = match_obj
.group(i
)
109 #adjust the inconsistent accidental syntax
110 if current
['acc'].startswith('s'):
111 current
['acc'] = 'e' + current
['acc']
115 #======================================================================
116 # - forandre current['pitch']
117 # - avspille en lyd i overensstemmelse med cur_note['pitch'] og [oct]
119 def pitch(input_key
):
120 current
['pitch'] = pitchmap
[input_key
]
122 vim
.command("normal a" + n
+ " ")
124 #======================================================================
126 #======================================================================
128 #get current note from vim and parse it into current{}
129 vim
.command("call Get_current_note()")
131 note
= vim
.eval("b:notestring")
133 #calculate the new value for acc -- up or down?
134 if 'e' in current
['acc']:
138 accnum
= len(current
['acc']) / 2 * esis
+ accmap
[input_key
]
140 current
['acc'] = 'eses'
142 current
['acc'] = 'es'
146 current
['acc'] = 'is'
148 current
['acc'] = 'isis'
149 # her er det en feil: jeg forandrer key og ikke val, eller tvert om ; er
150 # for trøtt til å fikse det nå.
152 if pitchmap
[k
] == current
['pitch']:
153 pitchmap
[k
] = current
['pitch'] + current
['acc']
154 vim
.command("normal a" + make_note())
156 def reverse_lookup(d
,v
):
161 #======================================================================
163 #======================================================================
165 #get current note from vim and parse it into current{}
166 vim
.command("call Get_current_note()")
167 note
= vim
.eval("b:notestring")
169 current
['dur'] = durmap
[input_key
]
171 vim
.command("normal a" + make_note())
173 #======================================================================
175 #======================================================================
177 # bruker bare current, så ingen args er nødvendige
180 new_note
+= current
[i
]
183 #======================================================================
184 # cautionary accidentals {{{2
185 #======================================================================
187 vim
.command("call Get_current_note()")
188 note
= vim
.eval("b:notestring")
190 current
['caut'] = cautmap
[input_key
]
191 vim
.command("normal a" + make_note())
193 #======================================================================
195 #======================================================================
197 #get current note from vim and parse it into current{}
198 vim
.command("call Get_current_note()")
199 note
= vim
.eval("b:notestring")
201 if ',' in current
['oct']:
204 elif "'" in current
['oct']:
209 if octmap
[input_key
] == -1:
213 octnum
= abs(len(current
['oct']) * octdir
+ octmap
[input_key
])
214 current
['oct'] = octnum
* octsign
215 vim
.command("normal a" + make_note())
217 #======================================================================
219 #======================================================================
220 #if input = dot og dur ikke er definert:
221 # #scan tilbake etter siste dur
222 # TODO: make function for backwards scanning after rhythm value.
223 # In the meantime, a default value of 4 will have to do.
226 vim
.command("call Get_current_note()")
227 note
= vim
.eval("b:notestring")
229 if not current
['dur']:
231 current
['dot'] += '.'
232 vim
.command("normal a" + make_note())
235 #def find_prev_dur():
238 # dur_search[i] = '\\(' + durs[i] + '\\)'
239 # dur_str = '\\|'.join(dur_search)
240 # dur_match = vim.command("call search("+search_str+", 'bcpn')")
241 # current['dur'] = durs[dur_match-1]
244 # %======================================================================
246 # %======================================================================
247 # slurs ~ settes inn direkte, med luft rundt
248 # rest/silent (oppfører seg som vanlige noter, bortsett fra at deres verdi
250 # \ - settes inn direkte, og avviker midlertidig fra lyqi-mode, inntil ...
251 # hva? det trykkes \ igjen? Kanskje. Eller som i emacs: at det
253 # funksjon for å forandre notetrinn
254 # TODO- oppdaterer pitch
255 # - fjerner [acc]-verdi (så "fes" og "fis" blir til "e"
256 # - men endrer selvfølgelig ikke pitches
258 # add_markup [introduced by "\"; leaves lyqi-mode; return with <esc>]
262 #%======================================================================
264 #======================================================================
265 # change_degree: trenger kanskje kommando for å forandre degree (ikke
274 process_key(get_vim_key())
276 #======================================================================
278 #%======================================================================
279 # NB: unntak: chords, der [dur] står utenfor:
281 # < [pitch][oct][art] > [dur][dot]
283 # Chords er dessuten et spesialtilfelle som må tas hensyn til mht.
284 # forandring av rytmeverdi: prøver man å sette inn en 4 eller en . etter
285 # en uavsluttet <, skal det gis feilmelding, og trykker man 4 mens man er
286 # innenfor en <>-blokk, skal det søkes framover, og ikke bakover.
290 # TODO: hopper over midi-kommandoene enn så lenge
293 #%======================================================================
294 #Fra lyqi-tool (emacs) {{{2
295 #%======================================================================
298 #%======================================================================
301 #( let (( abspitch1 ( + ( * 7 ( lyqi-note-octave prevnote)) (lyqi-note-pitch prevnote)))
303 #finn forrige notes oktav, gange med 7 og legg til tallet for forrige note
304 #prevnote er en array som inneholderzc flere verdier: alle
305 #(abspitch2 (+ (* 7 (lyqi-note-octave note)) (lyqi-note-pitch note)))
307 #(if (< (abs (- abspitch1 abspitch2)) 4)
308 ##" ; same relative octave
309 #(if (> abspitch1 abspitch2)
310 #(make-string (+ (/ (- abspitch1 abspitch2 4) 7) 1)
311 #(lyqi-get-translation 'octave-down))
312 #(make-string (+ (/ (- abspitch2 abspitch1 4) 7) 1)
313 #(lyqi-get-translation 'octave-up)))))
315 #(type 'note "note, rest or skip")
316 #(pitch 0 "the actual note, from 0 (do) to 6 (si)")
317 #(accidental 2 "from 0 (##) to 4 (bb)")
318 #(octave 1 "octave 0 is starting with the do which
319 #is in the second interline in a fourth line F-clef")
320 #(duration 3 "from 1 to 8, real-duration = 2^(duration - 1)")
321 #(dots 0 "number of dots, from 0 to 4")
322 #(force-duration nil "tells if duration must be written")
323 #(previous nil "The previous note"))
326 #%======================================================================
328 #%======================================================================
329 #let g:lyqi_midi_command = "timidity -iA -B2,8 -0s -EFreverb=0"
330 #let g:lyqi_midi_kbd = "mymidikbd"
331 #let g:lyqi_use_midi = 1 #skal midi-processen starte automatisk?
333 #if &cp || exists("loaded_lyqi")
340 #======================================================================
342 #======================================================================
348 # (1) oversett til notenavn
349 # (2) hvilken gruppe tilhører det? Gå til tilsvarende funksjon
352 # (3) finne posisjon (etter streng under eller før cursor)
353 # (4) oppdatere current med det nye notenavnet
354 # (5) lage ny notestreng (som bare består av notenavn)
355 # (6) innføre strengen i dok. på den funne posisjon
359 # (8) hente streng under eller før cursor
361 # (4) oppdatere med ny verdi
363 # (10) erstatte gammel med ny streng
370 ## to typer, som trigges av "\" og
376 # 1. remappe tangentbordet, gjeldende for bufferen
378 # 2. inneholde funksjoner for å modifisere foregående tekst, i følgende
379 # tilfeller ("tekst" i dette tilfelle betyr hele blokken, dvs. strengen før
380 # eller under cursor, omgitt enten av whitespace eller <>, og parset i
381 # forhold til en standardgruppe):
383 # ny degree: tilføyer et nytt noteobjekt, og oppdaterer $current. Eneste
384 # grunn til å gjøre det, er for midi-ens del. En degree-inntastning skal
385 # aldri i seg selv føre til en mer omfattende streng, men det må hele
386 # tiden holdes styr på degree og oktav for sist innskrevne note.
388 # når en ny rytmeverdi skrives inn: da skal verdien føyes til foregående
389 # note, eller eksisterende verdi forandres, og $current oppdateres.
391 # punkteringer: ren strengemodifikator: punkt legges til eksplisitt
392 # rytmeverdi i strengen, hvis den eksisterer, eller forbindes med
393 # gjeldende rytmeverdi og føyes til etter pitch-gruppe. Trenger forsåvidt
394 # ikke lagres (vil man noen gang vite hvor mange punkteringer foregående=
395 # note hadde? I think not), men det skader vel ikke...
397 # når et oktavtegn skrives inn: to ting skjer: strengen forandres på
398 # enkelt vis (', legges til degree), og $current oppdateres
400 # når en akksidental skrives inn: da skal det føyes is/es til foregående
401 # degree, og dens verdi skal lagres, dvs. keyboard-kommandoen skal
402 # forandres temporært.
404 # Input-typer: degree_key, octave_key, rhythm_key, dot, change_aug, change_degree
406 # Lagrede interne variabler:
409 # default note constructions
410 # curr_rhythm | disse to er kanskje unødvendige; de er allerede del
411 # curr_pitch | av curr_note
413 #Modifikasjonen skjer "utenfor", dvs i en ekstern funksjon som sammenligner
414 #den parsede streng (curr_note) med en standard (note) og modifiserer i
415 #overensstemmelse med input.
417 # nødvendige funksjoner:
418 # - parse input: strengen kan variere fra "a" til "ais'4...^.[{
419 # den skal så deles opp og fylle en liste (degree, aug, oct, rhythm,
420 # dot, articulation) for current_note
421 # - oppgradere prev_values med den nye verdien
422 # - forandre strengen etter sml mellom curr_note og prev_values
423 # - føre strengen tilbake til tekstfilen (og avspille en note)