Snippet: Edit Step

Here is a snippet for moving to the next line after entering pattern data - a very common task.

This should be 100% compatible to the native behavior of Renoise, but please feel free to give improvements to the code structure and syntax wise.

  
  
local s = nil  
  
function move_cursor_wrapping()  
 local pos_table = { }  
 local i = 0  
 local current_pos = nil  
 for sequence in ipairs(s.sequencer.pattern_sequence) do  
 for pos,column in s.pattern_iterator:lines_in_pattern_track(s.sequencer.pattern_sequence[sequence], s.selected_track_index) do  
 i = i + 1  
 pos_table[i] = { pattern = pos.pattern, line = pos.line, sequence = sequence }  
 if sequence == s.selected_sequence_index and pos.line == s.selected_line_index then  
 current_pos = i  
 end  
 end  
 end  
 if pos_table[current_pos+s.transport.edit_step] then  
 s.selected_line_index = pos_table[current_pos+s.transport.edit_step].line  
 s.selected_sequence_index = pos_table[current_pos+s.transport.edit_step].sequence  
 else  
 s.selected_line_index = pos_table[table.count(pos_table)].line  
 s.selected_sequence_index = pos_table[table.count(pos_table)].sequence  
 end  
end  
  
function move_cursor()  
 s = renoise.song()  
 local new_position = s.selected_line_index + s.transport.edit_step  
 if new_position > s.selected_pattern.number_of_lines then  
 if s.transport.wrapped_pattern_edit then move_cursor_wrapping()  
 else s.selected_line_index = new_position - s.selected_pattern.number_of_lines end  
 else s.selected_line_index = new_position end  
end  
  
move_cursor()  
  

editstep?

Editstep is implemented. Editstep will also work across multiple patterns when pattern wrapping is on. That’s the reason why the code isn’t that slim, but it’s needed to make it behave the same way as native editstep.

Maybe editstep is the whole name of it? Good one. I didn’t think of that :)

Works as advertised. Good stuff!
If you want to expand on this, you could make the function also accept an arbitrary step value, including negative ones. That would make this even more useful!

proposed example usage:

  
move_cursor() --moves the cursor with default step, would be the current edit step  
move_cursor(1) --moves the cursor 1 line down  
move_cursor(-1) --moves the cursor 1 line up  
  

One optimization could also be to check if edit_step is zero, in which case the function would not have to run at all.

if editstep is zero, open up the next notecolumn. this would be perfect with the other script that adds a note effect (or a note delay) to the note.

KMaki, Good suggestions.

esaruoho, That would be a different tool. This is just meant as an “include” to use for a common task so people won’t have to reinvent the wheel all the time.

Bump. @joule: Sorry for the rude bumping here, you seem preoccupied with several cool tools! But… suppose you wouldn’t have a “move up also” version lying around somewhere…? :) If so, it sure would come in handy! If not, I just might have to dive in and try to mod that bugger for a simple tweak for my workflow.

both would be appreciated. also, how about one that resizes the notecolumn and goes from current row to current-row-on-note-column-CurrentNoteColumn+1 ?

Did this. Seems to work, but comments appreciated… I have to say I tried this a couple of times earlier, but did not manage to wrap my head around this. This time it appears I had more a)genius b)luck.

  
local s = nil  
  
function move_cursor_wrapping(step)  
 local pos_table = { }  
 local i = 0  
 local current_pos = nil  
  
 for sequence in ipairs(s.sequencer.pattern_sequence) do  
 for pos,column in s.pattern_iterator:lines_in_pattern_track(s.sequencer.pattern_sequence[sequence], s.selected_track_index) do  
 i = i + 1  
 pos_table[i] = { pattern = pos.pattern, line = pos.line, sequence = sequence }  
 if sequence == s.selected_sequence_index and pos.line == s.selected_line_index then  
 current_pos = i  
 end  
 end  
 end  
  
 if pos_table[current_pos+(step)] then  
 s.selected_sequence_index = pos_table[current_pos+step].sequence  
 s.selected_line_index = pos_table[current_pos+step].line  
 else  
 if step > 0 then  
 --ram to bottom  
 s.selected_sequence_index = pos_table[table.count(pos_table)].sequence  
 s.selected_line_index = pos_table[table.count(pos_table)].line  
 else  
 --ram to top  
 s.selected_sequence_index = 1  
 s.selected_line_index = 1  
 end  
 end  
  
end  
  
  
function move_cursor(step)  
 s = renoise.song()  
 step = step or s.transport.edit_step --default value for no args call=current edit_step  
 if step == 0 then end --no movement  
 local new_position = s.selected_line_index + step  
 if new_position > s.selected_pattern.number_of_lines or new_position < 1 then  
 if s.transport.wrapped_pattern_edit then  
 --move between patterns  
 move_cursor_wrapping(step)  
 else  
 --wrap around pattern edges  
 if step > 0 then  
 s.selected_line_index = new_position - s.selected_pattern.number_of_lines  
 else  
 s.selected_line_index = s.selected_pattern.number_of_lines + new_position  
 end  
 end  
 else  
 s.selected_line_index = new_position  
 end  
end  
  
move_cursor()  
  

This should accept any value, positive or negative. Default is current EditStep.

EDIT: Added test for zero movement, and fixed the ramming part that I just understood right now, looking at it on the forum. (Yeah. The usual. Noticing the errors after you post.)
EDIT: Yeah…
EDIT: Yep. Wasn’t wrapping around pattern edges until now. Yep.

can you wrap that into a xrnx, please, KMaki? Also, does it advance to next note column if editstep is 0?

The code I posted is old but works. I would recommend using pattern iterators instead. It would be much easier and fast as well.

EDIT: Oh sorry. That’s what i did.

Wrapping that into an xrnx would not really be that useful… If my calculations are correct, you’d get as a result a tool that advances 1 (one) line when you load up renoise. :D

And it does not do that column thing. Only the moving up and down on lines -thing…

The point of a snippet is to use it as a part of your own scripts. As a sub function of sorts. If you want to go to extremes with this sub-function business, save the snippet as a file of its own, with a snappy name (e.g. “movefunction.lua”), and put it in the folder of your main tool. Then, on your tool’s main.lua, put up a line like this:

  
require("movefunction")  
  

…after which you can move the cursor in your main tool by writing crazy instructions like:

  
move_cursor(10)  
--moves cursor 10 lines down  
  
a=renoise.song().selected_pattern_index  
move_cursor(a)  
--moves cursor down for the amount of the currently selected patterns index number. Not very useful, huh?  
  
move_cursor(-1 * renoise.song().selected_pattern.number_of_lines/2)  
--moves cursor up for the amount of half of the current patterns number of lines. Not that useful either. But kinda flashy.  
  
--etc..  
  

So in your main.lua, you don’t have to worry about the tiresome work of moving the cursor in an error-free way. You just move it.