-- RemoveFollowingRestsOfSameLength.hmm.lua (0.1) -- $NWCUT$CONFIG: FileText $ -- This simple tool removes all objects after the selection for a duration that is equal to the duration's length. -- This is helpful if you have added a stretch of notation in a run of rests, but actually did not want to move back everything behind your insertion; -- think of it as a remedy for NWC's missing "overwrite mode". -- The tool is especially useful in collaboration with the "Extend staff below with rests to cursor" user tool, which creates such stretches of rests. -- If the tool encounters an object with duration during its removal that is *not* a rest, it stops - it does not want to destroy parts of the score. -- Finally, if the removed rests do not sum up to the exact length of the selection, the tool inserts a few small rests for compensation. if nwcut.getprop("Mode") ~= nwcut.const.mode_FileText then error("Invalid input mode...this tool requires file text") end local f = nwcut.loadFile() local durations = { Whole = 1, Half = 1/2, ['4th'] = 1/4, ['8th'] = 1/8, ['16th'] = 1/16, ['32nd'] = 1/32, ['64h'] = 1/64 } local durationFactor = { [0] = 1, [1] = 3/2, [2] = 7/4 } local insertDurationsOrdered = { 'Half', '4th', '8th', '16th', '32nd', '64h' } local function duration(item) return item:HasDuration() and not item.Opts.Dur.Grace and durations[item:NoteDurBase()] * durationFactor[item:NoteDots()] or 0 end local function insertRests(staff, i, lg) for _, restDur in ipairs(insertDurationsOrdered) do while lg >= durations[restDur] do table.insert(staff.Items, i, nwcItem.new('|Rest|Dur:' .. restDur .. '|Visibility:Never')) lg = lg - durations[restDur] end end end local staff = f.Staff[f.Editor.Opts.ActiveStaff + 0] local selectionDuration = 0 if f.Editor.Opts.SelectIndex + 0 > 0 then local left = math.min(f.Editor.Opts.SelectIndex + 0, f.Editor.Opts.CaretIndex + 0) local right = math.max(f.Editor.Opts.SelectIndex + 0, f.Editor.Opts.CaretIndex + 0) for i = left, right - 1 do local item = staff.Items[i] selectionDuration = selectionDuration + duration(item) end if selectionDuration > 0 then local i = right local indicesToRemove = { } while selectionDuration > 0 and i <= #staff.Items do local item = staff.Items[i] if item.ObjType == 'Rest' then selectionDuration = selectionDuration - duration(item) elseif duration(item) > 0 then break end i = i + 1 end for j = right, i - 1 do table.remove(staff.Items, right) end insertRests(staff, right, -selectionDuration) f:save(nwcut.writeline) end end nwcut.status = nwcut.const.rc_Success