openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

indent.js (2757B)


      1 import { getContextBefore } from "../line/highlight.js"
      2 import { Pos } from "../line/pos.js"
      3 import { getLine } from "../line/utils_line.js"
      4 import { replaceRange } from "../model/changes.js"
      5 import { Range } from "../model/selection.js"
      6 import { replaceOneSelection } from "../model/selection_updates.js"
      7 import { countColumn, Pass, spaceStr } from "../util/misc.js"
      8 
      9 // Indent the given line. The how parameter can be "smart",
     10 // "add"/null, "subtract", or "prev". When aggressive is false
     11 // (typically set to true for forced single-line indents), empty
     12 // lines are not indented, and places where the mode returns Pass
     13 // are left alone.
     14 export function indentLine(cm, n, how, aggressive) {
     15   let doc = cm.doc, state
     16   if (how == null) how = "add"
     17   if (how == "smart") {
     18     // Fall back to "prev" when the mode doesn't have an indentation
     19     // method.
     20     if (!doc.mode.indent) how = "prev"
     21     else state = getContextBefore(cm, n).state
     22   }
     23 
     24   let tabSize = cm.options.tabSize
     25   let line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize)
     26   if (line.stateAfter) line.stateAfter = null
     27   let curSpaceString = line.text.match(/^\s*/)[0], indentation
     28   if (!aggressive && !/\S/.test(line.text)) {
     29     indentation = 0
     30     how = "not"
     31   } else if (how == "smart") {
     32     indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text)
     33     if (indentation == Pass || indentation > 150) {
     34       if (!aggressive) return
     35       how = "prev"
     36     }
     37   }
     38   if (how == "prev") {
     39     if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize)
     40     else indentation = 0
     41   } else if (how == "add") {
     42     indentation = curSpace + cm.options.indentUnit
     43   } else if (how == "subtract") {
     44     indentation = curSpace - cm.options.indentUnit
     45   } else if (typeof how == "number") {
     46     indentation = curSpace + how
     47   }
     48   indentation = Math.max(0, indentation)
     49 
     50   let indentString = "", pos = 0
     51   if (cm.options.indentWithTabs)
     52     for (let i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t"}
     53   if (pos < indentation) indentString += spaceStr(indentation - pos)
     54 
     55   if (indentString != curSpaceString) {
     56     replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input")
     57     line.stateAfter = null
     58     return true
     59   } else {
     60     // Ensure that, if the cursor was in the whitespace at the start
     61     // of the line, it is moved to the end of that space.
     62     for (let i = 0; i < doc.sel.ranges.length; i++) {
     63       let range = doc.sel.ranges[i]
     64       if (range.head.line == n && range.head.ch < curSpaceString.length) {
     65         let pos = Pos(n, curSpaceString.length)
     66         replaceOneSelection(doc, i, new Range(pos, pos))
     67         break
     68       }
     69     }
     70   }
     71 }