Para encurtar a história: seria ótimo se os pontos de interrupção se movessem à medida que o código mudasse.
Em mais detalhes: seria ótimo ter identificadores de linha que persistem para as linhas. Esse recurso parece ser um pouco essencial para a experiência de edição, e os pontos de interrupção e as mensagens de erro devem ser vinculados aos identificadores de linha.
No cloud9, usamos change listener para atualizar pontos de interrupção em uma matriz separada https://github.com/ajaxorg/cloud9/blob/master/plugins-client/ext.debugger/breakpoints.js#L170
Como ace usa array de strings, não tenho certeza de como implementar melhor os identificadores de linha, seja um array completo de objetos mantidos em sincronia com as linhas ou use intervalos semelhantes ao manuseio de linhas de dobra em edit_session. A parte complicada é o manuseio de linhas que estão sendo divididas ou mescladas, pois diferentes tipos de anotações de linha precisam de comportamento diferente.
Acredito que sua solução para pontos de interrupção funcionaria bem para anotações.
A parte complicada é o manuseio de linhas que estão sendo divididas ou mescladas, pois diferentes tipos de anotações de linha precisam de comportamento diferente.
Hmm.. Não consigo inventar um único exemplo. Agradeceria se compartilhasse alguns :)
Encontrei uma solução, mas funciona apenas no meu caso porque permito apenas um ponto de interrupção por vez. Com alguma melhora pode caber também para o caso geral.
Eu usei o ouvinte on change na instância do editor e verifiquei o número de linhas que são modificadas pela ação que disparou o evento. Se forem mais de uma, estamos no caso em que uma ou mais linhas são adicionadas ou removidas. O parâmetro de ação do evento nos ajuda a entender em que caso estamos.
Para ver se tenho que mover o(s) breakpoint(s) verifico se está entre a linha inicial e final da modificação. Se estiver nessa faixa eu tenho que me mover.
O código (escrito rapidamente) é o seguinte:
aceEditor.on("change", function (e) {
var breakpointsArray = aceEditor.session.getBreakpoints();
if(Object.keys(aceEditor.session.getBreakpoints()).length>0){
if(e.lines.length>1){
var breakpoint = parseInt(Object.keys(breakpointsArray)[0]);
var lines = e.lines.length -1;
var start = e.start.row;
var end = e.end.row;
if(e.action==='insert'){
console.log('new lines',breakpoint, start , end );
if(breakpoint>start ){
console.log('breakpoint forward');
aceEditor.session.clearBreakpoint(breakpoint);
aceEditor.session.setBreakpoint(breakpoint + lines);
}
} else if(e.action==='remove'){
console.log('removed lines',breakpoint, start , end);
if(breakpoint>start && breakpoint<end ){
console.log('breakpoint remove');
aceEditor.session.clearBreakpoint(breakpoint);
}
if(breakpoint>=end ){
console.log('breakpoint behind');
aceEditor.session.clearBreakpoint(breakpoint);
aceEditor.session.setBreakpoint(breakpoint - lines);
}
}
}
}
});
Espero ter ajudado alguém!
Modifiquei a solução de alessandrocaprarelli acima para funcionar em vários pontos de interrupção, pode ser útil para outros:
editor.on("change", function (e) {
if (e.lines.length > 1 && (e.action==='insert' || e.action==='remove')){
const breakpointsArrayOld = editor.session.getBreakpoints();
let breakpointsArrayNew = [];
const amountOfLinesAffected = e.lines.length - 1;
const startRow = e.start.row;
const endRow = e.end.row;
for (const key of Object.keys(breakpointsArrayOld)) {
let breakpointRow = parseInt(key)
if (e.action==='insert') { // new lines
if (breakpointRow > startRow ){
// breakpoint forward
breakpointsArrayNew[breakpointRow + amountOfLinesAffected] = "ace_breakpoint"
}
else {
// unaffected by insert
breakpointsArrayNew[breakpointRow] = "ace_breakpoint"
}
}
else if (e.action==='remove') { // removed lines
if (breakpointRow > startRow && breakpointRow <= endRow ){
// breakpoint removed
}
else if (breakpointRow >= endRow ){
// breakpoint behind
breakpointsArrayNew[breakpointRow - amountOfLinesAffected] = "ace_breakpoint"
}
else {
// unaffected by remove
breakpointsArrayNew[breakpointRow] = "ace_breakpoint"
}
}
}
// remove all old breakpoints
for (const key of Object.keys(breakpointsArrayOld)) {
let breakpointRow = parseInt(key)
editor.session.clearBreakpoint(breakpointRow);
}
// add all new breakpoints
for (const key of Object.keys(breakpointsArrayNew)) {
let breakpointRow = parseInt(key)
editor.session.setBreakpoint(breakpointRow);
}
}
})
Comentários muito úteis
Encontrei uma solução, mas funciona apenas no meu caso porque permito apenas um ponto de interrupção por vez. Com alguma melhora pode caber também para o caso geral.
Eu usei o ouvinte on change na instância do editor e verifiquei o número de linhas que são modificadas pela ação que disparou o evento. Se forem mais de uma, estamos no caso em que uma ou mais linhas são adicionadas ou removidas. O parâmetro de ação do evento nos ajuda a entender em que caso estamos.
Para ver se tenho que mover o(s) breakpoint(s) verifico se está entre a linha inicial e final da modificação. Se estiver nessa faixa eu tenho que me mover.
O código (escrito rapidamente) é o seguinte:
Espero ter ajudado alguém!