|
|
1.1 ! root 1: ;; Note: use ! 2: ;; (autoload 'icon-mode "icon" nil t) ! 3: ;; (setq auto-mode-alist (cons '("\\.icn$" . icon-mode) auto-mode-alist)) ! 4: ;; if not permanently installed in your emacs ! 5: ! 6: ;; Icon code editing commands for Emacs ! 7: ;; from c-mode.el 13-Apr-88 Chris Smith; bugs to convex!csmith ! 8: ;; Copyright (C) 1988 Free Software Foundation, Inc. ! 9: ! 10: ;; This file is part of GNU Emacs. ! 11: ! 12: ;; GNU Emacs is distributed in the hope that it will be useful, ! 13: ;; but WITHOUT ANY WARRANTY. No author or distributor ! 14: ;; accepts responsibility to anyone for the consequences of using it ! 15: ;; or for whether it serves any particular purpose or works at all, ! 16: ;; unless he says so in writing. Refer to the GNU Emacs General Public ! 17: ;; License for full details. ! 18: ! 19: ;; Everyone is granted permission to copy, modify and redistribute ! 20: ;; GNU Emacs, but only under the conditions described in the ! 21: ;; GNU Emacs General Public License. A copy of this license is ! 22: ;; supposed to have been given to you along with GNU Emacs so you ! 23: ;; can know your rights and responsibilities. It should be in a ! 24: ;; file named COPYING. Among other things, the copyright notice ! 25: ;; and this notice must be preserved on all copies. ! 26: ! 27: ! 28: (defvar icon-mode-abbrev-table nil ! 29: "Abbrev table in use in Icon-mode buffers.") ! 30: (define-abbrev-table 'icon-mode-abbrev-table ()) ! 31: ! 32: (defvar icon-mode-map () ! 33: "Keymap used in Icon mode.") ! 34: (if icon-mode-map ! 35: () ! 36: (setq icon-mode-map (make-sparse-keymap)) ! 37: (define-key icon-mode-map "{" 'electric-icon-brace) ! 38: (define-key icon-mode-map "}" 'electric-icon-brace) ! 39: (define-key icon-mode-map "\e\C-h" 'mark-icon-function) ! 40: (define-key icon-mode-map "\e\C-a" 'beginning-of-icon-defun) ! 41: (define-key icon-mode-map "\e\C-e" 'end-of-icon-defun) ! 42: (define-key icon-mode-map "\e\C-q" 'indent-icon-exp) ! 43: (define-key icon-mode-map "\177" 'backward-delete-char-untabify) ! 44: (define-key icon-mode-map "\t" 'icon-indent-command)) ! 45: ! 46: (defvar icon-mode-syntax-table nil ! 47: "Syntax table in use in Icon-mode buffers.") ! 48: ! 49: (if icon-mode-syntax-table ! 50: () ! 51: (setq icon-mode-syntax-table (make-syntax-table)) ! 52: (modify-syntax-entry ?\\ "\\" icon-mode-syntax-table) ! 53: (modify-syntax-entry ?# "<" icon-mode-syntax-table) ! 54: (modify-syntax-entry ?\n ">" icon-mode-syntax-table) ! 55: (modify-syntax-entry ?$ "." icon-mode-syntax-table) ! 56: (modify-syntax-entry ?/ "." icon-mode-syntax-table) ! 57: (modify-syntax-entry ?* "." icon-mode-syntax-table) ! 58: (modify-syntax-entry ?+ "." icon-mode-syntax-table) ! 59: (modify-syntax-entry ?- "." icon-mode-syntax-table) ! 60: (modify-syntax-entry ?= "." icon-mode-syntax-table) ! 61: (modify-syntax-entry ?% "." icon-mode-syntax-table) ! 62: (modify-syntax-entry ?< "." icon-mode-syntax-table) ! 63: (modify-syntax-entry ?> "." icon-mode-syntax-table) ! 64: (modify-syntax-entry ?& "." icon-mode-syntax-table) ! 65: (modify-syntax-entry ?| "." icon-mode-syntax-table) ! 66: (modify-syntax-entry ?\' "\"" icon-mode-syntax-table)) ! 67: ! 68: (defconst icon-indent-level 4 ! 69: "*Indentation of Icon statements with respect to containing block.") ! 70: (defconst icon-brace-imaginary-offset 0 ! 71: "*Imagined indentation of a Icon open brace that actually follows a statement.") ! 72: (defconst icon-brace-offset 0 ! 73: "*Extra indentation for braces, compared with other text in same context.") ! 74: (defconst icon-continued-statement-offset 4 ! 75: "*Extra indent for lines not starting new statements.") ! 76: (defconst icon-continued-brace-offset 0 ! 77: "*Extra indent for substatements that start with open-braces. ! 78: This is in addition to icon-continued-statement-offset.") ! 79: ! 80: (defconst icon-auto-newline nil ! 81: "*Non-nil means automatically newline before and after braces, ! 82: and after colons and semicolons, inserted in C code.") ! 83: ! 84: (defconst icon-tab-always-indent t ! 85: "*Non-nil means TAB in Icon mode should always reindent the current line, ! 86: regardless of where in the line point is when the TAB command is used.") ! 87: ! 88: (defun icon-mode () ! 89: "Major mode for editing Icon code. ! 90: Expression and list commands understand all Icon brackets. ! 91: Tab indents for Icon code. ! 92: Paragraphs are separated by blank lines only. ! 93: Delete converts tabs to spaces as it moves back. ! 94: \\{icon-mode-map} ! 95: Variables controlling indentation style: ! 96: icon-tab-always-indent ! 97: Non-nil means TAB in Icon mode should always reindent the current line, ! 98: regardless of where in the line point is when the TAB command is used. ! 99: icon-auto-newline ! 100: Non-nil means automatically newline before and after braces ! 101: inserted in Icon code. ! 102: icon-indent-level ! 103: Indentation of Icon statements within surrounding block. ! 104: The surrounding block's indentation is the indentation ! 105: of the line on which the open-brace appears. ! 106: icon-continued-statement-offset ! 107: Extra indentation given to a substatement, such as the ! 108: then-clause of an if or body of a while. ! 109: icon-continued-brace-offset ! 110: Extra indentation given to a brace that starts a substatement. ! 111: This is in addition to icon-continued-statement-offset. ! 112: icon-brace-offset ! 113: Extra indentation for line if it starts with an open brace. ! 114: icon-brace-imaginary-offset ! 115: An open brace following other text is treated as if it were ! 116: this far to the right of the start of its line. ! 117: ! 118: Turning on Icon mode calls the value of the variable icon-mode-hook with no args, ! 119: if that value is non-nil." ! 120: (interactive) ! 121: (kill-all-local-variables) ! 122: (use-local-map icon-mode-map) ! 123: (setq major-mode 'icon-mode) ! 124: (setq mode-name "Icon") ! 125: (setq local-abbrev-table icon-mode-abbrev-table) ! 126: (set-syntax-table icon-mode-syntax-table) ! 127: (make-local-variable 'paragraph-start) ! 128: (setq paragraph-start (concat "^$\\|" page-delimiter)) ! 129: (make-local-variable 'paragraph-separate) ! 130: (setq paragraph-separate paragraph-start) ! 131: (make-local-variable 'indent-line-function) ! 132: (setq indent-line-function 'icon-indent-line) ! 133: (make-local-variable 'require-final-newline) ! 134: (setq require-final-newline t) ! 135: (make-local-variable 'comment-start) ! 136: (setq comment-start "# ") ! 137: (make-local-variable 'comment-end) ! 138: (setq comment-end "") ! 139: (make-local-variable 'comment-column) ! 140: (setq comment-column 32) ! 141: (make-local-variable 'comment-start-skip) ! 142: (setq comment-start-skip "# *") ! 143: (make-local-variable 'comment-indent-hook) ! 144: (setq comment-indent-hook 'icon-comment-indent) ! 145: (run-hooks 'icon-mode-hook)) ! 146: ! 147: ;; This is used by indent-for-comment ! 148: ;; to decide how much to indent a comment in Icon code ! 149: ;; based on its context. ! 150: (defun icon-comment-indent () ! 151: (if (looking-at "^#") ! 152: 0 ;Existing comment at bol stays there. ! 153: (save-excursion ! 154: (skip-chars-backward " \t") ! 155: (max (1+ (current-column)) ;Else indent at comment column ! 156: comment-column)))) ; except leave at least one space. ! 157: ! 158: (defun electric-icon-brace (arg) ! 159: "Insert character and correct line's indentation." ! 160: (interactive "P") ! 161: (let (insertpos) ! 162: (if (and (not arg) ! 163: (eolp) ! 164: (or (save-excursion ! 165: (skip-chars-backward " \t") ! 166: (bolp)) ! 167: (if icon-auto-newline ! 168: (progn (icon-indent-line) (newline) t) ! 169: nil))) ! 170: (progn ! 171: (insert last-command-char) ! 172: (icon-indent-line) ! 173: (if icon-auto-newline ! 174: (progn ! 175: (newline) ! 176: ;; (newline) may have done auto-fill ! 177: (setq insertpos (- (point) 2)) ! 178: (icon-indent-line))) ! 179: (save-excursion ! 180: (if insertpos (goto-char (1+ insertpos))) ! 181: (delete-char -1)))) ! 182: (if insertpos ! 183: (save-excursion ! 184: (goto-char insertpos) ! 185: (self-insert-command (prefix-numeric-value arg))) ! 186: (self-insert-command (prefix-numeric-value arg))))) ! 187: ! 188: (defun icon-indent-command (&optional whole-exp) ! 189: (interactive "P") ! 190: "Indent current line as Icon code, or in some cases insert a tab character. ! 191: If icon-tab-always-indent is non-nil (the default), always indent current line. ! 192: Otherwise, indent the current line only if point is at the left margin ! 193: or in the line's indentation; otherwise insert a tab. ! 194: ! 195: A numeric argument, regardless of its value, ! 196: means indent rigidly all the lines of the expression starting after point ! 197: so that this line becomes properly indented. ! 198: The relative indentation among the lines of the expression are preserved." ! 199: (if whole-exp ! 200: ;; If arg, always indent this line as Icon ! 201: ;; and shift remaining lines of expression the same amount. ! 202: (let ((shift-amt (icon-indent-line)) ! 203: beg end) ! 204: (save-excursion ! 205: (if icon-tab-always-indent ! 206: (beginning-of-line)) ! 207: (setq beg (point)) ! 208: (forward-sexp 1) ! 209: (setq end (point)) ! 210: (goto-char beg) ! 211: (forward-line 1) ! 212: (setq beg (point))) ! 213: (if (> end beg) ! 214: (indent-code-rigidly beg end shift-amt "#"))) ! 215: (if (and (not icon-tab-always-indent) ! 216: (save-excursion ! 217: (skip-chars-backward " \t") ! 218: (not (bolp)))) ! 219: (insert-tab) ! 220: (icon-indent-line)))) ! 221: ! 222: (defun icon-indent-line () ! 223: "Indent current line as Icon code. ! 224: Return the amount the indentation changed by." ! 225: (let ((indent (calculate-icon-indent nil)) ! 226: beg shift-amt ! 227: (case-fold-search nil) ! 228: (pos (- (point-max) (point)))) ! 229: (beginning-of-line) ! 230: (setq beg (point)) ! 231: (cond ((eq indent nil) ! 232: (setq indent (current-indentation))) ! 233: ((eq indent t) ! 234: (setq indent (calculate-icon-indent-within-comment))) ! 235: ((looking-at "[ \t]*#") ! 236: (setq indent 0)) ! 237: (t ! 238: (skip-chars-forward " \t") ! 239: (if (listp indent) (setq indent (car indent))) ! 240: (cond ((and (looking-at "else\\b") ! 241: (not (looking-at "else\\s_"))) ! 242: (setq indent (save-excursion ! 243: (icon-backward-to-start-of-if) ! 244: (current-indentation)))) ! 245: ((or (= (following-char) ?}) ! 246: (looking-at "end\\b")) ! 247: (setq indent (- indent icon-indent-level))) ! 248: ((= (following-char) ?{) ! 249: (setq indent (+ indent icon-brace-offset)))))) ! 250: (skip-chars-forward " \t") ! 251: (setq shift-amt (- indent (current-column))) ! 252: (if (zerop shift-amt) ! 253: (if (> (- (point-max) pos) (point)) ! 254: (goto-char (- (point-max) pos))) ! 255: (delete-region beg (point)) ! 256: (indent-to indent) ! 257: ;; If initial point was within line's indentation, ! 258: ;; position after the indentation. Else stay at same point in text. ! 259: (if (> (- (point-max) pos) (point)) ! 260: (goto-char (- (point-max) pos)))) ! 261: shift-amt)) ! 262: ! 263: (defun calculate-icon-indent (&optional parse-start) ! 264: "Return appropriate indentation for current line as Icon code. ! 265: In usual case returns an integer: the column to indent to. ! 266: Returns nil if line starts inside a string, t if in a comment." ! 267: (save-excursion ! 268: (beginning-of-line) ! 269: (let ((indent-point (point)) ! 270: (case-fold-search nil) ! 271: state ! 272: containing-sexp ! 273: toplevel) ! 274: (if parse-start ! 275: (goto-char parse-start) ! 276: (setq toplevel (beginning-of-icon-defun))) ! 277: (while (< (point) indent-point) ! 278: (setq parse-start (point)) ! 279: (setq state (parse-partial-sexp (point) indent-point 0)) ! 280: (setq containing-sexp (car (cdr state)))) ! 281: (cond ((or (nth 3 state) (nth 4 state)) ! 282: ;; return nil or t if should not change this line ! 283: (nth 4 state)) ! 284: ((and containing-sexp ! 285: (/= (char-after containing-sexp) ?{)) ! 286: ;; line is expression, not statement: ! 287: ;; indent to just after the surrounding open. ! 288: (goto-char (1+ containing-sexp)) ! 289: (current-column)) ! 290: (t ! 291: ;; Statement level. Is it a continuation or a new statement? ! 292: ;; Find previous non-comment character. ! 293: (if toplevel ! 294: (progn (icon-backward-to-noncomment (point-min)) ! 295: (if (icon-is-continuation-line) ! 296: icon-continued-statement-offset 0)) ! 297: (if (null containing-sexp) ! 298: (progn (beginning-of-icon-defun) ! 299: (setq containing-sexp (point)))) ! 300: (goto-char indent-point) ! 301: (icon-backward-to-noncomment containing-sexp) ! 302: ;; Now we get the answer. ! 303: (if (icon-is-continuation-line) ! 304: ;; This line is continuation of preceding line's statement; ! 305: ;; indent icon-continued-statement-offset more than the ! 306: ;; first line of the statement. ! 307: (progn ! 308: (icon-backward-to-start-of-continued-exp containing-sexp) ! 309: (+ icon-continued-statement-offset (current-column) ! 310: (if (save-excursion (goto-char indent-point) ! 311: (skip-chars-forward " \t") ! 312: (eq (following-char) ?{)) ! 313: icon-continued-brace-offset 0))) ! 314: ;; This line starts a new statement. ! 315: ;; Position following last unclosed open. ! 316: (goto-char containing-sexp) ! 317: ;; Is line first statement after an open-brace? ! 318: (or ! 319: ;; If no, find that first statement and indent like it. ! 320: (save-excursion ! 321: (if (looking-at "procedure\\s ") ! 322: (forward-sexp 3) ! 323: (forward-char 1)) ! 324: (while (progn (skip-chars-forward " \t\n") ! 325: (looking-at "#")) ! 326: ;; Skip over comments following openbrace. ! 327: (forward-line 1)) ! 328: ;; The first following code counts ! 329: ;; if it is before the line we want to indent. ! 330: (and (< (point) indent-point) ! 331: (current-column))) ! 332: ;; If no previous statement, ! 333: ;; indent it relative to line brace is on. ! 334: ;; For open brace in column zero, don't let statement ! 335: ;; start there too. If icon-indent-level is zero, ! 336: ;; use icon-brace-offset + icon-continued-statement-offset instead. ! 337: ;; For open-braces not the first thing in a line, ! 338: ;; add in icon-brace-imaginary-offset. ! 339: (+ (if (and (bolp) (zerop icon-indent-level)) ! 340: (+ icon-brace-offset icon-continued-statement-offset) ! 341: icon-indent-level) ! 342: ;; Move back over whitespace before the openbrace. ! 343: ;; If openbrace is not first nonwhite thing on the line, ! 344: ;; add the icon-brace-imaginary-offset. ! 345: (progn (skip-chars-backward " \t") ! 346: (if (bolp) 0 icon-brace-imaginary-offset)) ! 347: ;; here we are ! 348: (current-indentation)))))))))) ! 349: ! 350: (defun icon-is-continuation-line () ! 351: (let* ((ch (preceding-char)) ! 352: (ch-syntax (char-syntax ch))) ! 353: (if (eq ch-syntax ?w) ! 354: (assoc (buffer-substring ! 355: (progn (forward-word -1) (point)) ! 356: (progn (forward-word 1) (point))) ! 357: '(("do") ("dynamic") ("else") ("initial") ("link") ! 358: ("local") ("of") ("static") ("then"))) ! 359: (not (memq ch '(0 ?\; ?\} ?\{ ?\) ?\] ?\" ?\' ?\n)))))) ! 360: ! 361: (defun icon-backward-to-noncomment (lim) ! 362: (let (opoint stop) ! 363: (while (not stop) ! 364: (skip-chars-backward " \t\n\f" lim) ! 365: (setq opoint (point)) ! 366: (beginning-of-line) ! 367: (if (and (search-forward "#" opoint 'move) ! 368: (< lim (point))) ! 369: (forward-char -1) ! 370: (setq stop t))))) ! 371: ! 372: (defun icon-backward-to-start-of-continued-exp (lim) ! 373: (if (memq (preceding-char) '(?\) ?\])) ! 374: (forward-sexp -1)) ! 375: (while (icon-is-continued-line) ! 376: (end-of-line 0)) ! 377: (beginning-of-line) ! 378: (if (<= (point) lim) ! 379: (goto-char (1+ lim))) ! 380: (skip-chars-forward " \t")) ! 381: ! 382: (defun icon-is-continued-line () ! 383: (save-excursion ! 384: (end-of-line 0) ! 385: (icon-is-continuation-line))) ! 386: ! 387: (defun icon-backward-to-start-of-if (&optional limit) ! 388: "Move to the start of the last ``unbalanced'' if." ! 389: (or limit (setq limit (save-excursion (beginning-of-icon-defun) (point)))) ! 390: (let ((if-level 1) ! 391: (case-fold-search nil)) ! 392: (while (not (zerop if-level)) ! 393: (backward-sexp 1) ! 394: (cond ((looking-at "else\\b") ! 395: (setq if-level (1+ if-level))) ! 396: ((looking-at "if\\b") ! 397: (setq if-level (1- if-level))) ! 398: ((< (point) limit) ! 399: (setq if-level 0) ! 400: (goto-char limit)))))) ! 401: ! 402: (defun mark-icon-function () ! 403: "Put mark at end of Icon function, point at beginning." ! 404: (interactive) ! 405: (push-mark (point)) ! 406: (end-of-icon-defun) ! 407: (push-mark (point)) ! 408: (beginning-of-line 0) ! 409: (beginning-of-icon-defun)) ! 410: ! 411: (defun beginning-of-icon-defun () ! 412: "Go to the start of the enclosing procedure; return t if at top level." ! 413: (interactive) ! 414: (if (re-search-backward "^procedure\\s \\|^end[ \t\n]" (point-min) 'move) ! 415: (looking-at "e") ! 416: t)) ! 417: ! 418: (defun end-of-icon-defun () ! 419: (interactive) ! 420: (if (not (bobp)) (forward-char -1)) ! 421: (re-search-forward "\\(\\s \\|^\\)end\\(\\s \\|$\\)" (point-max) 'move) ! 422: (forward-word -1) ! 423: (forward-line 1)) ! 424: ! 425: (defun indent-icon-exp () ! 426: "Indent each line of the Icon grouping following point." ! 427: (interactive) ! 428: (let ((indent-stack (list nil)) ! 429: (contain-stack (list (point))) ! 430: (case-fold-search nil) ! 431: restart outer-loop-done inner-loop-done state ostate ! 432: this-indent last-sexp ! 433: at-else at-brace at-do ! 434: (opoint (point)) ! 435: (next-depth 0)) ! 436: (save-excursion ! 437: (forward-sexp 1)) ! 438: (save-excursion ! 439: (setq outer-loop-done nil) ! 440: (while (and (not (eobp)) (not outer-loop-done)) ! 441: (setq last-depth next-depth) ! 442: ;; Compute how depth changes over this line ! 443: ;; plus enough other lines to get to one that ! 444: ;; does not end inside a comment or string. ! 445: ;; Meanwhile, do appropriate indentation on comment lines. ! 446: (setq innerloop-done nil) ! 447: (while (and (not innerloop-done) ! 448: (not (and (eobp) (setq outer-loop-done t)))) ! 449: (setq ostate state) ! 450: (setq state (parse-partial-sexp (point) (progn (end-of-line) (point)) ! 451: nil nil state)) ! 452: (setq next-depth (car state)) ! 453: (if (and (car (cdr (cdr state))) ! 454: (>= (car (cdr (cdr state))) 0)) ! 455: (setq last-sexp (car (cdr (cdr state))))) ! 456: (if (or (nth 4 ostate)) ! 457: (icon-indent-line)) ! 458: (if (or (nth 3 state)) ! 459: (forward-line 1) ! 460: (setq innerloop-done t))) ! 461: (if (<= next-depth 0) ! 462: (setq outer-loop-done t)) ! 463: (if outer-loop-done ! 464: nil ! 465: (if (/= last-depth next-depth) ! 466: (setq last-sexp nil)) ! 467: (while (> last-depth next-depth) ! 468: (setq indent-stack (cdr indent-stack) ! 469: contain-stack (cdr contain-stack) ! 470: last-depth (1- last-depth))) ! 471: (while (< last-depth next-depth) ! 472: (setq indent-stack (cons nil indent-stack) ! 473: contain-stack (cons nil contain-stack) ! 474: last-depth (1+ last-depth))) ! 475: (if (null (car contain-stack)) ! 476: (setcar contain-stack (or (car (cdr state)) ! 477: (save-excursion (forward-sexp -1) ! 478: (point))))) ! 479: (forward-line 1) ! 480: (skip-chars-forward " \t") ! 481: (if (eolp) ! 482: nil ! 483: (if (and (car indent-stack) ! 484: (>= (car indent-stack) 0)) ! 485: ;; Line is on an existing nesting level. ! 486: ;; Lines inside parens are handled specially. ! 487: (if (/= (char-after (car contain-stack)) ?{) ! 488: (setq this-indent (car indent-stack)) ! 489: ;; Line is at statement level. ! 490: ;; Is it a new statement? Is it an else? ! 491: ;; Find last non-comment character before this line ! 492: (save-excursion ! 493: (setq at-else (looking-at "else\\W")) ! 494: (setq at-brace (= (following-char) ?{)) ! 495: (icon-backward-to-noncomment opoint) ! 496: (if (icon-is-continuation-line) ! 497: ;; Preceding line did not end in comma or semi; ! 498: ;; indent this line icon-continued-statement-offset ! 499: ;; more than previous. ! 500: (progn ! 501: (icon-backward-to-start-of-continued-exp (car contain-stack)) ! 502: (setq this-indent ! 503: (+ icon-continued-statement-offset (current-column) ! 504: (if at-brace icon-continued-brace-offset 0)))) ! 505: ;; Preceding line ended in comma or semi; ! 506: ;; use the standard indent for this level. ! 507: (if at-else ! 508: (progn (icon-backward-to-start-of-if opoint) ! 509: (setq this-indent (current-indentation))) ! 510: (setq this-indent (car indent-stack)))))) ! 511: ;; Just started a new nesting level. ! 512: ;; Compute the standard indent for this level. ! 513: (let ((val (calculate-icon-indent ! 514: (if (car indent-stack) ! 515: (- (car indent-stack)))))) ! 516: (setcar indent-stack ! 517: (setq this-indent val)))) ! 518: ;; Adjust line indentation according to its contents ! 519: (if (or (= (following-char) ?}) ! 520: (looking-at "end\\b")) ! 521: (setq this-indent (- this-indent icon-indent-level))) ! 522: (if (= (following-char) ?{) ! 523: (setq this-indent (+ this-indent icon-brace-offset))) ! 524: ;; Put chosen indentation into effect. ! 525: (or (= (current-column) this-indent) ! 526: (progn ! 527: (delete-region (point) (progn (beginning-of-line) (point))) ! 528: (indent-to this-indent))) ! 529: ;; Indent any comment following the text. ! 530: (or (looking-at comment-start-skip) ! 531: (if (re-search-forward comment-start-skip (save-excursion (end-of-line) (point)) t) ! 532: (progn (indent-for-comment) (beginning-of-line))))))))))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.