(doc, pos, dir, unit, visually)
| 466 | // of the current position. The resulting position will have a |
| 467 | // hitSide=true property if it reached the end of the document. |
| 468 | function findPosH(doc, pos, dir, unit, visually) { |
| 469 | let oldPos = pos |
| 470 | let origDir = dir |
| 471 | let lineObj = getLine(doc, pos.line) |
| 472 | let lineDir = visually && doc.direction == "rtl" ? -dir : dir |
| 473 | function findNextLine() { |
| 474 | let l = pos.line + lineDir |
| 475 | if (l < doc.first || l >= doc.first + doc.size) return false |
| 476 | pos = new Pos(l, pos.ch, pos.sticky) |
| 477 | return lineObj = getLine(doc, l) |
| 478 | } |
| 479 | function moveOnce(boundToLine) { |
| 480 | let next |
| 481 | if (unit == "codepoint") { |
| 482 | let ch = lineObj.text.charCodeAt(pos.ch + (unit > 0 ? 0 : -1)) |
| 483 | if (isNaN(ch)) next = null |
| 484 | else next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (ch >= 0xD800 && ch < 0xDC00 ? 2 : 1))), |
| 485 | -dir) |
| 486 | } else if (visually) { |
| 487 | next = moveVisually(doc.cm, lineObj, pos, dir) |
| 488 | } else { |
| 489 | next = moveLogically(lineObj, pos, dir) |
| 490 | } |
| 491 | if (next == null) { |
| 492 | if (!boundToLine && findNextLine()) |
| 493 | pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir) |
| 494 | else |
| 495 | return false |
| 496 | } else { |
| 497 | pos = next |
| 498 | } |
| 499 | return true |
| 500 | } |
| 501 | |
| 502 | if (unit == "char" || unit == "codepoint") { |
| 503 | moveOnce() |
| 504 | } else if (unit == "column") { |
| 505 | moveOnce(true) |
| 506 | } else if (unit == "word" || unit == "group") { |
| 507 | let sawType = null, group = unit == "group" |
| 508 | let helper = doc.cm && doc.cm.getHelper(pos, "wordChars") |
| 509 | for (let first = true;; first = false) { |
| 510 | if (dir < 0 && !moveOnce(!first)) break |
| 511 | let cur = lineObj.text.charAt(pos.ch) || "\n" |
| 512 | let type = isWordChar(cur, helper) ? "w" |
| 513 | : group && cur == "\n" ? "n" |
| 514 | : !group || /\s/.test(cur) ? null |
| 515 | : "p" |
| 516 | if (group && !first && !type) type = "s" |
| 517 | if (sawType && sawType != type) { |
| 518 | if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after"} |
| 519 | break |
| 520 | } |
| 521 | |
| 522 | if (type) sawType = type |
| 523 | if (dir > 0 && !moveOnce(!first)) break |
| 524 | } |
| 525 | } |
no test coverage detected