pax_global_header00006660000000000000000000000064116173555440014525gustar00rootroot0000000000000052 comment=0b88f46f523dda7afd674b41a0fb8af20985c382 diakonos-0.9.0/000077500000000000000000000000001161735554400133425ustar00rootroot00000000000000diakonos-0.9.0/.gitignore000066400000000000000000000001021161735554400153230ustar00rootroot00000000000000*.gem *.tar.bz2 *.tar.gz spec/test-files/temp-file.rb .yardoc doc diakonos-0.9.0/CHANGELOG000066400000000000000000000337601161735554400145650ustar00rootroot00000000000000Diakonos Changelog ------------------ 0.9.0 - Added partial UTF-8 support (only characters the same width as US-ASCII). 0.8.15 - Introduced open_as_first_buffer setting (default false). - Now shows number of matches found after searching. - Now shows number of replacements made. - Now switches to previous buffer when switching to the current buffer by number. - Last search and readline histories are now saved to sessions. - Added delete_from function. - Added key.after configuration directive for history-sensitive key mapping. - Added select_word function. Mapped to by default. - Added select_word_another function. Mapped to after select_word. - Added search for word, mapped to by default. - Undo now opens any just-closed file. - Fixed find_again behaviour for buffers without search history. 0.8.14 - comment_out now skips blank lines. - Added renumber_buffer function. Default . - Can now configure fuzzy_file_find.ignore globs and fuzzy_file_find.max_files. - go_to_char and go_to_char_previous now support an optional :after argument. - delete_to_and_from now supports an optional :inclusive argument. - More effecient marking of undo points when pasting external text or typing fast. - Added more info about config files in About page. - Display-related bug fixes and improvements. - Ruby 1.9.2 is now the minimum Ruby version required for Diakonos. 0.8.13 Contributors: Pistos - Added different_file argument to cursor_return. - Remapped different-file cursor_return to and . - Added KDE4 Klipper support (via dbus). - Now automatically jumps to first merge conflict (if any) on startup. - Added find_clip function. - Now switches to existing buffer when trying to open a file that is already loaded. - Now supports more formats for opening files at specific line numbers. - Added keys to switch to buffers 10 through 19. through . - Numerous minor fixes and improvements. 0.8.12 Contributors: Pistos - Refactored keying system. - Introduced keying modes. - Ruby version now enforced, both at installation and run time. - Input line can now scroll if input is longer than screen width. - Added support for session completion in zsh and bash. - Added select_line. - Added select_wrapping_block (default key: Alt-space). - Searching is now restricted to the selected text, if any. - Added view.non_search_area.format. - Fixed cursor stack. - Cursor stack is now global (cross-buffer). - Simplified switch_to_next_buffer and switch_to_prev_buffer; no more history. - Added chdir function. - Various refactorings. - Various bug fixes. 0.8.11 Contributors: Pistos, dominikh - Added join_lines_upward (Alt-Shift-J). - Added one-key selection in buffer list. - Added support for single line indentation. - Added extension system. - Added surround_selection and related functions. - Added "about" page. - Various bug fixes and refactorings. 0.8.10 Contributors: Pistos, dominikh - Ruby version 1.9+ now required. (Ruby 1.8 support dropped) - Added go_to_char (Alt-N). - Added go_to_char_previous (Alt-P). - shell command now shows executed command on interaction line. - shell command is now interruptible. - Klipper synchronization now a single setting (clipboard.external klipper). - Added xclip support. - Cursor and viewport positions now saved in and restored from sessions. - Current buffer number now saved in sessions. - Fixed context line. - Textual indication of no shell results now given. - Added basic pair (bracket) highlighting. - Added go_to_pair_match (Alt-Shift-[). - Fixed chmodding in installer. - Undo and redo now actually compare file contents to set "modified" flag. - Added support for a special 'all' language, whose formats apply no matter the current language. - Added dynamic prefix expansion (Alt-E). 0.8.9 Contributors: Pistos, Decklin Foster - Put interaction timer only on first stale session prompt, not any after that. - Changed all function names from camelCase to snake_case. - Added --help-dir switch to installer. - Fixed some issues with installer. - Changed delete_to_and_from to always assume given character is the left side character when matching pairs. - Fixed a line number display bug. - X windows pasting handled much better now. - Numerous internal refactorings and reorganizations. 0.8.8 - New installation and uninstallation method: tarball + install.rb. - Added configuration setting inheritance. - Added block selection mode (Alt-Shift-M B; Alt-Shift-M N). - Added line numbering settings. - Added spawn function. - Added go_block_previous, go_block_next (Ctrl-PageUp, Ctrl-PageDown). - Added go_block_outer, go_block_inner (Alt-PageUp, Alt-PageDown). - "Remove word" functionality (Ctrl-W) added to readline. - Added find.show_context_after setting. - Added view.column_markers. - Added lang.____.indent.not_indented setting. - Introduced $d shell variable: current buffer's directory. - $f and $d now expand to absolute paths. - delete_to and delete_to_and_from can now operate over multiple lines. - delete_to_and_from can now delete between matching brackets. - Added git diff (F9). - Ruby 1.9 support smoothed out. Ruby 1.8 support being deprecated. - Support for non-ASCII encodings tentatively confirmed. - Several bugs fixed. - Help files updated. 0.8.7 - MRU buffer history added. - strip_trailing_whitespace_on_save setting added. - Sessions (named and unnamed) added. - grep as you type added. - delete_to added. - delete_to_and_from added. - find.return_on_abort setting added. - Makefile config added. - Markdown config added. - Sass config added. - Now including custom.conf from default diakonos.conf. - Help files updated. - Some Ruby 1.9 compatibility introduced. - Lots of code refactoring done. - Numerous little adjustments and fixes made. 0.8.6 - Find-as-you-type added. - Help system added. - print_mapped_function added. - User-definable status line variables added. - :after_open and :after_buffer_switch hooks added. - Sample script for git branch status variable added. - comment_out and uncomment functions added. - comment_string and comment_close_string settings added. - Added -m (--open-matching) command line argument. - wrap_paragraph function and wrap_margin setting added for hard wrapping text. - columnize function and column_delimiter setting added. - Numerous small fixes, adjustments and refactorings. 0.8.5 - Added 256 colour support. - Added support for opening files with "filepath:linenumber" syntax. - Added ability to put %_ in a code closer as the place to position the cursor. - Code closers can now contain newlines. - Now closer text is parsed-indented by default. - Added copy_selection_to_klipper. - Added cut_selection_to_klipper. - Added paste_from_klipper. - Added delete_and_store_line_to_klipper. - Added delete_to_EOL_to_klipper. - Added delete_line_to_klipper. - Added support for regexp match placeholders (\1, \2, etc.) in findAndReplace. - Added $k shell command variable for klipper contents. - Added eol_behaviour setting. - Various minor bug fixes. - Changed to MIT licence. 0.8.4 - Added joinLines function. - Added "yes and (s)top" as a find-and-replace option. - Added '-h' to be synonymous with '--help'. - Added "Ctrl-Q to quit" to opening message. - Added close_code feature. - Added list selection. - Added buffer selection. - Added delete_newline_on_delete_to_eol option. - Added select_block command. - Slight (8%) display performance improvement. - Moved source code from svn to github.com. 0.8.3 - Extended ASCII characters (128 to 254) are now typeable. - Added elsif as a Ruby unindenter. - Significant internal refactoring. - First working rubygem. - Added HAML syntax highlighting. - Configuration can now be downloaded from the Internet if missing. - Updated README and changed setup.rb installation method. 0.8.2 - Added ability to use ';' in keychains. - Added the printKeychain command. - Augmented default conf to include some KDE 3.5 konsole keychains for common keys. - Added use_magic_file setting; default to off. - Added a clipboard/selected diff keybinding. 0.8.1 - Added choice prompt iteration. - Added a cursor stack for jumping back and forth between recently visited locations in the buffer. - Introduced cursorReturn command (to move through the cursor stack). - replaceAll now sets modified flag. - Speed of many multi-line operations improved. - Fixed parsedIndent logic in cases of adjacent indenter and unindenter. - goToLine command now supports a column argument. - goToLine command's line and column argument are now both optional. - goToLine also takes a +/- number of lines argument. - Added case sensitivity parameter to find command; defaults to case-insensitive. - Added operateOnString, operateOnLines, operateOnEachLine. 0.8.0 - Changed seek behaviour to use regexp group indexes. - Changed "word seek" in configuration file to seek both word beginnings and word endings. - Added settings interaction.blink_string, interaction.blink_duration, interaction.choice_delay. - Choice prompt no longer coerces invalid choices. - Choice prompt now requires a valid choice if no default given. - Default choice removed from critical choices. - Critical choices now ignore user input for interaction.choice_delay seconds. - Added hooks. - Added toggleSelection command. - Added lang.*.indent.using_tabs. - Fixed some indentation and tab-related bugs. - Added YAML syntax highlighting. - Refactored lots of code and began using unit tests. - Minor default conf additions and modifications. - Added fstab definitions to default conf. - Diff now shown before revert prompt. - Bang line must start with #! to be considered as a bang line (re: bangmasks). - Added a collapseWhitespace command. 0.7.9 - Changed seek behaviour to not remember last position, but use current cursor position instead. - File is now checked for external modifications, prompting for load. - Added -e, --execute option which eval's Ruby code (including Diakonos commands) after startup. - Paging up and down now respects the y cursor margin. - Paging up and down now keeps cursor at same screen coordinates. - Settings can now be altered for the duration of the editing session. (new commands: changeSessionSetting, toggleSessionSetting) 0.7.8 - Included package.rb and setup.rb for installation. - Now looks for conf in more directories. - Updated README. - Added pasteShellResult function. - Added $c shell variable: file containing clipboard contents. - Added $s shell variable: file containing selected text. - Fixed buffer switching to use a proper stack. - Added input line history. - Added Ctrl-K to clear input line. 0.7.7 - Fixed various find-related bugs. - Added the command deleteAndStoreLine, which accumulates cut lines into the same clipboard clip. 0.7.6 - Added some crontab highlighting to the default configuration file. - Added "delete character" functionality to input line. - Fixed backspace functionality of input line. 0.7.5 - Fixed bug which stopped Diakonos from completing refresh operations when the context line is disabled. - Added execute command, which executes a command in a subshell, but only displays the return code (ignores stdout). - Added a $F parameter for shell and execute commands. Space-separated list of all current buffer filenames. - Added a $i parameter for shell and execute commands. Substitute a string obtained from user. - /usr/share/diakonos is now checked for a config file, if /usr/local/share/diakonos is not found. - findAgain command now also retains memory across buffers, if needed. 0.7.4 - Prevent attempts to open non-files. - Fixed saveFileAs bug which saved the wrong file when tab-completion was used in the filename prompt. - Fixed bug in tab completion: Directories are now completed properly and their contents are listed. 0.7.3 - Fixed function-argument duplication bug which occurs after Help is consulted. - Updated default conf file to include CSS and modifications to "conf" format and the ruby format. - Added display debug logging. - Fixed off-screen drawing bug. - Fixed on-startup drawing bug. - Minor conf file additions and changes, including PHP and PL/pgSQL support. 0.7.2 - Fixed a drawing bug to do with long lines and screens wider than 80 columns. - Added support for specifying any numeric keycode as a keystroke. - Added a suspend command, to suspend the Diakonos process/job to background and return to the shell. - Altered drawing code a bit re: the shell and suspend commands. - Fixed "view.jump.* 0" bug. - Fixed copy/cut bug for selections starting or ending in columns besides the left-most column. 0.7.1 - The openFile command now uses /usr/bin/file (if available) to check if the file is readable (text), prompting to confirm open if it isn't. - Fixed popTag bug where popping from an empty stack caused an exception. - The seek command now no longer (incorrectly) cancels text selection. - Drawing bugs fixed (to do with illegal off-screen drawing). - Added the ability to use \n in searches, to match across lines. 0.7.0 - Adjusted buffer management system so that, internally, absolute file paths are used. - Added limited (line-number-based) ctags support. Commands: goToTag, goToTagUnderCursor, popTag. - Fixed revert command bug. - Added an evaluate command, which lets you run any Diakonos command. - Fixed display bug where Diakonos errors (Ruby exceptions) would ruin the curses display. - Malformed regular expressions given for regexp searching are now searched for as literal text, instead of just throwing an error. - Keychains that have no assignment are now shown in full on the interaction line. - Error message for some caught exceptions now includes a listing of probable causes. 0.6.13 - Fixed the bug where searching backwards from the start of a line will cause the search to start from the end of the line, instead of from the end of the next line up. - Added a "seek" command, which is a sort of silent find. Used for implementing features like go to next word and previous word. - Adjusted default conf file to include alternate ANSI sequences for function keys. - Context line truncation now omits the more proximate code, not the less proximate code. diakonos-0.9.0/LICENCE000066400000000000000000000020571161735554400143330ustar00rootroot00000000000000The MIT Licence Copyright (c) 2004-2011 Pistos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.diakonos-0.9.0/LICENSE000077700000000000000000000000001161735554400153272LICENCEustar00rootroot00000000000000diakonos-0.9.0/README.rdoc000066400000000000000000000035071161735554400151550ustar00rootroot00000000000000= Diakonos == REQUIREMENTS - Ruby 1.9.2+ Diakonos is built to run on Linux, but may run under other flavours of UNIX. It is known NOT to work under Windows (unless using Cygwin). == DOWNLOAD The latest stable tarballs can be acquired from http://diakonos.pist0s.ca/ The latest development code can be obtained from github: git clone git://github.com/Pistos/diakonos.git == INSTALLATION ruby install.rb --help ruby install.rb [installation parameters] You may need root privileges on the system in order to install to system-wide places like /usr . However, Diakonos runs perfectly well in userspace, such as under ~/usr . === RVM If you use RVM[1], note that Diakonos installs very easily into an RVM-based Ruby. After installing Diakonos under RVM, you can symlink to the installed binary, and that will allow you to use Diakonos with that specific Ruby version no matter what the current RVM Ruby is. Example: mkdir -p ~/bin cd ~/bin ln -s /home/pistos/.rvm/rubies/ruby-1.9.2-p180/bin/diakonos Then ensure that ~/bin is in your PATH. [1]: http://rvm.beginrescueend.com/ == UNINSTALLATION diakonos --uninstall == USAGE Run with any of these: diakonos [filename...] diakonos -m or, for other options and arguments, diakonos --help For help using Diakonos, simply press F1 or Shift-F1 from within the editor to use the interactive help system. ---------------------------------------------------------------- The source code repository is at http://github.com/Pistos/diakonos . Send comments, feedback and tech support requests to the #mathetes channel on the FreeNode IRC network ( http://webchat.freenode.net/?channels=mathetes ), or the mailing list diakonos@librelist.com . Reproducible issues may be reported at https://github.com/Pistos/diakonos/issues . Pistos http://diakonos.pist0s.ca/ diakonos-0.9.0/Rakefile000066400000000000000000000011201161735554400150010ustar00rootroot00000000000000require 'rake' require 'rake/testtask' task :default => [ :test ] task :spec => [ :test ] desc "Run Diakonos tests" task :test do system 'bacon -Ilib spec/*.rb spec/*/*.rb' end begin require 'yard' YARD::Rake::YardocTask.new( :docs ) do |t| end rescue LoadError desc "Generate source code documentation with YARD" task :docs do $stderr.puts "('gem install yard' in order to be able to generate Diakonos source code documentation.)" end end desc "Clean directory of gems and tarballs" task :clean do system 'rm diakonos-*.*.*.tar.*' system 'rm diakonos-*.*.*.gem' enddiakonos-0.9.0/_diakonos_bash_completion000066400000000000000000000007001161735554400204560ustar00rootroot00000000000000_diakonos() { local cur prev opts base COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" opts="-s" case "${prev}" in -s) local sessions=$(ls "${HOME}/.diakonos/sessions") COMPREPLY=( $(compgen -W "${sessions}" -- ${cur}) ) return 0 ;; *) ;; esac COMPREPLY=($(compgen -f -- ${cur})) return 0 } complete -F _diakonos diakonosdiakonos-0.9.0/_diakonos_zsh_completion000066400000000000000000000003641161735554400203530ustar00rootroot00000000000000#compdef diakonos typeset -A opt_args local context state line local sessiondir sessiondir="${HOME}/.diakonos/sessions" _arguments -n -s -S \ "-s[specify session]:session:_files -W $sessiondir" \ "*:file:_files" \ && return 0 return 1 diakonos-0.9.0/ansi-terminalcolours.txt000066400000000000000000000116121161735554400202560ustar00rootroot00000000000000 0 1 2 3 4 5 6 7  8 9 10 11 12 13 14 15  16 17 18 19 20 21  22 23 24 25 26 27  28 29 30 31 32 33  34 35 36 37 38 39  40 41 42 43 44 45  46 47 48 49 50 51  52 53 54 55 56 57  58 59 60 61 62 63  64 65 66 67 68 69  70 71 72 73 74 75  76 77 78 79 80 81  82 83 84 85 86 87  88 89 90 91 92 93  94 95 96 97 98 99  100 101 102 103 104 105  106 107 108 109 110 111  112 113 114 115 116 117  118 119 120 121 122 123  124 125 126 127 128 129  130 131 132 133 134 135  136 137 138 139 140 141  142 143 144 145 146 147  148 149 150 151 152 153  154 155 156 157 158 159  160 161 162 163 164 165  166 167 168 169 170 171  172 173 174 175 176 177  178 179 180 181 182 183  184 185 186 187 188 189  190 191 192 193 194 195  196 197 198 199 200 201  202 203 204 205 206 207  208 209 210 211 212 213  214 215 216 217 218 219  220 221 222 223 224 225  226 227 228 229 230 231  232 233 234 235 236 237  238 239 240 241 242 243  244 245 246 247 248 249  250 251 252 253 254 255 diakonos-0.9.0/bin/000077500000000000000000000000001161735554400141125ustar00rootroot00000000000000diakonos-0.9.0/bin/diakonos000077500000000000000000000001441161735554400156460ustar00rootroot00000000000000#!/usr/bin/env ruby require 'diakonos' $diakonos = Diakonos::Diakonos.new( ARGV ) $diakonos.start diakonos-0.9.0/diakonos000077700000000000000000000000001161735554400173712bin/diakonosustar00rootroot00000000000000diakonos-0.9.0/diakonos-256-colour.conf000066400000000000000000000211341161735554400176340ustar00rootroot00000000000000colour 32 253 39 # selection; light grey on light blue colour 33 255 69 # comments; white on blue colour 34 45 black # Ruby symbols; light blue on black colour 35 123 black # Ruby instance variables; light blue on black colour 36 177 54 # regular expressions; purple on dark purple colour 37 111 17 # single-quoted strings; light blue on dark blue colour 38 117 18 # double-quoted strings; light blue on dark blue colour 39 213 90 # shell-quoted strings; light purple on purple colour 40 15 234 # constants; white on light black colour 44 224 88 # Ruby modifiers; light red on dark red colour 41 15 233 # XML nodes; white on light black colour 42 45 233 # XML attributes; light blue on black colour 43 123 233 # XML namespaces; light blue on black colour 45 white 52 # 80-char column marker white on very dark red colour 46 236 0 # lowlight very dark grey on black view.column_markers.margin.format 45 view.non_search_area.format 46 # Shared lang.shared.format.default white bold lang.shared.format.selection 32 lang.shared.format.found yellow inverse lang.shared.tokens.reserved_words.format white lang.shared.tokens.constants.format 40 lang.shared.tokens.comments.format 33 lang.shared.tokens.non_alphanum.format white lang.shared.tokens.regular_expressions.format 36 lang.shared.tokens.singlequoted_strings.format 37 lang.shared.tokens.doublequoted_strings.format 38 lang.shared.tokens.backquoted_strings.format 39 # Diakonos help files lang.dhf.format.default white lang.dhf.format.selection inverse lang.dhf.format.found = lang.shared.format.found lang.dhf.tokens.tags.format blue lang.dhf.tokens.title.format 33 # Ruby lang.ruby.format.default = lang.shared.format.default lang.ruby.format.selection = lang.shared.format.selection lang.ruby.format.found = lang.shared.format.found lang.ruby.tokens.reserved_words.format = lang.shared.tokens.reserved_words.format lang.ruby.tokens.constants.format = lang.shared.tokens.constants.format lang.ruby.tokens.comments.format = lang.shared.tokens.comments.format lang.ruby.tokens.non_alphanum.format = lang.shared.tokens.non_alphanum.format lang.ruby.tokens.regular_expressions.format = lang.shared.tokens.regular_expressions.format lang.ruby.tokens.singlequoted_strings.format = lang.shared.tokens.singlequoted_strings.format lang.ruby.tokens.doublequoted_strings.format = lang.shared.tokens.doublequoted_strings.format lang.ruby.tokens.backquoted_strings.format = lang.shared.tokens.backquoted_strings.format lang.ruby.tokens.modifiers.format 44 lang.ruby.tokens.symbols.format 34 lang.ruby.tokens.hash_keys.format 34 lang.ruby.tokens.instance_variables.format 35 lang.ruby.tokens.regular_expressions2.format 36 lang.ruby.tokens.interpolated_string.format 38 lang.interpolated_ruby.format.default 38 lang.interpolated_ruby.tokens.interpolation.format 12 bold lang.ruby.tokens.interpolated_exec_string.format 39 lang.interpolated_exec_ruby.format.default 39 lang.interpolated_exec_ruby.tokens.interpolation.format 9 bold lang.ruby.tokens.character_codes.format magenta bold lang.ruby.tokens.long_comments.format 8 bold lang.ruby.tokens.sql_string.format 1 # Perl lang.perl.format.default = lang.shared.format.default lang.perl.format.selection = lang.shared.format.selection lang.perl.format.found = lang.shared.format.found lang.perl.tokens.reserved_words.format = lang.shared.tokens.reserved_words.format lang.perl.tokens.constants.format = lang.shared.tokens.constants.format lang.perl.tokens.comments.format = lang.shared.tokens.comments.format lang.perl.tokens.non_alphanum.format = lang.shared.tokens.non_alphanum.format lang.perl.tokens.regular_expressions.format = lang.shared.tokens.regular_expressions.format lang.perl.tokens.singlequoted_strings.format = lang.shared.tokens.singlequoted_strings.format lang.perl.tokens.doublequoted_strings.format = lang.shared.tokens.doublequoted_strings.format lang.perl.tokens.backquoted_strings.format = lang.shared.tokens.backquoted_strings.format lang.perl.tokens.builtins.format cyan bold lang.perl.tokens.array_variables.format red bold lang.perl.tokens.hash_variables.format magenta bold # Java lang.java.format.default = lang.shared.format.default lang.java.format.selection = lang.shared.format.selection lang.java.format.found = lang.shared.format.found lang.java.tokens.singlequoted_strings.format = lang.shared.tokens.singlequoted_strings.format lang.java.tokens.doublequoted_strings.format = lang.shared.tokens.doublequoted_strings.format lang.java.tokens.reserved_words.format white lang.java.tokens.constants.format = lang.shared.tokens.constants.format lang.java.tokens.comments.format = lang.shared.tokens.comments.format lang.java.tokens.long_comments.format = lang.shared.tokens.comments.format lang.java.tokens.non_alphanum.format = lang.shared.tokens.non_alphanum.format lang.java.tokens.regular_expressions.format = lang.shared.tokens.regular_expressions.format # XML lang.xml.format.default white lang.xml.format.selection = lang.shared.format.selection lang.xml.format.found = lang.shared.format.found lang.xml.tokens.entities.format magenta bold lang.xml.tokens.code.format white bold lang.xml.tokens.comments.format = lang.shared.tokens.comments.format lang.xml.tokens.template.format brown lang.xml_tag.format.default 41 lang.xml_tag.format.selection 32 lang.xml_tag.format.found yellow inverse lang.xml_tag.tokens.doublequoted_strings.format = lang.shared.tokens.doublequoted_strings.format lang.xml_tag.tokens.singlequoted_strings.format = lang.shared.tokens.doublequoted_strings.format lang.xml_tag.tokens.non_alphanum.format = lang.shared_tag.tokens.non_alphanum.format lang.xml_tag.tokens.namespaces.format 43 lang.xml_comment.format.default = lang.shared.tokens.comments.format lang.xml_comment.format.selection = lang.shared.format.selection lang.xml_comment.format.found = lang.shared.format.found lang.xml_tag.tokens.attributes ([a-zA-Z_-]+?)= lang.xml_tag.tokens.attributes.format 42 # HTML lang.html.tokens.comments.format = lang.shared.tokens.comments.format lang.html_comment.format.default = lang.shared.tokens.comments.format lang.html_tag.format.default 41 lang.html_tag.format.selection 32 lang.html_tag.tokens.attributes.format 42 lang.html_tag.tokens.doublequoted_strings.format = lang.shared.tokens.doublequoted_strings.format lang.html_tag.tokens.singlequoted_strings.format = lang.shared.tokens.doublequoted_strings.format # Haskell lang.haskell.format.default = lang.shared.format.default lang.haskell.format.selection = lang.shared.format.selection lang.haskell.format.found = lang.shared.format.found lang.haskell.tokens.comments.format = lang.shared.tokens.comments.format lang.haskell.tokens.doublequoted_strings.format = lang.shared.tokens.doublequoted_strings.format lang.haskell.tokens.singlequoted_strings.format = lang.shared.tokens.singlequoted_strings.format lang.haskell.tokens.non_alphanum.format = lang.shared_tag.tokens.non_alphanum.format # PHP lang.php.format.default = lang.shared.format.default lang.php.format.selection = lang.shared.format.selection lang.php.format.found = lang.shared.format.found lang.php.tokens.singlequoted_strings.format = lang.shared.tokens.singlequoted_strings.format lang.php.tokens.doublequoted_strings.format = lang.shared.tokens.doublequoted_strings.format lang.php.tokens.reserved_words.format = lang.shared.tokens.reserved_words.format lang.php.tokens.constants.format = lang.shared.tokens.constants.format lang.php.tokens.comments.format = lang.shared.tokens.comments.format lang.php.tokens.comments.format = lang.shared.tokens.comments.format lang.php.tokens.long_comments.format = lang.shared.tokens.comments.format lang.php.tokens.non_alphanum.format = lang.shared.tokens.non_alphanum.format # Lua lang.lua.format.default = lang.shared.format.default lang.lua.format.selection = lang.shared.format.selection lang.lua.format.found = lang.shared.format.found lang.lua.tokens.reserved_words.format = lang.shared.tokens.reserved_words.format lang.lua.tokens.comments.format = lang.shared.tokens.comments.format lang.lua.tokens.singlequoted_strings.format lang.shared.tokens.singlequoted_strings.format lang.lua.tokens.doublequoted_strings.format lang.shared.tokens.doublequoted_strings.format lang.lua.tokens.non_alphanum.format = lang.shared.tokens.non_alphanum.format # SQL lang.sql.tokens.reserved_words.format lang.shared.tokens.reserved_words.format lang.sql.tokens.comments.format = lang.shared.tokens.comments.format lang.sql.tokens.singlequoted_strings.format = lang.shared.tokens.singlequoted_strings.format lang.sql.tokens.non_alphanum.format = lang.shared.tokens.non_alphanum.format diakonos-0.9.0/diakonos.conf000066400000000000000000002077021161735554400160300ustar00rootroot00000000000000#suppress_welcome true logfile ~/.diakonos/diakonos.log #session.default_session default-session # --------------------------------------------------------------------- # Colour Definitions # # colour # # For a list of colour names, see the list of format codes in the # Language Definitions section, below. # # With this colour command you can set a different background colour than the # terminal default. # # color is a synonym for colour. colour 8 white blue colour 9 white red colour 10 white magenta colour 11 yellow blue colour 12 white green colour 13 white brown colour 14 black cyan colour 15 yellow red # When the cursor is view.margin.y lines or less from the top or # bottom line, repeatedly scroll the screen view.jump.y lines until # the cursor is more than view.margin.y lines from the top and # bottom line. # Similarly for view.margin.x and view.jump.x, with respect to the # left-most and right-most screen columns. view.margin.x 10 view.margin.y 5 view.jump.x 10 view.jump.y 5 view.scroll_amount 1 view.lookback 200 view.nonfilelines.visible false view.nonfilelines.character ~ view.wrap.visual true view.pairs.highlight true view.line_numbers false view.line_numbers.width 4 # view.line_numbers.number_format is a "printf" style format string view.line_numbers.number_format "%3s " view.line_numbers.format white #view.column_markers.margin.column 80 view.column_markers.margin.format 9 view.non_search_area.format black # bol_behaviour: This specifies where the cursor should go when the # beginning-of-line key (the default is the Home key) is pressed. # zero: Always move to the left-most column of the line # first-char: Always move to the left-most non-whitespace character # alternating-zero: As with 'zero', unless the cursor is # already there, in which case, as with 'first-char'. # alternating-first-char: As with 'first-char', unless the cursor is # already there, in which case, as with 'zero'. # bol_behavior is a synonym for bol_behaviour. bol_behaviour alternating-first-char # eol_behaviour: This specifies where the cursor should go when the # end-of-line key (the default is the End key) is pressed. # end: Always move to the right-most column of the line # last-char: Always move to the right-most non-whitespace character # alternating-end: As with 'end', unless the cursor is # already there, in which case, as with 'last-char'. # alternating-last-char: As with 'last-char', unless the cursor is # already there, in which case, as with 'end'. # eol_behavior is a synonym for eol_behaviour. eol_behaviour alternating-end delete_newline_on_delete_to_eol false # Specifies whether the cursor should be at the end (false) of found text, or the # beginning (true). found_cursor_start false find.return_on_abort false find.show_context_after true grep.context 0 max_clips 30 # If you are using KDE, you can uncomment this line to make Diakonos use KDE's # klipper instead of its own internal clipboard. Use klipper-dcop for KDE 3, # klipper-dbus for KDE 4. #clipboard.external klipper-dcop #clipboard.external klipper-dbus # Non-KDE users can try xclip (separate, third-party software package) #clipboard.external xclip # The maximum number of undo lines held in memory per file # Smaller files will be able to have more undo levels. max_undo_lines 16384 convert_tabs false strip_trailing_whitespace_on_save true # Ensures saved files end with a newline character by adding it if necessary: eof_newline false diff_command diff -U 5 # Whether or not to use /usr/bin/file to determine whether files are readable # before opening them. use_magic_file false fuzzy_file_find true fuzzy_file_find.max_files 8192 # Fuzzy file finder ignores. Uses glob syntax, as per File.fnmatch # http://www.ruby-doc.org/core/classes/File.html#M000001 # fuzzy_file_find.ignore some/relative/path/glob* # fuzzy_file_find.ignore some/other/relative/path/glob* # By default, opened files are added to the end of the buffer list. # i.e. with 3 buffers already open, opening a file will put it into buffer number 4 # Set open_as_first_buffer to true to put the next opened file into buffer number 1. #open_as_first_buffer true # --------------------------------------------------------------------- # Status Line # Use "% syntax" as placeholders # e.g. %d for decimal integers, %s for strings status.left -- %s %s%s%s%s -- (%s) -- status.right - %s Buf %d of %d --- L%3d/%3d C%2d -- # The string to use to fill in the space between the left and right sides # of the status line. status.filler - status.modified_str (modified) status.selecting_str (selecting) status.unnamed_str (unnamed file) status.read_only_str (read-only) # status.vars: any subset of: # line row num_lines col filename modified type buffer_number num_buffers selecting selection_mode session_name read_only status.vars filename modified read_only selecting selection_mode type session_name buffer_number num_buffers row num_lines col status.format inverse # --------------------------------------------------------------------- # Context Line # The context line shows the wrapping context of the cursor, with respect to # indentation. This shows the current code block(s) that the cursor is in. context.visible false context.combined false context.max_levels 4 context.format inverse context.separator | context.separator.format red inverse #context.max_segment_width 10 # --------------------------------------------------------------------- # Interaction Line # Duration of "alert" blink (in seconds) when user has made an invalid choice interaction.blink_duration 0.05 interaction.blink_string *********************************************************** # Time to wait (in seconds) before accepting user keystrokes when prompting for # a choice which has no default interaction.choice_delay 3 # --------------------------------------------------------------------- # Key Configuration # # key [...]; [[,...]] # If no function is specified, it unmaps any previous mapping. # i.e. key [...]; # can be "keycode##" to specify specific keycodes. # e.g. key keycode8;delete # Note the lack of space after the word keycode. # To obtain the string to use for any keychain, use the printKeychain command # (default alt+k). # The shell, execute and pasteShellResult commands can take variables: # $f current buffer's filepath # $d current buffer's directory # $F all current buffer filepaths, space-separated # $i get a string from user input # $c temp file containing current clipboard text # $s temp file containing currently selected text key left;cursorLeft key right;cursorRight key up;cursorUp key down;cursorDown key home;cursorBOL key esc O H;cursorBOL key esc [ H;cursorBOL key esc [ 1 ~ cursorBOL key esc [ 7 ~ cursorBOL key end;cursorEOL key esc O F;cursorEOL key esc [ F;cursorEOL key esc [ 4 ~;cursorEOL key esc [ 8 ~;cursorEOL key pageup;pageUp key pagedown;pageDown #key ctrl+a;cursorBOL key ctrl+e;cursorEOL key alt+<;cursorBOF key esc [ 1 ; 5 H cursorBOF key esc [ 1 ^ cursor_bof key esc [ 7 ^ cursor_bof key alt+>;cursorEOF key esc [ 1 ; 5 F cursorEOF key esc [ 4 ^ cursor_eof key esc [ 8 ^ cursor_eof key alt+,;cursorTOV key alt+.;cursorBOV key ctrl+j cursor_return key ctrl+l cursor_return :forward key esc ` cursor_return :backward, DIFFERENT_FILE key esc ~ cursor_return :forward, DIFFERENT_FILE key alt+n go_to_char key esc N go_to_char :after key alt+p go_to_char_previous key esc P go_to_char_previous :after key esc up scrollUp key esc O a scrollUp key esc [ A scrollUp key esc [ 1 ; 3 A scrollUp key esc [ 1 ; 5 A scrollUp key keycode520 scrollUp key keycode521 scrollUp key esc down scrollDown key esc O b scrollDown key esc [ B scrollDown key esc [ 1 ; 3 B scrollDown key esc [ 1 ; 5 B scrollDown key keycode513 scrollDown key keycode514 scrollDown key esc right seek /(?:^|\W)(\w)|\w(\W|$)/ key esc O c seek /(?:^|\W)(\w)|\w(\W|$)/ key esc [ C seek /\w(\W|$)|(?:^|\W)(\w)/ key esc [ 1 ; 3 C seek /\w(\W|$)|(?:^|\W)(\w)/ key esc [ 1 ; 5 C seek /\w(\W|$)|(?:^|\W)(\w)/ key esc [ 1 ; ; C seek /\w(\W|$)|(?:^|\W)(\w)/ key keycode517 seek /\w(\W|$)|(?:^|\W)(\w)/ key keycode518 seek /\w(\W|$)|(?:^|\W)(\w)/ key keycode553 seek /\w(\W|$)|(?:^|\W)(\w)/ key keycode555 seek /\w(\W|$)|(?:^|\W)(\w)/ key esc left seek /\w(\W|$)|(?:^|\W)(\w)/, :up key esc O d seek /\w(\W|$)|(?:^|\W)(\w)/, :up key esc [ D seek /(?:^|\W)(\w)|\w(\W|$)/, :up key esc [ 1 ; 3 D seek /\w(\W|$)|(?:^|\W)(\w)/, :up key esc [ 1 ; 5 D seek /\w(\W|$)|(?:^|\W)(\w)/, :up key esc [ 1 ; ; D seek /\w(\W|$)|(?:^|\W)(\w)/, :up key keycode515 seek /\w(\W|$)|(?:^|\W)(\w)/, :up key keycode516 seek /\w(\W|$)|(?:^|\W)(\w)/, :up key keycode538 seek /\w(\W|$)|(?:^|\W)(\w)/, :up key keycode540 seek /\w(\W|$)|(?:^|\W)(\w)/, :up key esc [ 5 ; 5 ~ go_block_previous key esc [ 6 ; 5 ~ go_block_next key esc [ 5 ; 3 ~ go_block_outer key esc [ 6 ; 3 ~ go_block_inner key esc { go_to_pair_match key esc } go_to_pair_match key ctrl+g;goToLineAsk key alt+b alt+b;toggleBookmark key alt+b alt+n;goToNextBookmark key alt+b alt+p;goToPreviousBookmark key alt+b alt+a;addNamedBookmark key alt+b alt+r;removeNamedBookmark key alt+b alt+g;goToNamedBookmark key alt+b alt+!;addNamedBookmark 1 key alt+b alt+@;addNamedBookmark 2 key alt+b alt+#;addNamedBookmark 3 key alt+b alt+$;addNamedBookmark 4 key alt+b alt+%;addNamedBookmark 5 key alt+b alt+1;goToNamedBookmark 1 key alt+b alt+2;goToNamedBookmark 2 key alt+b alt+3;goToNamedBookmark 3 key alt+b alt+4;goToNamedBookmark 4 key alt+b alt+5;goToNamedBookmark 5 key alt+t;goToTag key alt+);goToTagUnderCursor key alt+(;popTag key backspace backspace key ctrl+h backspace key del delete #key ctrl+k deleteLine key ctrl+k delete_and_store_line key ctrl+d ctrl+d delete_and_store_line key ctrl+alt+k delete_to_eol key ctrl+d $ delete_to_eol key ctrl+d t delete_to key ctrl+d ctrl+t delete_to key ctrl+d f delete_from key ctrl+d ctrl+f delete_from key ctrl+d i delete_to_and_from key ctrl+d I delete_to_and_from :inclusive key ctrl+d ctrl+i delete_to_and_from key esc del collapse_whitespace key esc [ 3 ; ; ~ collapse_whitespace key esc [ 3 ; 3 ~ collapse_whitespace key alt+w wrap_paragraph key alt+a columnize key enter carriageReturn key tab parsedIndent #key tab indent #key ctrl+alt+l unindent key alt+i indent key esc i indent key esc I unindent key esc [ Z unindent key keycode353 unindent #key tab insertSpaces 4 #key tab insertTab key ctrl+t insertTab key alt+j join_lines key esc J join_lines_upward key f1 help key esc O P help key esc [ 1 1 ~ help key esc [ [ A help key f13 help key esc O 2 P help key esc O 1 ; 2 P help key f11 about key esc [ 2 3 ~ about key f12 openFile "~/.diakonos/diakonos.conf" key esc [ 2 4 ~ openFile "~/.diakonos/diakonos.conf" # Option-F12 in OSX key f17 openFile "~/.diakonos/diakonos.conf" key ctrl+alt+r redraw key esc C toggleSessionSetting 'context.visible', DO_REDRAW key ctrl+alt+d toggleSessionSetting 'display' key esc W toggleSessionSetting 'view.wrap.visual', DO_REDRAW key esc L toggleSessionSetting 'view.line_numbers', DO_REDRAW key ctrl+n new_file key ctrl+o open_file_ask key alt+o open_matching_files key ctrl+s save_file key esc S save_file_as key ctrl+w close_buffer key ctrl+alt+o revert key alt+! setReadOnly key ctrl+q quit key esc T setBufferType key esc s esc n name_session key esc s n name_session key esc s esc l load_session key esc s l load_session key esc s esc d set_session_dir key esc s d set_session_dir key alt+1;switchToBufferNumber 1 key alt+2;switchToBufferNumber 2 key alt+3;switchToBufferNumber 3 key alt+4;switchToBufferNumber 4 key alt+5;switchToBufferNumber 5 key alt+6;switchToBufferNumber 6 key alt+7;switchToBufferNumber 7 key alt+8;switchToBufferNumber 8 key alt+9;switchToBufferNumber 9 # key alt+0;switchToBufferNumber 10 key alt+0 alt+0 switch_to_buffer_number 10 key alt+0 alt+1 switch_to_buffer_number 11 key alt+0 alt+2 switch_to_buffer_number 12 key alt+0 alt+3 switch_to_buffer_number 13 key alt+0 alt+4 switch_to_buffer_number 14 key alt+0 alt+5 switch_to_buffer_number 15 key alt+0 alt+6 switch_to_buffer_number 16 key alt+0 alt+7 switch_to_buffer_number 17 key alt+0 alt+8 switch_to_buffer_number 18 key alt+0 alt+9 switch_to_buffer_number 19 key alt+0 0 switch_to_buffer_number 10 key alt+0 1 switch_to_buffer_number 11 key alt+0 2 switch_to_buffer_number 12 key alt+0 3 switch_to_buffer_number 13 key alt+0 4 switch_to_buffer_number 14 key alt+0 5 switch_to_buffer_number 15 key alt+0 6 switch_to_buffer_number 16 key alt+0 7 switch_to_buffer_number 17 key alt+0 8 switch_to_buffer_number 18 key alt+0 9 switch_to_buffer_number 19 key alt+- switchToPreviousBuffer key alt+= switchToNextBuffer key ctrl+alt+b list_buffers key ctrl+b 1 renumber_buffer 1 key ctrl+b 2 renumber_buffer 2 key ctrl+b 3 renumber_buffer 3 key ctrl+b 4 renumber_buffer 4 key ctrl+b 5 renumber_buffer 5 key ctrl+b 6 renumber_buffer 6 key ctrl+b 7 renumber_buffer 7 key ctrl+b 8 renumber_buffer 8 key ctrl+b 9 renumber_buffer 9 key ctrl+b 0 renumber_buffer 10 #key ctrl+space toggleSelection key ctrl+space anchor_selection key ctrl+c copySelection key esc [ 2 ; 5 ~ copySelection key ctrl+x cutSelection key keycode383 cutSelection key alt+u removeSelection key ctrl+a select_all key esc M b selection_mode_block key esc M alt+b selection_mode_block key esc M esc B selection_mode_block key esc M n selection_mode_normal key esc M alt+n selection_mode_normal key esc M esc N selection_mode_normal key esc ctrl+space select_line key esc space select_wrapping_block key.after anchor_selection ctrl+space select_word key.after select_word ctrl+space select_word_another key.after select_word_another ctrl+space select_word_another # Select file diff in a patch key ctrl+alt+d f select_block /^Index: /, /^(Index: |$)/, false # Select a diff hunk in a patch key ctrl+alt+d h select_block /^@@ /, /^(@@ |$)/, false key esc # comment_out key esc @ uncomment key ctrl+alt+v;showClips key ctrl+v;paste key ctrl+y;unundo key ctrl+z;undo #key ctrl+z;suspend key suspend;undo #key suspend;suspend key ctrl+f find #key ctrl+f find case_sensitive: true key alt+f find nil, case_sensitive: true #key alt+f findExact key ctrl+alt+f find nil, word_only: true key esc F find_clip #key ctrl+alt+f find nil, direction: :up, case_sensitive: true key f3 find_again :down key esc [ [ C find_again :down key esc O R find_again :down key esc [ 1 3 ~ find_again :down key f15 find_again :up key esc [ 2 8 ~ find_again :up key esc O 2 R find_again :up key esc [ 2 5 ~ find_again :up key ctrl+r searchAndReplace key alt+r searchAndReplace CASE_SENSITIVE key ctrl+alt+u clearMatches key esc g grep key esc G grep_buffers key ctrl+alt+g grep_dir key alt+c close_code key alt+e complete_word key esc E complete_word :up key f2 shell key esc O Q shell key esc [ 1 2 ~ shell key esc [ [ B shell key f8;execute key esc d shell "diff -U 5 -w -b $c $s", "clipboard.diff" #key esc F;shell "grep -n '$i' $F" #key esc F;execute "grep -n '$i' $F | less" #key esc l execute "aspell check $f" key f14 evaluate key esc O 2 Q evaluate key esc [ 2 6 ~ evaluate key esc [ 1 ; 2 evaluate key ctrl+alt+c shell "ruby -c $f" #key f10 spawn "firefox --display=:0 http://apidock.com/ruby/$i" #key f10 spawn "DISPLAY=:0 opera --remote 'openURL(http://www.ruby-doc.org/core-1.9/classes/$i.html,new-page)' 2>&1 > /dev/null" # To use the following: # 1) Copy to the clipboard some Ruby code which operates on stdin text and outputs to stdout. # 2) Select (highlight) some text to operate on. # 3) Activate this pasteShellResult command. # 4) The selected text should now be replaced with the script's results. key ctrl+alt+p;pasteShellResult "cat $s | ruby $c" #key ctrl+alt+p;pasteShellResult "cat $s | perl $c" #key ctrl+alt+p;pasteShellResult "cat $s | python $c" #key ctrl+alt+p;pasteShellResult "cat $s | sed -f $c" #key ctrl+alt+p;pasteShellResult "cat $s | awk -f $c" key alt+k printKeychain key esc K print_mapped_function key alt+m toggleMacroRecording key f4 playMacro key esc O S playMacro key esc [ 1 4 ~ playMacro key esc [ [ D playMacro key f5 loadScript key esc [ 1 5 ~ loadScript key esc [ [ E loadScript key f6 repeatLast key esc [ 1 7 ~ repeatLast key f7 operate_on_each_line key f19 operate_on_string key esc [ 1 8 ; 2 ~ operate_on_string key esc f7 operate_on_lines key esc [ 1 8 ; 3 ~ operate_on_lines key esc [ 1 8 ; ; ~ operate_on_lines key keycode319 operate_on_lines # Emacs-like keychains #key ctrl+s;find #key ctrl+x ctrl+c;quit #key ctrl+x ctrl+f;openFileAsk #key ctrl+x ctrl+s;saveFile # ------ mkey input left readline_cursor_left mkey input esc [ D readline_cursor_left mkey input right readline_cursor_right mkey input esc [ C readline_cursor_right mkey input esc esc readline_abort mkey input ctrl+q readline_abort mkey input ctrl+c readline_abort mkey input enter readline_accept mkey input backspace readline_backspace mkey input ctrl+h readline_backspace mkey input tab readline_complete_input mkey input del readline_delete mkey input ctrl+k readline_delete_line mkey input ctrl+w readline_delete_word mkey input up readline_cursor_up mkey input esc [ A readline_cursor_up mkey input down readline_cursor_down mkey input esc [ B readline_cursor_down mkey input home readline_cursor_bol mkey input esc O H readline_cursor_bol mkey input esc [ H readline_cursor_bol mkey input esc [ 1 ~ readline_cursor_bol mkey input esc [ 7 ~ readline_cursor_bol mkey input ctrl+a readline_cursor_bol mkey input end readline_cursor_eol mkey input esc O F readline_cursor_eol mkey input esc [ F readline_cursor_eol mkey input esc [ 4 ~ readline_cursor_eol mkey input esc [ 8 ~ readline_cursor_eol mkey input ctrl+e readline_cursor_eol mkey input pagedown readline_page_down mkey input pageup readline_page_up mkey input f5 readline_grep_context_decrease mkey input esc [ 1 5 ~ readline_grep_context_decrease mkey input esc [ [ E readline_grep_context_decrease mkey input f6 readline_grep_context_increase mkey input esc [ 1 7 ~ readline_grep_context_increase mkey input f3 find_again :down mkey input esc [ [ C find_again :down mkey input esc O R find_again :down mkey input esc [ 1 3 ~ find_again :down mkey input f15 find_again :up mkey input esc [ 2 8 ~ find_again :up mkey input esc O 2 R find_again :up # --------------------------------------------------------------------- # Language Definitions # For syntax highlighting and indentation. # lang..tokens.[.case_insensitive] # lang..tokens..format # can be any subset of: # normal black red green brown blue magenta cyan white standout underline inverse blink dim bold # The numbers of colour pairs (as defined by the configuration command "colour") # can also be used as format codes. # # indent.roundup: If a line's indentation is not evenly divisible by the # indent.size, and indent.roundup is true, then the non-integer indentation # level will be rounded up. If indent.roundup is false, then it will be # rounded down. # e.g. given an indent.size of 4, and a line with 6 spaces, indent.roundup # true will make Diakonos consider the line indented 2 levels. With # indent.roundup false, it will be considered indented 1 level. # # The filemask can also be used to specify specific filenames which # don't conform to the standard extensions for a language. # Used no matter what language lang.all.tokens.conflict_ours ^<<<<<<<.* lang.all.tokens.conflict_ours.format 15 bold lang.all.tokens.conflict_theirs ^>>>>>>>.* lang.all.tokens.conflict_theirs.format 15 bold lang.all.tokens.conflict_separator ^=======$ lang.all.tokens.conflict_separator.format 9 bold # lang.all.tokens.trailing_whitespace (\s+$) # lang.all.tokens.trailing_whitespace.format 9 lang.all.surround.pair "(" "( " " )" lang.all.surround.pair ")" "(" ")" lang.all.surround.pair "{" "{ " " }" lang.all.surround.pair "}" "{" "}" lang.all.surround.pair "[" "[ " " ]" lang.all.surround.pair "]" "[" "]" lang.all.surround.pair "<" "< " " >" lang.all.surround.pair ">" "<" ">" lang.all.surround.pair "'" "'" "'" lang.all.surround.pair "\"" "\"" "\"" lang.all.surround.pair "/*" "/*" "*/" # Inherited by several languages lang.shared.format.default white bold lang.shared.format.selection inverse lang.shared.format.found yellow inverse lang.shared.format.pair cyan inverse lang.shared.tokens.reserved_words.format white lang.shared.tokens.constants.format yellow bold lang.shared.tokens.comments.format 8 bold lang.shared.tokens.non_alphanum.format white lang.shared.tokens.regular_expressions.format red bold lang.shared.tokens.singlequoted_strings.format green bold lang.shared.tokens.doublequoted_strings.format green bold lang.shared.tokens.backquoted_strings.format red bold # Text (default) lang.text.format.default white lang.text.format.selection inverse lang.text.format.found yellow inverse lang.text.indent.size 2 lang.text.indent.auto true lang.text.indent.roundup false #lang.text.indent.using_tabs true lang.text.tabsize 8 lang.text.wrap_margin 80 # Diakonos help files lang.dhf.filemask \.dhf lang.dhf.format.default white lang.dhf.format.selection inverse lang.dhf.format.found yellow inverse lang.dhf.tokens.tags (^Tags: .+) lang.dhf.tokens.tags.format blue lang.dhf.tokens.title (^# .*) lang.dhf.tokens.title.format 8 bold lang.dhf.tokens.subtitle (^## .*) lang.dhf.tokens.subtitle.format cyan bold lang.dhf.tokens.subsubtitle (^### .*) lang.dhf.tokens.subsubtitle.format cyan lang.dhf.tokens.keys <(.+?)> lang.dhf.tokens.keys.format white bold lang.dhf.indent.size 2 lang.dhf.indent.auto true lang.dhf.indent.roundup true lang.dhf.wrap_margin 80 # XML lang.xml.filemask \.(xml|xsd|xsl|rdl|aiml)$ lang.xml.format.default white lang.xml.format.selection inverse lang.xml.format.found yellow inverse lang.xml.tabsize 8 lang.xml.indent.size 2 lang.xml.indent.auto true lang.xml.indent.roundup true #lang.xml.indent.using_tabs true lang.xml.tokens.entities &\S+?; lang.xml.tokens.entities.format magenta bold lang.xml.tokens.comments.open () lang.xml.tokens.comments.format 8 lang.xml.tokens.comments.change_to xml_comment lang.xml.comment_string "" lang.xml.tokens.code.open (<)(?:[^%]|$) lang.xml.tokens.code.close (?:[^%]|^)(>) lang.xml.tokens.code.format white bold lang.xml.tokens.code.change_to xml_tag lang.xml.tokens.template.open \[@-- lang.xml.tokens.template.close --@\] lang.xml.tokens.template.format brown lang.xml.tokens.template.change_to perl lang.xml.closers.tag.regexp .*<([^/> ]*)(?:.+?)?> lang.xml.closers.tag.closer lang.xml_tag.format.default white bold lang.xml_tag.format.selection inverse lang.xml_tag.format.found yellow inverse lang.xml_tag.tabsize 8 lang.xml_tag.indent.size 2 lang.xml_tag.indent.auto true lang.xml_tag.indent.roundup true #lang.xml_tag.indent.using_tabs true lang.xml_tag.tokens.doublequoted_strings (\".*?[^\\]\") lang.xml_tag.tokens.doublequoted_strings.format green bold lang.xml_tag.tokens.singlequoted_strings ('.*?[^\\]') lang.xml_tag.tokens.singlequoted_strings.format green bold lang.xml_tag.tokens.non_alphanum ([@!#$%^&*()\[\]{}/?=+\-\\|,<.>;:]) lang.xml_tag.tokens.non_alphanum.format white lang.xml_tag.tokens.namespaces ([a-zA-Z_-]+): lang.xml_tag.tokens.namespaces.format yellow bold lang.xml_comment.format.default 8 lang.xml_comment.format.selection inverse lang.xml_comment.format.found yellow inverse lang.xml_comment.tabsize 8 lang.xml_comment.indent.size 2 lang.xml_comment.indent.auto true lang.xml_comment.indent.roundup true #lang.xml_comment.indent.using_tabs true lang.xml.surround.pair "" lang.xml.surround.pair "/^<(.+?)>$/" "<\1>" "" lang.html.filemask \.([rx]?html?|php|asp|erb)$ lang.html.format.default white lang.html.format.selection inverse lang.html.format.found yellow inverse lang.html.tabsize 8 lang.html.indent.size 2 lang.html.indent.auto true lang.html.indent.roundup true #lang.html.indent.using_tabs true lang.html.tokens.comments.open () lang.html.tokens.comments.format 8 lang.html.tokens.comments.change_to html_comment lang.html.comment_string "" lang.html.tokens.entities &\S+?; lang.html.tokens.entities.format magenta bold lang.html.tokens.eruby.open <% lang.html.tokens.eruby.close %> lang.html.tokens.eruby.format 9 bold lang.html.tokens.eruby.change_to ruby lang.html.tokens.ezamar.open <\?r lang.html.tokens.ezamar.close \?> lang.html.tokens.ezamar.format 9 bold lang.html.tokens.ezamar.change_to ruby lang.html.tokens.ezamar-value.open \#\{ lang.html.tokens.ezamar-value.close \} lang.html.tokens.ezamar-value.format 9 bold lang.html.tokens.ezamar-value.change_to ruby lang.html.tokens.php.open <\?(?:php)? lang.html.tokens.php.close \?> lang.html.tokens.php.format 10 bold lang.html.tokens.php.change_to php lang.html.tokens.code.open (<)(?:[^%]|$) lang.html.tokens.code.close (?:[^%]|^)(>) lang.html.tokens.code.format white bold lang.html.tokens.code.change_to html_tag lang.html.closers.tag.regexp .*<([^/> ]*)(?:.+?)?> lang.html.closers.tag.closer lang.html_tag.format.default white bold lang.html_tag.format.selection inverse lang.html_tag.format.found yellow inverse lang.html_tag.tabsize 8 lang.html_tag.indent.size 4 lang.html_tag.indent.auto true lang.html_tag.indent.roundup true #lang.html_tag.indent.using_tabs true lang.html_tag.tokens.elements.case_insensitive \b(A|ABBR|ACRONYM|ADDRES|APPLET|AREA|B|BASE|BASEFONT|BDO|BIG|BLOCKQUOTE|BODY|BR|BUTTON|CAPTION|CENTER|CITE|CODE|COL|COLGROUP|DD|DEL|DFN|DIR|DIV|DL|DT|EM|FIELDSET|FONT|FORM|FRAME|FRAMESET|H1|H2|H3|H4|H5|H6|HEAD|HR|HTML|I|IFRAME|IMG|INPUT|INS|ISINDEX|KBD|LABEL|LEGEND|LI|LINK|MAP|MENU|META|NOFRAMES|NOSCRIPT|OBJECT|OL|OPTGROUP|OPTION|P|PARAM|PRE|Q|S|SAMP|SCRIPT|SELECT|SMALL|SPAN|STRIKE|STRONG|STYLE|SUB|SUP|TABLE|TBODY|TD|TEXTAREA|TFOOT|TH|THEAD|TITLE|TR|TT|U|UL|VA)\b lang.html_tag.tokens.elements.format cyan lang.html_tag.tokens.attributes.case_insensitive \b(abbr|accept-charset|accept|accesskey|action|align|alink|alt|archive|axis|background|bgcolor|border|cellpadding|cellspacing|char|charoff|charset|checked|cite|class|classid|clear|code|codebase|codetype|color|cols|colspan|compact|content|coords|data|datetime|declare|defer|dir|disabled|enctype|face|for|frame|frameborder|headers|height|href|href|hreflang|hspace|http-equiv|id|ismap|label|lang|language|link|longdesc|marginheight|marginwidth|maxlength|media|method|multiple|name|nohref|noresize|noshade|nowrap|object|onblur|onchange|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onreset|onselect|onsubmit|onunload|profile|prompt|readonly|rel|rev|rows|rowspan|rules|scheme|scope|scrolling|selected|shape|size|span|src|standby|start|style|summary|tabindex|target|text|title|type|usemap|valign|value|valuetype|version|vlink|vspace|width)\b lang.html_tag.tokens.attributes.format white lang.html_tag.tokens.doublequoted_strings (\".*?[^\\]\") lang.html_tag.tokens.doublequoted_strings.format green bold lang.html_tag.tokens.singlequoted_strings ('.*?[^\\]') lang.html_tag.tokens.singlequoted_strings.format green bold lang.html_tag.tokens.non_alphanum ([@!#$%^&*()\[\]{}/?=+\-\\|,<.>;:]) lang.html_tag.tokens.non_alphanum.format white lang.html_comment.format.default 8 lang.html_comment.format.selection inverse lang.html_comment.format.found yellow inverse lang.html_comment.tabsize 8 lang.html_comment.indent.size 4 lang.html_comment.indent.auto true lang.html_comment.indent.roundup true #lang.html_comment.indent.using_tabs true lang.html.surround.pair "" lang.html.surround.pair "/^<(.+?)>$/" "<\1>" "" # CSS lang.css.filemask \.(?:s?css|less)$ lang.css.format.default white lang.css.format.selection inverse lang.css.format.found yellow inverse lang.css.tabsize 8 lang.css.indent.size 4 lang.css.indent.auto true lang.css.indent.roundup true #lang.css.indent.using_tabs true lang.css.indent.indenters (\{) lang.css.indent.unindenters (\}) lang.css.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(\/\/.*) lang.css.tokens.properties \b(azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-collapse|border-color|border-spacing|border-style|border-top|border-bottom|border-right|border-left|border-top-color|border-top-style|border-top-width|border-width|border|bottom|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-right|margin-top|margin-left|margin-bottom|margin|max-height|max-width|min-height|min-width|orphans|outline-color|outline-style|outline-width|outline|overflow|padding-top|padding-left|padding-right|padding-bottom|padding|page-break-after|page-break-before|page-break-inside|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|table-layout|text-align|text-decoration|text-indent|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index)\s*: lang.css.tokens.properties.format white bold lang.css.tokens.colours #[A-Fa-f0-9]{6}|\b(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow)\b lang.css.tokens.colours.format yellow bold lang.css.tokens.long_comments.open \/\* lang.css.tokens.long_comments.close \*\/ lang.css.tokens.long_comments.format = lang.shared.tokens.comments.format lang.css.comment_string "/* " lang.css.comment_close_string " */" lang.css.tokens.numbers \b([0-9]+\.[0-9]+|[0-9]+) lang.css.tokens.numbers.format blue bold lang.css.tokens.units [^A-Za-z](em|pt|px)\b lang.css.tokens.units.format cyan lang.css.tokens.html_elements.case_insensitive \b(A|ABBR|ACRONYM|ADDRES|APPLET|AREA|B|BASE|BASEFONT|BDO|BIG|BLOCKQUOTE|BODY|BR|BUTTON|CAPTION|CENTER|CITE|CODE|COL|COLGROUP|DD|DEL|DFN|DIR|DIV|DL|DT|FIELDSET|FORM|FRAME|FRAMESET|H1|H2|H3|H4|H5|H6|HEAD|HR|HTML|I|IFRAME|IMG|INPUT|INS|ISINDEX|KBD|LABEL|LEGEND|LI|LINK|MAP|MENU|META|NOFRAMES|NOSCRIPT|OBJECT|OL|OPTGROUP|OPTION|P|PARAM|PRE|Q|S|SAMP|SCRIPT|SELECT|SMALL|SPAN|STRIKE|STRONG|STYLE|SUB|SUP|TABLE|TBODY|TD|TEXTAREA|TFOOT|TH|THEAD|TITLE|TR|TT|U|UL|VA)\b lang.css.tokens.html_elements.format green lang.css.tokens.values \b(auto|block|inherit|inline|larger|none|smaller|solid)\b lang.css.tokens.values.format blue bold lang.css.column_delimiters :|, lang.css.tokens.variables @\w+ lang.css.tokens.variables.format cyan bold # Ruby lang.ruby.filemask (?:[Rr]akefile)|Gemfile|(?:\.(?:r[bu]|gem(?:spec)?|rake)$) lang.ruby.bangmask #!.*ruby lang.ruby.format.default = lang.shared.format.default lang.ruby.format.selection = lang.shared.format.selection lang.ruby.format.pair = lang.shared.format.pair lang.ruby.format.found = lang.shared.format.found lang.ruby.tokens.reserved_words \b(?:__FILE__|and|def|end|in|or|self|__LINE__|begin|defined\?|ensure|module|redo|super|until|BEGIN|break|do|false|next|rescue|then|when|END|case|else|for|nil|retry|true|while|alias|class|elsif|not|return|undef|yield)\b lang.ruby.tokens.reserved_words.format = lang.shared.tokens.reserved_words.format lang.ruby.tokens.non_modifiers ^\s*(if|unless) lang.ruby.tokens.non_modifiers.format white lang.ruby.tokens.modifiers \s+(if|unless) lang.ruby.tokens.modifiers.format 9 bold lang.ruby.tokens.constants \b([A-Z_]+|[A-Z_][A-Z0-9_]+)\b lang.ruby.tokens.constants.format = lang.shared.tokens.constants.format lang.ruby.tokens.namespace :: lang.ruby.tokens.namespace.format white lang.ruby.tokens.symbols (:[a-zA-Z_][a-zA-Z_0-9]*) lang.ruby.tokens.symbols.format white bold lang.ruby.tokens.hash_keys \b(\w+):\s lang.ruby.tokens.hash_keys.format white bold lang.ruby.tokens.comments (#.*) lang.ruby.tokens.comments.format = lang.shared.tokens.comments.format lang.ruby.comment_string "# " lang.ruby.tokens.long_comments.open ^=begin lang.ruby.tokens.long_comments.close ^=end lang.ruby.tokens.long_comments.format = lang.shared.tokens.comments.format lang.ruby.tokens.sql_string.open (<<-EOSQL) lang.ruby.tokens.sql_string.close (EOSQL) lang.ruby.tokens.sql_string.format 1 lang.ruby.tokens.sql_string.change_to sql lang.ruby.tokens.instance_variables (@[A-Za-z_][A-Za-z_0-9]*) lang.ruby.tokens.instance_variables.format white bold lang.ruby.tokens.regular_expressions (\/.+?[^\\]\/) lang.ruby.tokens.regular_expressions.format red bold lang.ruby.tokens.regular_expressions2 (%r\{.+?[^\}]\}) lang.ruby.tokens.regular_expressions2.format red bold lang.ruby.tokens.doublequoted_strings (\".*?[^\\]\"|\"\") lang.ruby.tokens.doublequoted_strings.format green bold lang.ruby.tokens.interpolated_string.open (%Q?\{) lang.ruby.tokens.interpolated_string.close (\}) lang.ruby.tokens.interpolated_string.format green bold lang.ruby.tokens.interpolated_string.change_to interpolated_ruby lang.interpolated_ruby.format.default green bold lang.interpolated_ruby.tokens.interpolation.open (#\{) lang.interpolated_ruby.tokens.interpolation.close (\}) lang.interpolated_ruby.tokens.interpolation.format 12 bold lang.interpolated_ruby.tokens.interpolation.change_to ruby lang.ruby.tokens.singlequoted_strings ('.*?[^\\]'|'') lang.ruby.tokens.singlequoted_strings.format green bold lang.ruby.tokens.backquoted_strings (`.*?[^\\]`|``) lang.ruby.tokens.backquoted_strings.format red bold lang.ruby.tokens.interpolated_exec_string.open (%x\{) lang.ruby.tokens.interpolated_exec_string.close (\}) lang.ruby.tokens.interpolated_exec_string.format red bold lang.ruby.tokens.interpolated_exec_string.change_to interpolated_exec_ruby lang.interpolated_exec_ruby.format.default red bold lang.interpolated_exec_ruby.tokens.interpolation.open (#\{) lang.interpolated_exec_ruby.tokens.interpolation.close (\}) lang.interpolated_exec_ruby.tokens.interpolation.format 9 bold lang.interpolated_exec_ruby.tokens.interpolation.change_to ruby lang.ruby.tokens.character_codes \W(\?\S) lang.ruby.tokens.character_codes.format magenta bold lang.ruby.tokens.non_alphanum [@!#$%^&*()\[\]{}/?=+\-\\|,<.>;~] lang.ruby.tokens.non_alphanum.format white lang.ruby.indent.size 2 lang.ruby.indent.auto true lang.ruby.indent.roundup true #lang.ruby.indent.using_tabs true lang.ruby.tabsize 2 lang.ruby.indent.indenters ^\s*(case|def|begin|ensure|when|else|ensure|for|while|until|elsif|if|class|module|rescue)\b|([{\[(]$|\{\s*\|[\w\s,]*\|\s*$)|\b(do)\b lang.ruby.indent.unindenters ^\s*(end|else|elsif|ensure|when|rescue)\b|(^\s*[\]})]) lang.ruby.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(`.+?[^\\]`)|(\/.+?[^\\]\/)|(^\s*#.*)|\S\s+if lang.ruby.indent.ignore ^\s*$ lang.ruby.context.ignore ^=(begin|end)$ lang.ruby.column_delimiters =>?|:|, # PHP lang.php.filemask \.php\d?$ lang.php.bangmask #!.*php|<\?php lang.php.format.default white bold lang.php.format.selection inverse lang.php.format.found yellow inverse lang.php.tokens.doublequoted_strings (\".*?[^\\]\") lang.php.tokens.doublequoted_strings.format green bold lang.php.tokens.singlequoted_strings ('.*?[^\\]') lang.php.tokens.singlequoted_strings.format green bold lang.php.tokens.reserved_words \b(NULL|E_ALL|__wakeup|not|endwhile|__sleep|new|endswitch|__LINE__|list|endif|__FILE__|global|endforeach|while|include_once|endfor|virtual|include|enddeclare|xor|if|empty|var|elseif|TRUE|true|else|this|echo|stdClass|die|switch|do|static|default|return|function|declare|require_once|foreach|continue|require|for|class|print|FALSE|false|cfunction|PHP_VERSION|extends|case|exit|break|PHP_OS|eval|argc|parent|E_WARNING|as|or|E_ERROR|argv|old_function|E_PARSE|and)\b lang.php.tokens.reserved_words.format white lang.php.tokens.constants \b([A-Z_]+|[A-Z_][A-Z0-9_]+)\b lang.php.tokens.constants.format yellow bold lang.php.tokens.comments (\/\/.*) lang.php.tokens.comments.format = lang.shared.tokens.comments.format lang.php.comment_string "// " lang.php.tokens.long_comments.open \/\* lang.php.tokens.long_comments.close \*\/ lang.php.tokens.long_comments.format = lang.shared.tokens.comments.format lang.php.tokens.preprocessor (^\s*#.*) lang.php.tokens.preprocessor.format yellow bold lang.php.tokens.sql_string.open (<<;:]) lang.php.tokens.non_alphanum.format white lang.php.indent.size 4 lang.php.indent.auto true lang.php.indent.roundup false #lang.php.indent.using_tabs true lang.php.indent.indenters ([{\[(]$) lang.php.indent.unindenters (^\s+[\]})]) lang.php.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(\/\/.*) lang.php.indent.ignore ^(.+:|\s*?)$ lang.php.context.ignore ^(.+:|\s*\{?)$ # Perl lang.perl.filemask \.(?:pl|pm)$ lang.perl.bangmask #!.*perl lang.perl.format.default white bold lang.perl.format.selection inverse lang.perl.format.found yellow inverse lang.perl.tokens.comments (#.*) lang.perl.tokens.comments.format = lang.shared.tokens.comments.format lang.perl.comment_string "# " lang.perl.tokens.non_modifiers ^\s*(if|unless|until|while) lang.perl.tokens.non_modifiers.format white lang.perl.tokens.modifiers \s+(if|unless|until|while) lang.perl.tokens.modifiers.format 9 bold lang.perl.tokens.constants \b([A-Z_]+|[A-Z_][A-Z0-9_]+)\b lang.perl.tokens.constants.format yellow bold lang.perl.tokens.regular_expressions (\/.+?[^\\]\/) lang.perl.tokens.regular_expressions.format red bold lang.perl.tokens.doublequoted_strings (\".*?[^\\]\") lang.perl.tokens.doublequoted_strings.format green bold lang.perl.tokens.singlequoted_strings ('.*?[^\\]') lang.perl.tokens.singlequoted_strings.format green bold lang.perl.tokens.backquoted_strings (`.*?[^\\]`) lang.perl.tokens.backquoted_strings.format red bold lang.perl.tokens.reserved_words \b(else|for|foreach|return|do|next|elsif|last|redo|continue|sub|goto)\b lang.perl.tokens.reserved_words.format white lang.perl.tokens.builtins \b(abs|accept|alarm|atan2|bind|binmode|bless|caller|chdir|chmod|chomp|chop|chown|chr|chroot|close|closedir|connect|continue|cos|crypt|dbmclose|dbmopen|defined|delete|die|do|dump|each|endgrent|endhostent|endnetent|endprotoent|endpwent|endservent|eof|eval|exec|exists|exit|exp|fcntl|fileno|flock|fork|format|formline|getc|getgrent|getgrgid|getgrnam|gethostbyaddr|gethostbyname|gethostent|getlogin|getnetbyaddr|getnetbyname|getnetent|getpeername|getpgrp|getppid|getpriority|getprotobyname|getprotobynumber|getprotoent|getpwent|getpwnam|getpwuid|getservbyname|getservbyport|getservent|getsockname|getsockopt|glob|gmtime|goto|grep|hex|import|index|int|ioctl|join|keys|kill|last|lc|lcfirst|length|link|listen|local|localtime|lock|log|lstat|m|map|mkdir|msgctl|msgget|msgrcv|msgsnd|my|next|no|oct|open|opendir|ord|our|pack|package|pipe|pop|pos|print|printf|prototype|push|q|qq|qr|quotemeta|qw|qx|rand|read|readdir|readline|readlink|readpipe|recv|redo|ref|rename|require|reset|return|reverse|rewinddir|rindex|rmdir|s|scalar|seek|seekdir|select|semctl|semget|semop|send|setgrent|sethostent|setnetent|setpgrp|setpriority|setprotoent|setpwent|setservent|setsockopt|shift|shmctl|shmget|shmread|shmwrite|shutdown|sin|sleep|socket|socketpair|sort|splice|split|sprintf|sqrt|srand|stat|study|sub|substr|symlink|syscall|sysopen|sysread|sysseek|system|syswrite|tell|telldir|tie|tied|time|times|tr|truncate|uc|ucfirst|umask|undef|unlink|unpack|unshift|untie|use|utime|values|vec|wait|waitpid|wantarray|warn|write|y)\b lang.perl.tokens.builtins.format cyan bold lang.perl.tokens.array_variables \s(@[A-Za-z_][A-Za-z_0-9]*)\b lang.perl.tokens.array_variables.format red bold lang.perl.tokens.hash_variables \s(%[A-Za-z_][A-Za-z_0-9]*)\b lang.perl.tokens.hash_variables.format magenta bold lang.perl.tokens.non_alphanum [!#^&*()\[\]{}/?=+\-\\|,<.>;:~] lang.perl.tokens.non_alphanum.format white lang.perl.indent.size 4 lang.perl.indent.auto true lang.perl.indent.roundup true #lang.perl.indent.using_tabs true lang.perl.indent.indenters (case|[{\[(]$) lang.perl.indent.unindenters (case|^\s+[\]})]) #lang.perl.indent.indenters \b(unless|else|for|while|foreach|if|do|elsif|sub)\b #lang.perl.indent.unindenters \b(else)\b lang.perl.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(`.+?[^\\]`)|(\/.+?[^\\]\/)|(^\s*#.*) lang.perl.indent.ignore ^\s*$ lang.perl.context.ignore ^(.+:|\s*\{?)$ lang.perl.column_delimiters =>?|:|, # Python lang.python.filemask \.py$ lang.python.bangmask #!.*python lang.python.format.default white bold lang.python.format.selection inverse lang.python.format.found yellow inverse lang.python.tokens.constants \b([A-Z_]+|[A-Z_][A-Z0-9_]+)\b lang.python.tokens.constants.format yellow bold lang.python.tokens.comments (#.*) lang.python.tokens.comments.format = lang.shared.tokens.comments.format lang.python.comment_string "# " lang.python.tokens.doublequoted_strings (\".*?[^\\]\") lang.python.tokens.doublequoted_strings.format green bold lang.python.tokens.singlequoted_strings ('.*?[^\\]') lang.python.tokens.singlequoted_strings.format green bold lang.python.tokens.backquoted_strings (`.*?[^\\]`) lang.python.tokens.backquoted_strings.format red bold lang.python.tokens.reserved_words \b(and|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|yield)\b lang.python.tokens.reserved_words.format white lang.python.tokens.non_alphanum [@!#$%^&*()\[\]{}/?=+\-\\|,<.>;:~] lang.python.tokens.non_alphanum.format white lang.python.indent.size 4 lang.python.indent.auto true lang.python.indent.roundup true #lang.python.indent.using_tabs true lang.python.indent.indenters \b(class|def|elif|else|except|finally|for|if|try|while)\b #lang.python.indent.indenters : lang.python.indent.unindenters \b(else|elif|except)\b lang.python.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(`.+?[^\\]`)|(^\s*#.*) lang.python.indent.ignore ^\s*$ # Java lang.java.filemask \.(?:java|js)$ lang.java.format.default white bold lang.java.format.selection inverse lang.java.format.found yellow inverse lang.java.tokens.doublequoted_strings (\".*?[^\\]\") lang.java.tokens.doublequoted_strings.format green bold lang.java.tokens.singlequoted_strings ('.*?[^\\]') lang.java.tokens.singlequoted_strings.format green bold lang.java.tokens.reserved_words \b(abstract|do|if|package|synchronized|boolean|double|implements|private|this|break|else|import|protected|throw|byte|extends|instanceof|public|throws|case|false|int|return|transient|catch|final|interface|short|true|char|finally|long|static|try|class|float|native|strictfp|void|const|for|new|super|volatile|continue|goto|null|switch|while|default|assert)\b lang.java.tokens.reserved_words.format white lang.java.tokens.constants \b([A-Z_]+|[A-Z_][A-Z0-9_]+)\b lang.java.tokens.constants.format yellow bold lang.java.tokens.comments (\/\/.*) lang.java.tokens.comments.format = lang.shared.tokens.comments.format lang.java.comment_string "/* " lang.java.comment_close_string " */" lang.java.tokens.long_comments.open \/\* lang.java.tokens.long_comments.close \*\/ lang.java.tokens.long_comments.format = lang.shared.tokens.comments.format lang.java.tokens.regular_expressions (\/.+?[^\\]\/) lang.java.tokens.regular_expressions.format red bold lang.java.tokens.non_alphanum ([!@#$%\^&*()\[\]{}/?=+\-\\|,<.>;:]) lang.java.tokens.non_alphanum.format white lang.java.indent.size 4 lang.java.indent.auto true lang.java.indent.roundup false #lang.java.indent.using_tabs true lang.java.indent.indenters (\{) lang.java.indent.unindenters (\}) lang.java.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(\/\/.*) lang.java.indent.ignore ^(.+:|\s*?)$ lang.java.indent.closers true lang.java.context.ignore ^(.+:|\s*\{?)$ lang.java.closers.for.regexp for$ lang.java.closers.for.closer { |m| "( $i = 0; $i < limit; $i++ ) {\n%_\n}" } lang.java.column_delimiters =|:|, # C lang.c.filemask \.(c(pp|xx)?|h)$ lang.c.format.default white bold lang.c.format.selection inverse lang.c.format.found yellow inverse lang.c.tokens.doublequoted_strings (\".*?[^\\]\") lang.c.tokens.doublequoted_strings.format green bold lang.c.tokens.singlequoted_strings ('.*?[^\\]') lang.c.tokens.singlequoted_strings.format green bold lang.c.tokens.reserved_words \b(if|double|break|else|byte|case|int|return|short|char|long|static|void|for|super|continue|goto|switch|while)\b lang.c.tokens.reserved_words.format white lang.c.tokens.constants \b([A-Z_]+|[A-Z_][A-Z0-9_]+)\b lang.c.tokens.constants.format yellow bold lang.c.tokens.comments (\/\/.*) lang.c.tokens.comments.format = lang.shared.tokens.comments.format lang.c.comment_string "// " lang.c.tokens.preprocessor (^\s*#.*) lang.c.tokens.preprocessor.format yellow bold lang.c.tokens.long_comments.open \/\* lang.c.tokens.long_comments.close \*\/ lang.c.tokens.long_comments.format = lang.shared.tokens.comments.format lang.c.tokens.non_alphanum ([!@#$%\^&*()\[\]{}/?=+\-\\|,<.>;:]) lang.c.tokens.non_alphanum.format white lang.c.indent.size 4 lang.c.indent.auto true lang.c.indent.roundup false #lang.c.indent.using_tabs true lang.c.indent.indenters_next_line (if\s*\(.+?\)\s*[^{]?$) lang.c.indent.indenters (case|[{\[(]$) lang.c.indent.unindenters (case|^\s+[\]})]) lang.c.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(\/\/.*) lang.c.indent.ignore ^(.+:|\s*?)$ lang.c.indent.not_indented ^\s*# lang.c.context.ignore ^(.+:|\s*\{?)$ # Configuration files lang.conf.filemask (?:\.conf(?:ig)?|\.cfg|\.cnf|user_prefs|XF86Config)$ lang.conf.format.default white lang.conf.format.selection inverse lang.conf.format.found yellow inverse lang.conf.tokens.commands ^\s*([^\s=#]+) lang.conf.tokens.commands.format cyan bold lang.conf.tokens.comments (^\s*#.*) lang.conf.tokens.comments.format yellow bold lang.conf.comment_string "# " lang.conf.tokens.doublequoted_strings (\".*?[^\\]\") lang.conf.tokens.doublequoted_strings.format green bold lang.conf.tokens.singlequoted_strings ('.*?[^\\]') lang.conf.tokens.singlequoted_strings.format green bold lang.conf.indent.size 4 lang.conf.indent.auto true lang.conf.indent.roundup true #lang.conf.indent.using_tabs true # crontab lang.crontab.filemask (?:^|\/)crontab$ lang.crontab.format.default white lang.crontab.format.selection inverse lang.crontab.format.found yellow inverse lang.crontab.tokens.comments (^\s*#.*) lang.crontab.tokens.comments.format yellow bold lang.crontab.comment_string "# " lang.crontab.tokens.schedule ^((?:[0-9\/*,-]+\s+){5}) lang.crontab.tokens.schedule.format cyan bold lang.crontab.tokens.commands ^(\S+=.+) lang.crontab.tokens.commands.format cyan lang.crontab.indent.size 4 lang.crontab.indent.auto true lang.crontab.indent.roundup true #lang.crontab.indent.using_tabs true lang.fstab.filemask ^fstab$ lang.fstab.format.default white lang.fstab.format.selection inverse lang.fstab.format.found yellow inverse lang.fstab.tokens.comments (^\s*#.*) lang.fstab.tokens.comments.format yellow bold lang.fstab.comment_string "# " lang.fstab.indent.size 4 lang.fstab.indent.auto true lang.fstab.indent.roundup true #lang.fstab.indent.using_tabs true # SQL lang.sql.filemask \.sql$ lang.sql.format.default white bold lang.sql.format.selection inverse lang.sql.format.found yellow inverse lang.sql.indent.size 4 lang.sql.indent.auto true lang.sql.indent.roundup false #lang.sql.indent.using_tabs true #lang.sql.tokens.reserved_words.case_insensitive \b(ABSOLUTE|ACCESS|ACTION|ADD|ADMIN|AFTER|ALIAS|ALL|ALLOCATE|AND|ANY|ARE|AS|ASC|ASSERTION|AT|AUDIT|AUTHORIZATION|AVG|BEFORE|BEGIN|BETWEEN|BIT_LENGTH|BOTH|BREADTH|BY|CASCADE|CASCADED|CASE|CAST|CATALOG|CHAR_LENGTH|CHARACTER_LENGTH|CHECK|CLASS|CLOSE|CLUSTER|COALESCE|COBOL|COLLATE|COLLATION|COLUMN|COMPLETION|COMPRESS|COMPUTED|CONCAT|CONNECT|CONNECTION|CONSTRAINT|CONSTRAINTS|CONSTRUCTOR|CONTINUE|CONVERT|CORRESPONDING|COUNT|CROSS|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURRENT|CURSOR|CYCLE|DATA|DAY|DBHIGH|DBKEY|DBLOW|DBMAC|DEALLOCATE|DECLARE|DECODE|DEFAULT|DEFERRABLE|DEFERRED|DEPTH|DEREF|DESC|DESCRIBE|DESCRIPTOR|DESTROY|DESTRUCTOR|DIAGNOSTICS|DICTIONARY|DISCONNECT|DISTINCT|DO|DOMAIN|EACH|ELEMENT|ELSE|ELSEIF|END-EXEC|END|EQUALS|ESCAPE|EXCEPT|EXCEPTION|EXCEPTIONS|EXCLUSIVE|EXISTS|EXTERNAL|EXTERNALLY|EXTRACT|FALSE|FILE|FIRST|FOR|FOREIGN|FORTRAN|FOUND|FROM|FULL|FUNCTION|GENERAL|GET|GLOBAL|GO|GOTO|GROUP|HAVING|HOUR|IDENTIFIED|IDENTITY|IF|IGNORE|IMMEDIATE|IN|INCREMENT|INDEX|INDICATOR|INITIAL|INITIALLY|INNER|INOUT|INPUT|INSENSITIVE|INSTEAD|INTERSECT|INTERVAL|INTO|IS|ISOLATION|JOIN|KEY|LABEL|LANGUAGE|LAST|LEADING|LEAVE|LEFT|LESS|LEVEL|LIKE|LIMIT|LOCAL|LOCK|LOOP|LOWER|MATCH|MAX|MAXEXTENTS|MIN|MINUS|MINUTE|MLSLABEL|MLS_LABEL_FORMAT|MODE|MODIFY|MODULE|MONTH|MOVE|MULTISET|NAMES|NATIONAL|NATURAL|NEW_TABLE|NEXT|NO|NOAUDIT|NOCOMPRESS|NONE|NOT|NOWAIT|NULL|NULLIF|NUMBER|NVL|OCTET_LENGTH|OF|OFF|OFFLINE|OID|OLD|OLD_TABLE|ON|ONLINE|ONLY|OPEN|OPERATION|OPERATORS|OPTION|OR|ORDER|OTHERS|OUT|OUTER|OUTPUT|OVERLAPS|PAD|PARAMETER|PARTIAL|PASCAL|PCTFREE|PENDANT|PLI|POSITION|PRECISION|PREORDER|PRESERVE|PRIMARY|PRIOR|PRIVATE|PRIVILEGES|PROCEDURE|PROTECTED|PUBLIC|RAW|READ|READUP|REAL|RECORD|RECURSIVE|REF|REFERENCES|REFERENCING|RELATIVE|RENAME|REPLACE|REPRESENTATION|RESIGNAL|RESOURCE|RESTRICT|RETURN|RETURNS|RIGHT|ROLE|ROUTINE|ROW|ROWID|ROWNUM|ROWS|SAVEPOINT|SCHEMA|SCROLL|SEARCH|SECOND|SECTION|SENSITIVE|SEQUENCE|SESSION|SESSION_USER|SET|SHARE|SIGNAL|SIMILAR|SIZE|SOME|SPACE|SPECIFIC|SQL|SQLCODE|SQLERROR|SQLEXCEPTION|SQLSTATE|SQLWARNING|START|STRUCTURE|SUBSTRING|SUCCESSFUL|SUM|SYNONYM|SYSDATE|SYSTEM_USER|TABLE|TEMPLATE|TEMPORARY|TEST|THAN|THEN|THERE|SQ92|TIMEZONE_HOUR|TIMEZONE_MINUTE|TO|TRAILING|TRANSACTION|TRANSLATE|TRANSLATION|TRIGGER|TRIM|TRUE|TUPLE|TYPE|UID|UNDER|UNION|UNIQUE|UNKNOWN|UPPER|USAGE|USER|USING|VALIDATE|VALUE|VALUES|VARIABLE|VARIANT|VIRTUAL|VARYING|VIEW|VISIBLE|VOID|WAIT|WHEN|WHENEVER|WHERE|WHILE|WITH|WITHOUT|WORK|WRITE|WRITEDOWN|WRITEUP|YEAR|ZONE)\b lang.sql.tokens.reserved_words.case_insensitive \b(ALL|AND|ANY|AS|ASC|BEGIN|BY|CASCADE|CASE|CAST|CHECK|COALESCE|COLUMN|CONSTRAINT|COUNT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURSOR|DECLARE|DEFAULT|DESC|DISTINCT|DO|ELSE|ELSEIF|END|EXCEPT|EXISTS|FALSE|FIRST|FOR|FOREIGN|FOUND|FROM|FULL|FUNCTION|GROUP|HAVING|HOUR|IF|IN|INCREMENT|INDEX|INNER|INPUT|INSTEAD|INTERSECT|INTERVAL|INTO|IS|JOIN|KEY|LANGUAGE|LAST|LEFT|LIKE|LIMIT|LOOP|MAX|MIN|NATURAL|NEXT|NO|NONE|NOT|NULL|NUMBER|OF|OFF|OLD|ON|ONLY|OR|ORDER|OUT|OUTER|PARTIAL|PRECISION|PRIMARY|REAL|RECORD|REF|REFERENCES|REPLACE|RESTRICT|RETURN|RETURNS|RIGHT|SCHEMA|SEQUENCE|SET|SUM|TABLE|TEMPORARY|THAN|THEN|TO|TRANSACTION|TRIGGER|TRUE|TYPE|UNION|UNIQUE|UPPER|USING|VALUE|VALUES|VARYING|VIEW|WHEN|WHERE|WHILE|WITH|WITHOUT|WORK)\b lang.sql.tokens.reserved_words.format white lang.sql.tokens.commands.case_insensitive \b(ALTER|COMMENT|COMMIT|CREATE|DELETE|DROP|EXEC|EXECUTE|FETCH|GRANT|INSERT|PERFORM|PREPARE|REVOKE|ROLLBACK|SELECT|UPDATE)\b lang.sql.tokens.commands.format cyan lang.sql.tokens.data_types.case_insensitive \b(BIT|BOOLEAN|CHAR|CHARACTER|DATE|DEC|DECIMAL|DOUBLE|FLOAT|INT|INTEGER|INTERVAL|LONG|NCHAR|NUMBER|NUMERIC|REAL|RECORD|ROW|SMALLINT|STRUCTURE|TIME|TIMESTAMP|TUPLE|VARCHAR|VARCHAR2)\b lang.sql.tokens.data_types.format brown lang.sql.tokens.comments (--.*) lang.sql.tokens.comments.format = lang.shared.tokens.comments.format lang.sql.comment_string "-- " lang.sql.tokens.singlequoted_strings ('.*?[^\\]') lang.sql.tokens.singlequoted_strings.format green bold lang.sql.tokens.typos (==) lang.sql.tokens.typos.format 15 bold lang.sql.tokens.non_alphanum ([!@#$%\^&*()\[\]{}/?=+\-\\|,<.>;:]) lang.sql.tokens.non_alphanum.format white lang.sql.indent.indenters ((?:\(|BEGIN|DECLARE|FROM|LOOP|ORDER BY|SELECT|SET|WHERE)$) lang.sql.indent.unindenters (^\s+(?:\)|;|BEGIN|DECLARE|END)) lang.sql.indent.preventers (\".+?[^\\]\")|('.+?[^\\]') lang.sql.context.ignore ^(\W+)$ # Bash lang.bash.filemask (?:\.(?:ebuild|bash_profile|bashrc))$ lang.bash.bangmask #!.*(?:ba)?sh\b lang.bash.format.default white bold lang.bash.format.selection inverse lang.bash.format.found yellow inverse lang.bash.indent.size 2 lang.bash.indent.auto true lang.bash.indent.roundup true #lang.bash.indent.using_tabs true lang.bash.tabsize 2 lang.bash.tokens.comments (^\s*#.*) lang.bash.tokens.comments.format = lang.shared.tokens.comments.format lang.bash.comment_string "# " lang.bash.tokens.singlequoted_strings ('.*?[^\\]') lang.bash.tokens.singlequoted_strings.format green bold lang.bash.tokens.doublequoted_strings (\".*?[^\\]\") lang.bash.tokens.doublequoted_strings.format green bold lang.bash.tokens.backquoted_strings (`.*?[^\\]`) lang.bash.tokens.backquoted_strings.format red bold lang.bash.indent.indenters (\{) lang.bash.indent.unindenters (\}) lang.bash.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(\/\/.*) lang.bash.indent.ignore ^(.+:|\s*?)$ # Tcl lang.tcl.filemask \.tcl$ lang.tcl.bangmask #!.*tcl lang.tcl.format.default white bold lang.tcl.format.selection inverse lang.tcl.format.found yellow inverse lang.tcl.indent.size 4 lang.tcl.indent.auto true lang.tcl.indent.roundup true #lang.tcl.indent.using_tabs true lang.tcl.tabsize 4 lang.tcl.tokens.comments (^\s*#.*) lang.tcl.tokens.comments.format = lang.shared.tokens.comments.format lang.tcl.comment_string "# " lang.tcl.tokens.reserved_words \b(encoding|incr|pid|tcl_endOfWord|Tcl|eof|info|tcl_findLibrary|after|error|interp|pkg_mkIndex|tcl_startOfNextWord|append|eval|join|proc|tcl_startOfPreviousWord|array|exec|lappend|puts|tcl_wordBreakAfter|auto_execok|exit|lassign|pwd|tcl_wordBreakBefore|auto_import|expr|lindex|re_syntax|tcltest|auto_load|fblocked|linsert|read|tclvars|auto_mkindex|fconfigure|list|regexp|tell|auto_mkindex_old|fcopy|llength|registry|time|auto_qualify|file|load|regsub|trace|auto_reset|fileevent|lrange|rename|unknown|bgerror|filename|lrepeat|resource|unload|binary|flush|lreplace|return|unset|break|for|lsearch|scan|update|catch|foreach|lset|seek|uplevel|cd|format|lsort|set|upvar|clock|gets|memory|socket|variable|close|glob|msgcat|source|vwait|concat|global|namespace|split|while|continue|history|open|string|dde|http|package|subst|dict|if|parray|switch)\b lang.tcl.tokens.reserved_words.format white lang.tcl.tokens.variables (\$[A-Za-z_][A-Za-z_0-9]*)\b lang.tcl.tokens.variables.format yellow bold lang.tcl.tokens.doublequoted_strings (\".*?[^\\]\") lang.tcl.tokens.doublequoted_strings.format green bold lang.tcl.tokens.non_alphanum ([!@#$%\^&*()\[\]{}/?=+\-\\|,<.>;:]) lang.tcl.tokens.non_alphanum.format white lang.tcl.indent.indenters (\{) lang.tcl.indent.unindenters (\}) lang.tcl.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(\/\/.*) lang.diff.filemask (?:\.(?:diff|patch|rej)|COMMIT_EDITMSG)$ lang.diff.format.default white lang.diff.format.selection inverse lang.diff.format.found yellow inverse lang.diff.indent.size 4 lang.diff.indent.auto false #lang.diff.indent.using_tabs true lang.diff.tabsize 4 lang.diff.tokens.oldfile (^--- .+$) lang.diff.tokens.oldfile.format red bold lang.diff.tokens.newfile (^\+\+\+ .+$) lang.diff.tokens.newfile.format green bold lang.diff.tokens.oldline (^-.+$) lang.diff.tokens.oldline.format red bold lang.diff.tokens.newline (^\+.+$) lang.diff.tokens.newline.format green bold lang.diff.tokens.location (^@@.+$) lang.diff.tokens.location.format green lang.diff.tokens.filediff (^Only in .+$) lang.diff.tokens.filediff.format magenta bold lang.diff.tokens.diff_command (^diff .+$) lang.diff.tokens.diff_command.format 13 bold lang.yaml.filemask (?:\.ya?ml)$ lang.yaml.format.default white bold lang.yaml.format.selection inverse lang.yaml.format.found yellow inverse lang.yaml.tokens.value_indicator (:)(?: |$) lang.yaml.tokens.value_indicator.format white lang.yaml.tokens.key_indicator (\? ) lang.yaml.tokens.key_indicator.format white lang.yaml.tokens.nested_series (?:^|[^-])(- ) lang.yaml.tokens.nested_series.format magenta bold lang.yaml.tokens.series_separator (,) lang.yaml.tokens.series_separator.format white lang.yaml.tokens.inline_series ([\[\]]) lang.yaml.tokens.inline_series.format white lang.yaml.tokens.inline_keyed ([{}]) lang.yaml.tokens.inline_keyed.format white lang.yaml.tokens.doublequoted_strings (\".*?[^\\]\"|\"\") lang.yaml.tokens.doublequoted_strings.format green bold lang.yaml.tokens.singlequoted_strings ('.*?[^\\]'|'') lang.yaml.tokens.singlequoted_strings.format green bold lang.yaml.tokens.block_scalar (\|[0-9+-]*)$ lang.yaml.tokens.block_scalar.format blue bold lang.yaml.tokens.folded_scalar (>[0-9+-]*)$ lang.yaml.tokens.folded_scalar.format blue bold lang.yaml.tokens.document_header ^(---.*)$ lang.yaml.tokens.document_header.format 10 bold lang.yaml.tokens.document_terminator ^(\.\.\.) lang.yaml.tokens.document_terminator.format 10 lang.yaml.tokens.directive_indicator ^(%.*) lang.yaml.tokens.directive_indicator.format 10 lang.yaml.tokens.comment_indicator (#.+) lang.yaml.tokens.comment_indicator.format = lang.shared.tokens.comments.format lang.yaml.comment_string "# " lang.yaml.tokens.anchor_indicator (&\w+) lang.yaml.tokens.anchor_indicator.format red bold lang.yaml.tokens.alias_indicator (\*\w+) lang.yaml.tokens.alias_indicator.format yellow lang.yaml.tokens.tag (!\w*) lang.yaml.tokens.tag.format yellow bold lang.yaml.tokens.null (~|null) lang.yaml.tokens.null.format red lang.yaml.tabsize 8 lang.yaml.indent.size 2 lang.yaml.indent.auto true lang.yaml.indent.roundup true lang.yaml.indent.indenters :$ lang.yaml.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(`.+?[^\\]`)|(^\s*#.*) lang.yaml.indent.ignore ^\s*$ lang.haml.filemask \.haml$ lang.haml.format.default white bold lang.haml.format.selection inverse lang.haml.format.found yellow inverse lang.haml.tabsize 8 lang.haml.indent.size 2 lang.haml.indent.auto true lang.haml.indent.roundup true lang.haml.indent.using_tabs false lang.haml.tokens.code.open [=~-] lang.haml.tokens.code.close $ lang.haml.tokens.code.format 9 bold lang.haml.tokens.code.change_to ruby lang.haml.tokens.tags (%\w+\b) lang.haml.tokens.tags.format white lang.haml.tokens.hash.open [{\[] lang.haml.tokens.hash.close [}\]] lang.haml.tokens.hash.format blue bold lang.haml.tokens.hash.change_to ruby lang.haml.tokens.class \.\w+ lang.haml.tokens.class.format cyan bold lang.haml.tokens.id #\w+ lang.haml.tokens.id.format cyan lang.haml.tokens.xml !!! lang.haml.tokens.xml.format magenta bold lang.haml.tokens.comments (^\s*-#.*) lang.haml.tokens.comments.format = lang.shared.tokens.comments.format lang.haml.comment_string "-# " lang.haml.tokens.html_comment ^ *(\/.*) lang.haml.tokens.html_comment.format = lang.shared.tokens.comments.format lang.haml.tokens.line_joiner \|$ lang.haml.tokens.line_joiner.format 12 bold lang.sass.filemask \.sass$ lang.sass.format.default white lang.sass.format.selection inverse lang.sass.format.found yellow inverse lang.sass.tabsize 2 lang.sass.indent.size 2 lang.sass.indent.auto true lang.sass.indent.roundup true lang.sass.indent.using_tabs false lang.sass.tokens.rules ^[A-Za-z0-9,.#\s_-]+$ lang.sass.tokens.rules.format cyan bold lang.sass.tokens.attributes ^ *(?::\S+|[A-Za-z0-9_-]+: ) lang.sass.tokens.attributes.format white bold lang.sass.tokens.colour #(?:[A-Fa-f0-9]{3}){1,2}\b lang.sass.tokens.colour.format yellow bold lang.sass.tokens.units \d+ *(px|em|pt)\b lang.sass.tokens.units.format brown lang.sass.tokens.silent_comments (\/\/.*) lang.sass.tokens.silent_comments.format = lang.shared.tokens.comments.format lang.sass.tokens.loud_comments (\/\*.*) lang.sass.tokens.loud_comments.format = lang.shared.tokens.comments.format lang.sass.tokens.line_joiner \|$ lang.sass.tokens.line_joiner.format 12 bold lang.sass.tokens.parent (&): lang.sass.tokens.parent.format red bold lang.makefile.filemask Makefile$ lang.makefile.format.default white lang.makefile.format.selection inverse lang.makefile.format.found yellow inverse lang.makefile.tokens.assignment_lhs ^\s*([^\s=]+)\s*[+?]?= lang.makefile.tokens.assignment_lhs.format white bold lang.makefile.tokens.comments (^\s*#.*) lang.makefile.tokens.comments.format = lang.shared.tokens.comments.format lang.makefile.comment_string "# " lang.makefile.tokens.targets (^\S+): lang.makefile.tokens.targets.format yellow bold lang.makefile.tokens.references @?\$(?:\(.+?\)|\w+) lang.makefile.tokens.references.format green bold lang.makefile.tokens.keywords ^\s*(else|endif|export|ifdef|ifeq|ifndef|ifneq) lang.makefile.tokens.keywords.format cyan bold lang.makefile.indent.size 8 lang.makefile.indent.auto true lang.makefile.indent.roundup true lang.makefile.indent.using_tabs true lang.makefile.indent.indenters ^(\S+:|ifdef|ifeq|ifndef|ifneq|else) lang.makefile.indent.unindenters ^(\S+:|endif) lang.makefile.indent.preventers (^\s*#.*) lang.makefile.indent.ignore ^\s*$ lang.bind.bangmask ^(@\s|\$TTL|;.*(?:bind|BIND|Bind)) lang.bind.format.default white bold lang.bind.format.selection inverse lang.bind.format.found yellow inverse lang.bind.tokens.comments (;.*) lang.bind.tokens.comments.format = lang.shared.tokens.comments.format lang.bind.comment_string "; " lang.bind.tokens.ttl \$TTL lang.bind.tokens.ttl.format yellow bold lang.bind.tokens.number \s(\d+)(?:[^0-9.mhdw]|$) lang.bind.tokens.number.format blue bold lang.bind.tokens.time \b(\d+)[mhdw] lang.bind.tokens.time.format red bold lang.bind.tokens.domain (?:[a-z][\w-]+\.)+[a-z][\w-]+\.? lang.bind.tokens.domain.format cyan bold lang.bind.tokens.ip4address \b\d+\.\d+\.\d+\.\d+\b lang.bind.tokens.ip4address.format cyan lang.bind.tokens.keywords1 \b(IN)\b lang.bind.tokens.keywords1.format white lang.bind.tokens.keywords2 \b(A|CNAME|MX|NS|SOA|TXT)\b lang.bind.tokens.keywords2.format yellow bold lang.bind.tokens.doublequoted_strings (\".*?[^\\]\"|\"\") lang.bind.tokens.doublequoted_strings.format green bold lang.bind.indent.size 8 lang.bind.indent.auto true lang.bind.indent.roundup true lang.bind.indent.using_tabs false lang.markdown.filemask \.(?:md|markdown) lang.markdown.format.default white lang.markdown.format.selection inverse lang.markdown.format.found yellow inverse lang.markdown.tokens.title (^# .*) lang.markdown.tokens.title.format 8 bold lang.markdown.tokens.subtitle (^## .*) lang.markdown.tokens.subtitle.format cyan bold lang.markdown.tokens.subsubtitle (^###+ .*) lang.markdown.tokens.subsubtitle.format cyan lang.markdown.tokens.list_item ^\s*\* lang.markdown.tokens.list_item.format white bold lang.markdown.tokens.code ^(?: {4,}|\t)\s*.+ lang.markdown.tokens.code.format yellow bold lang.markdown.indent.size 2 lang.markdown.indent.auto true lang.markdown.indent.roundup true lang.markdown.wrap_margin 80 lang.gherkin.filemask \.feature lang.gherkin.format.default white lang.gherkin.format.selection inverse lang.gherkin.format.found yellow inverse lang.gherkin.tokens.keyword ^\s*(And|As a|Background|But|Examples|Scenarios|Given|GivenScenario|I want|In order to|Scenario Outline|Then|When) lang.gherkin.tokens.keyword.format white bold lang.gherkin.tokens.feature_header ^\s*(Feature:.+) lang.gherkin.tokens.feature_header.format 8 bold lang.gherkin.tokens.scenario_header ^\s*(Scenario:.+) lang.gherkin.tokens.scenario_header.format 8 lang.gherkin.indent.size 2 lang.gherkin.indent.auto true lang.gherkin.indent.roundup true lang.gherkin.indent.indenters ^\s*(?:Feature|Scenario): lang.gherkin.wrap_margin 80 lang.haskell.filemask \.hs$ # lang.haskell.bangmask #!.*ruby lang.haskell.format.default = lang.shared.format.default lang.haskell.format.selection = lang.shared.format.selection lang.haskell.format.found = lang.shared.format.found lang.haskell.tokens.reserved_words \b(case|class|data|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|of|module|newtype|then|type|where)\b lang.haskell.tokens.reserved_words.format = lang.shared.tokens.reserved_words.format # lang.haskell.tokens.non_modifiers ^\s*(if|unless) # lang.haskell.tokens.non_modifiers.format white # lang.haskell.tokens.modifiers \s+(if|unless) # lang.haskell.tokens.modifiers.format 44 # lang.haskell.tokens.constants \b([A-Z_]+|[A-Z_][A-Z0-9_]+)\b # lang.haskell.tokens.constants.format = lang.shared.tokens.constants.format # lang.haskell.tokens.symbols [^:](:[a-zA-Z_][a-zA-Z_0-9]*) # lang.haskell.tokens.symbols.format white bold lang.haskell.tokens.comments (--.*) lang.haskell.tokens.comments.format = lang.shared.tokens.comments.format lang.haskell.comment_string "-- " lang.haskell.tokens.long_comments.open \{- lang.haskell.tokens.long_comments.close -\} lang.haskell.tokens.long_comments.format = lang.shared.tokens.comments.format # lang.haskell.tokens.regular_expressions (\/.+?[^\\]\/) # lang.haskell.tokens.regular_expressions (\/.+?[^\\]\/) # lang.haskell.tokens.regular_expressions.format red bold # lang.haskell.tokens.regular_expressions2 (%r\{.+?[^\}]\}) # lang.haskell.tokens.regular_expressions2.format red bold lang.haskell.tokens.doublequoted_strings (\".*?[^\\]\"|\"\") lang.haskell.tokens.doublequoted_strings.format green bold lang.haskell.tokens.singlequoted_strings ('.*?[^\\]'|'') lang.haskell.tokens.singlequoted_strings.format green bold # lang.haskell.tokens.backquoted_strings (`.*?[^\\]`|``) # lang.haskell.tokens.backquoted_strings.format red bold lang.haskell.tokens.numbers \b([0-9]+[.e][0-9]+|[0-9]+) lang.haskell.tokens.numbers.format blue bold lang.haskell.tokens.non_alphanum [@!#$%^&*()\[\]{}/?=+\-\\|,<.>;~] lang.haskell.tokens.non_alphanum.format white lang.haskell.indent.size 4 lang.haskell.indent.auto true lang.haskell.indent.roundup true lang.haskell.tabsize 4 lang.haskell.indent.indenters ^\s*(else|if|where)\b|([{\[(=]$|(?:do|let|of|where)$|\{\s*\|[\w\s,]*\|\s*$) # lang.haskell.indent.unindenters ^\s*(end|else|elsif|ensure|when|rescue)\b|(^\s*[\]})]) lang.haskell.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(`.+?[^\\]`)|(\/.+?[^\\]\/)|(^\s*--.*) lang.haskell.indent.ignore ^\s*$ # lang.haskell.context.ignore ^=(begin|end)$ lang.haskell.column_delimiters =>?|:|, # Lua lang.lua.filemask (?:\.lua)$ lang.lua.bangmask #!.*lua\b lang.lua.format.default white bold lang.lua.format.selection inverse lang.lua.format.found yellow inverse lang.lua.indent.size 4 lang.lua.indent.auto true lang.lua.indent.roundup true #lang.lua.indent.using_tabs true lang.lua.tabsize 4 lang.lua.tokens.reserved_words \b(and|break|do|else|elseif|end|for|function|if|local|nil|not|or|repeat|return|then|until|while)\b lang.lua.tokens.reserved_words.format = lang.shared.tokens.reserved_words.format lang.lua.tokens.comments (--.*) lang.lua.tokens.comments.format = lang.shared.tokens.comments.format lang.lua.comment_string "-- " lang.lua.tokens.singlequoted_strings ('.*?[^\\]') lang.lua.tokens.singlequoted_strings.format green bold lang.lua.tokens.doublequoted_strings (\".*?[^\\]\") lang.lua.tokens.doublequoted_strings.format green bold lang.lua.tokens.numbers \b([0-9]+[.e][0-9]+|[0-9]+) lang.lua.tokens.numbers.format blue bold lang.lua.tokens.non_alphanum [@!#$%^&*()\[\]{}/?=+\-\\|,<.>;~] lang.lua.tokens.non_alphanum.format = lang.shared.tokens.non_alphanum.format lang.lua.indent.indenters ([{\[(]) lang.lua.indent.unindenters ([}\])]) lang.lua.indent.preventers (\".+?[^\\]\")|('.+?[^\\]')|(\/\/.*) lang.lua.indent.ignore ^(.+:|\s*?)$ # Other configuration files can be included. # If a setting is specified again, it overrides the previous setting given # higher up in the configuration file(s). #include ~/.diakonos/custom.conf # Uncomment this line if your terminal supports 256 colours. #include ~/.diakonos/diakonos-256-colour.conf # Load extensions like this, specifying the extension directory (relative to ~/.diakonos/extensions) #load_extension dk-git diakonos-0.9.0/ebuild/000077500000000000000000000000001161735554400146065ustar00rootroot00000000000000diakonos-0.9.0/ebuild/ChangeLog000066400000000000000000000006671161735554400163710ustar00rootroot00000000000000# ChangeLog for app-editors/diakonos # Copyright 1999-2006 Gentoo Foundation; Distributed under the GPL v2 # $Header: $ *diakonos-0.7.8 (9 Nov 2005) 9 Nov 2005; Pistos pistos@purepistos.net package.rb, setup.rb : Added package.rb, setup.rb. *diakonos-0.7.7 (22 Oct 2005) 22 Oct 2005; Pistos pistos@purepistos.net diakonos, diakonos.conf, README, CHANGELOG : Initial import. Ebuild submitted by Pistos . diakonos-0.9.0/ebuild/diakonos-0.7.8.ebuild000066400000000000000000000007061161735554400202560ustar00rootroot00000000000000# Copyright 1999-2005 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ IUSE="" DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.tar.gz" LICENSE="GPL-2" SLOT="0" KEYWORDS="~x86" DEPEND="virtual/ruby" src_install () { ruby setup.rb --prefix="${D}/usr" install || die "setup.rb install failed." dodoc README CHANGELOG } diakonos-0.9.0/ebuild/diakonos-0.7.9.ebuild000066400000000000000000000007061161735554400202570ustar00rootroot00000000000000# Copyright 1999-2005 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ IUSE="" DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.tar.gz" LICENSE="GPL-2" SLOT="0" KEYWORDS="~x86" DEPEND="virtual/ruby" src_install () { ruby setup.rb --prefix="${D}/usr" install || die "setup.rb install failed." dodoc README CHANGELOG } diakonos-0.9.0/ebuild/diakonos-0.8.0.ebuild000066400000000000000000000007061161735554400202470ustar00rootroot00000000000000# Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ IUSE="" DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.tar.gz" LICENSE="GPL-2" SLOT="0" KEYWORDS="~x86" DEPEND="virtual/ruby" src_install () { ruby setup.rb --prefix="${D}/usr" install || die "setup.rb install failed." dodoc README CHANGELOG } diakonos-0.9.0/ebuild/diakonos-0.8.1.ebuild000066400000000000000000000007061161735554400202500ustar00rootroot00000000000000# Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ IUSE="" DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.tar.gz" LICENSE="GPL-2" SLOT="0" KEYWORDS="~x86" DEPEND="virtual/ruby" src_install () { ruby setup.rb --prefix="${D}/usr" install || die "setup.rb install failed." dodoc README CHANGELOG } diakonos-0.9.0/ebuild/diakonos-0.8.11.ebuild000066400000000000000000000007471161735554400203360ustar00rootroot00000000000000# Copyright 1999-2009 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ EAPI="2" DESCRIPTION="A Linux editor for the masses" HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/diakonos-0.8.11.tar.bz2" LICENSE="MIT" SLOT="0" KEYWORDS="~amd64 ~x86" IUSE="" DEPEND=">=dev-lang/ruby-1.9" RDEPEND="$DEPEND" src_install() { cd ${S} ruby19 install.rb --dest-dir "${D}" || die "install failed" } diakonos-0.9.0/ebuild/diakonos-0.8.2.ebuild000066400000000000000000000007061161735554400202510ustar00rootroot00000000000000# Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ IUSE="" DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.tar.gz" LICENSE="GPL-2" SLOT="0" KEYWORDS="~x86" DEPEND="virtual/ruby" src_install () { ruby setup.rb --prefix="${D}/usr" install || die "setup.rb install failed." dodoc README CHANGELOG } diakonos-0.9.0/ebuild/diakonos-0.8.3.ebuild000066400000000000000000000005311161735554400202460ustar00rootroot00000000000000# Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ inherit ruby gems DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.gem" LICENSE="GPL-2" SLOT="0" KEYWORDS="~x86" IUSE="" USE_RUBY="ruby18" diakonos-0.9.0/ebuild/diakonos-0.8.4.ebuild000066400000000000000000000005311161735554400202470ustar00rootroot00000000000000# Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ inherit ruby gems DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.gem" LICENSE="GPL-2" SLOT="0" KEYWORDS="~x86" IUSE="" USE_RUBY="ruby18" diakonos-0.9.0/ebuild/diakonos-0.8.5.ebuild000066400000000000000000000005271161735554400202550ustar00rootroot00000000000000# Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ inherit ruby gems DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.gem" LICENSE="MIT" SLOT="0" KEYWORDS="~x86" IUSE="" USE_RUBY="ruby18" diakonos-0.9.0/ebuild/diakonos-0.8.6.ebuild000066400000000000000000000005271161735554400202560ustar00rootroot00000000000000# Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ inherit ruby gems DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" SRC_URI="http://purepistos.net/diakonos/${P}.gem" LICENSE="MIT" SLOT="0" KEYWORDS="~x86" IUSE="" USE_RUBY="ruby18" diakonos-0.9.0/ebuild/diakonos-0.8.7.ebuild000066400000000000000000000004541161735554400202560ustar00rootroot00000000000000# Copyright 1999-2009 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ inherit ruby gems DESCRIPTION="A usable console text editor." HOMEPAGE="http://purepistos.net/diakonos" LICENSE="MIT" SLOT="0" KEYWORDS="~amd64 ~x86" IUSE="" USE_RUBY="ruby18" diakonos-0.9.0/ebuild/metadata.xml000066400000000000000000000013341161735554400171110ustar00rootroot00000000000000 ruby pistos@purepistos.net Pistos Diakonos is a customizable, usable console-based text editor. It features arbitrary language scripting, bookmarking, regular expression searching, parsed ("smart") indentation, macro recording and playback, a multi-element clipboard, multi-level undo, a customizable status line, completely customizable keyboard mapping, and customizable syntax highlighting. diakonos-0.9.0/extensions/000077500000000000000000000000001161735554400155415ustar00rootroot00000000000000diakonos-0.9.0/extensions/dk-hello-world/000077500000000000000000000000001161735554400203655ustar00rootroot00000000000000diakonos-0.9.0/extensions/dk-hello-world/hello-world.conf000066400000000000000000000000261161735554400234620ustar00rootroot00000000000000key f23 hello_world diakonos-0.9.0/extensions/dk-hello-world/hello-world.rb000066400000000000000000000001661161735554400231450ustar00rootroot00000000000000module Diakonos module Functions def hello_world @buffer_current.paste "Hello, world!" end end enddiakonos-0.9.0/extensions/dk-hello-world/info.yaml000066400000000000000000000014651161735554400222120ustar00rootroot00000000000000name: Hello World description: An example of a Diakonos extension author: name: Pistos email: somebody@example.com uri: http://blog.purepistos.net version: 1.0.0 uris: homepage: http://github.com/Pistos/diakonos/tree/master/extensions/dk-hello-world repository: git://github.com/Pistos/diakonos.git licence: MIT requirements: diakonos: minimum: 0.8.11 tested: - 0.8.11 - 0.8.12 gems: # - gemname: # minimum: 1.0.0 # tested: # - 1.0.0 # - 1.1.0 # - gemname: # minimum: 1.0.0 # tested: # - 1.0.0 # - 1.1.0 notes: > This extension adds a hello_world function to Diakonos. Pressing Shift-F11 will activate the function. diakonos-0.9.0/help/000077500000000000000000000000001161735554400142725ustar00rootroot00000000000000diakonos-0.9.0/help/about-help.dhf000066400000000000000000000025751161735554400170260ustar00rootroot00000000000000# Diakonos Help Welcome to the Diakonos help system! To learn more about how to use Diakonos, type in some keywords as if you were searching the Internet. Diakonos will show the titles of matching help documents. Use the arrow keys to choose a document, and press Enter to read it. If you're not sure what keywords to type, you can type a partial word and press to see a list of tags that start with what you typed. Or, advanced users can prefix the search with a slash (/) and a full-document, regular expression search will be performed. Type a slash by itself to see a list of all help documents. The documentation is written using the default key chords and sequences. As such, please be aware that the documentation may not correspond to your actual setup if the keyboard configuration has been changed (by you, or someone else, such as a system administrator). When you are finished reading a document, close it with the close file key chord, . To abort your search for help and close the help system, press twice. ## Diakonos Help Files The help documents are normal files, and are opened just like other files in Diakonos. You can copy code examples and configuration lines out of them and paste them in other buffers. You can even create your own files (with a .dhf extension) and place them alongside the default help files. Tags: diakonos help usage support diakonos-0.9.0/help/clipboard.dhf000066400000000000000000000036551161735554400167250ustar00rootroot00000000000000# The Clipboard To select text, press . This marks (or "anchors") one end of the text you wish to select. Use any movement keys (such as the arrow keys) to move the cursor to the other end of the text you wish to select. As you do so, you will see the selection grow, being highlighted in a different colour. To work with the selection, press one of the following key chords: to copy to cut to paste to unselect the text Diakonos also lets you cut one or more lines of text without needing to delineate a selection. Pressing once cuts the current line and places it in the clipboard. You can press more times to cut and add more lines. will cut from the cursor to the end of the current line. Diakonos also supports synchronization with Klipper, the KDE clipboard manager. This requires DCOP to be installed. Uncomment the indicated line in the configuration file. Alternatively, synchronization with the X clipboard can be accomplished with xclip (third-party software). Uncomment the xclip line for xclip usage. ## Block Selection Diakonos supports block selection. This allows you to select and work with rectangular highlighted areas instead of selecting text the usual way (as a left-to-right flow of characters). To change to block selection mode, press . The status line will indicate "block" mode. To change to normal selection mode, press . Mnemonic: M for Mark, B for Block, N for Normal. ## Advanced Selection Press to select the current code block. That is, the lines which are at the same depth of indentation as the current line. Press more times to select each successive parent block (i.e., lines at shallower levels of indentation). Tags: clipboard copy cut paste kde klipper dcop select selecting selection selected unselect unselecting mark marking highlight eol line block column diakonos-0.9.0/help/close-file.dhf000066400000000000000000000002731161735554400170010ustar00rootroot00000000000000# Closing a File Press to close the current file. Help documents and error messages are also files, and are closed with . Tags: close closing file files buffer buffersdiakonos-0.9.0/help/code-block-navigation.dhf000066400000000000000000000014421161735554400211150ustar00rootroot00000000000000# Code Block Navigation Using , you can jump to the next code block of the same indentation level as the current line. goes back in the opposite direction (up or previous block). You might use this to easily browse: the methods of a class; or the different 'when' clauses of a Ruby case expression; or the components of an if-elsif-else tree; or the rules of a CSS stylesheet; and so on. Diakonos will automatically limit the extent of the navigation, so if you start your browsing within an if-elsif tree, your cursor won't jump outside that tree if you press too many times. brings the cursor one block level deeper; brings you out one level. Tags: code block navigation navigate move moving movement jump jumping cursordiakonos-0.9.0/help/column-markers.dhf000066400000000000000000000011771161735554400177220ustar00rootroot00000000000000# Column Markers You can define column markers using the view.column_markers.* settings. You might use a column marker as a visual cue to help you not exceed a certain line length. You can set up as many column markers as you like. ## Example of a column marker view.column_markers.margin.column 80 view.column_markers.margin.format 9 Adding these lines to your configuration would set up a column marker named 'margin'. The name 'margin' is arbitrary; use whatever string you want for your markers. The 'margin' marker would highlight the 80th column using the format code 9 (white on red in the default 16-colour configuration). diakonos-0.9.0/help/config.dhf000066400000000000000000000055311161735554400162260ustar00rootroot00000000000000# Configuring Diakonos ## Personal configuration Press to open your personal Diakonos configuration file, which is ~/.diakonos/diakonos.conf . Read the comments in the file for information on the individual settings. Edit the file as you like. When you save the file, your changes take effect immediately in your current session. Your personal configuration remains separate from the system-wide configuration, located elsewhere. Your personal settings take precedence over system configuration where there is any difference or discrepancy. ## Saving configuration changes Since configuring Diakonos is nothing but editing and saving the configuration file, to stop configuring, simply switch buffers or close the configuration file (with ). ## Configuration file format Each line in the configuration file has a setting identifier and the value of the setting, for example: lang.text.format.default white The identifier and the value are separated by one or more spaces. Previous versions of Diakonos used a semicolon to separate; this is still permitted, but may not be in future versions. Comments can be placed in the file by starting a line with an octothorpe character (#). ## Including other configuration files You can create and include custom configuration files which remain distinct from your standard default configuration file. You can place these files wherever you like, but it is recommended to put them in ~/.diakonos. Then, place a line like this at the bottom of the default configuration file: include ~/.diakonos/extra.conf If a setting is specified again (whether in the same file, or an included file), it overrides the previous setting given higher up in the configuration file(s). Note that editing and saving custom configuration files which reside outside of ~/.diakonos will not cause the changes to be automatically loaded like they are with configuration files in ~/.diakonos. To reload all configuration files, quit and restart Diakonos, or press and type "load_configuration". ## Configuration inheritance Configuration settings can be inherited (cascaded). Simply use an equals sign (=) to set one setting to the value of another. one.setting = another.setting For an example, have a look at the Ruby language definition in the default configuration file. See how the shared settings are defined earlier in the file, then used later on in the Ruby language configuration. Inheritance will work for any setting, not just formatting. The important thing to remember is that Diakonos will parse configuration files top to bottom, and visit each included file in the order the include directives are encountered, with a depth-first strategy. So you should define ancestor settings before descendant settings. Tags: diakonos config configure configuration configuring setup setting settings options option preferences diakonos-0.9.0/help/cursor-stack.dhf000066400000000000000000000016101161735554400173730ustar00rootroot00000000000000# The Cursor Stack The cursor stack is just like the Back and Forward functionality of your web browser. Diakonos semi-intelligently keeps track of the places where you do work. Using the cursorReturn command (), you can return to previous work areas. Use to go forward through the stack. Here is an example of a common scenario: 1. you are editing in some location 2. you need to examine some other code (such as the definition of a method) elsewhere in the file 3. you page through the file, or search for text 4. after examining the code there, possibly copying material to the clipboard, 5. you press and return to the exact location you were working in prior to your search Tags: cursor stack move movement jump jumping moving remember previous position next back forward browser web bookmark bookmarks bookmarking webbrowser page file search return clipboarddiakonos-0.9.0/help/delete.dhf000066400000000000000000000027041161735554400162220ustar00rootroot00000000000000# Deleting Text ## Common Deletion Diakonos behaves just as you would expect when you press or ; they delete the current and previous character respectively. When text is selected, pressing or will delete the selected text. Selecting text and then typing (or pasting) will also delete the selected text (and then process what was typed or pasted). ## Deleting a Line will delete the current line, regardless of where on the line the cursor is. ## Deleting Part of a Line will delete all the text from the cursor to the end of the current line. You can delete from the cursor up to a certain character by pressing (mnemonic: "Delete Till"). Diakonos will prompt you for a character, and then delete everything from the cursor to the first instance of that character to the right of the cursor. For example, pressing will delete up to the next period. You can delete all text in between a pair of the same character by pressing (mnemonic: "Delete Inside" or "Delete In Between"). Diakonos will prompt you for a character, and then delete between the closest pair of that character. For example, situating the cursor inside a string inside some source code, then pressing will deleted the contents of the string. That is: my_string = "this is a string" would become my_string = "" Tags: delete deleting text deletion remove removal removing linediakonos-0.9.0/help/extensions.dhf000066400000000000000000000114601161735554400171560ustar00rootroot00000000000000# Extending Diakonos Diakonos has a simple but powerful extension system. Extensions are written in Ruby (http://www.ruby-lang.org). ## Installing and Uninstalling Extensions ### Unpack/Clone Extensions are installed in ~/.diakonos/extensions/. Each extension should have its own subdirectory under there. Extension tarballs or repository clones should be unpacked or cloned under there. ### Load Once an extension is installed into ~/.diakonos/extensions/, you activate it by adding a command to your configuration: load_extension name_of_the_extension Diakonos will load extensions at startup, and will reload extensions whenever the Diakonos configuration is updated. ### Unload To deactivate an extension, simply remove (or comment out) all load_extension directives from your configuration which load the extension. ### Uninstall Extensions can be removed cleanly by deleting the extension's subdirectory out of ~/.diakonos/extensions/. ## Extension Format ### Directory Structure A Diakonos extension consists of a directory (or directory tree) of files: info.yaml *.conf *.rb The simplest extension will have nothing but an info.yaml file. This "empty" extension will do nothing useful, though, of course. Diakonos will parse and load all configuration files (*.conf) in the root of the extension's directory. All Ruby files (*.rb) found in the extension's directory, or any subdirectory underneath it, are loaded and executed at startup, and on configuration change. Typically, an extension will only have one configuration file, but it may have any number of Ruby files. ### Information File To be valid, an extension must have a properly-formatted info.yaml file. As the filename suggests, info.yaml is a YAML file. It consists of several keys, and a few arrays, described below. The diakonos key is required. It is strongly recommended to have name, uris and version keys. The other keys are optional. name: (recommended) The name of the extension. description: (optional) A brief, one-line description of the extension. author: (optional) Several subkeys provide information about the extension's author. name: The author's name or nickname. email: The author's email address. uri: A URI associated with the author. This might be a homepage, or a blog. version: (recommended) The version of the extension. uris: (recommended) homepage: The website giving more information about the extension. repository: The URI of the extension's source code repository. This should be a URI that can be used with version control software, and so might begin with "svn://" or "git://". licence: (optional) The licence of the extension's source code. requirements: (required) Several subkeys tell diakonos about what versions of things the extension works with. diakonos: (required) Several subkeys tell Diakonos about what versions of Diakonos the extension works with. minimum: The minimum version of Diakonos required for the extension to function properly. tested: A list of Diakonos versions which the extension is known to run under. gems: (optional) If the extension needs any gems to function, they should be listed here, with their minimum and tested versions given. notes: (optional) Longer text describing the extension, its capabilities and its usage. For multiple paragraphs, use the YAML syntax "notes: >", and indent the paragraphs to the same level. ## Extension Code Extension code is any valid Ruby code. See http://rdoc.info/projects/Pistos/diakonos for source code documentation for Diakonos, and http://github.com/Pistos/diakonos/tree/master/extensions/dk-hello-world for an example of an extension. To have code execute on keypress, define a method in the Diakonos::Functions module. All methods in Diakonos::Functions are exposed to the keying system, any method name can be referred to by the key directive in configuration files. Methods of Diakonos::Functions are run within the context of the main ::Diakonos::Diakonos object. In this context, you get access to all of the instance variables. Some variables of note: @current_buffer @diakonos_home String containing the user's Diakonos dir (usually ~/.diakonos) @buffers A BufferHash holding all the open buffers @status_vars @settings A Hash containing all settings from all configuration files When not within a method of Diakonos::Functions, main ::Diakonos::Diakonos object can be referred to by using the global variable $diakonos. Tags: script scripts scripting program programming language ruby extend extension extensions plugin plug-in plugins plug-ins addon addons add-on add-ons package packages format layout structure load loading unload unloading activate deactivate activating deactivating install installing installation diakonos-0.9.0/help/file-type.dhf000066400000000000000000000020271161735554400166540ustar00rootroot00000000000000# File Type The language (or type) of a file is shown in the status bar between parentheses. For example, the file type of this help document is "dhf". Diakonos can usually guess a file's language correctly. To do so, it considers the filename and, if present, the "bang" line at the top of the file. The bang line takes precedence over the filename. If Diakonos was wrong in its automatic determination of the file type, you can force it to assume a certain file type by pressing and typing in the file type (e.g. java, ruby, html, xml, and so on). The configuration settings (available by pressing ) which affect Diakonos' guessing are a language's filemask and bangmask settings. These settings are regular expressions. For example: lang.perl.filemask \.(?:pl|pm)$ lang.perl.bangmask perl These configuration lines tell Diakonos to think a file is a Perl file if its extension is .pl or .pm, or if the bang line has the word "perl" in it. Tags: file files lang language languages programming type mode types modesdiakonos-0.9.0/help/key-mapping.dhf000066400000000000000000000115041161735554400171770ustar00rootroot00000000000000# Key Mapping ## Executive Summary key mapping exploration mode key printing mode edit configuration file Example configuration line: key alt+b alt+! addNamedBookmark 1 ## Customizing the Diakonos key mapping Diakonos' key mapping is extremely customizable. You can map any Diakonos function to nearly any key chord or key sequence (as long as your terminal can produce the chord or sequence). To change the key mapping for a function, or to change the function mapped to a key mapping, you need to know what function you want performed, and what key chord or sequence you want to press in order to perform that function. Diakonos can help you determine these. ## What does this key do? Press and Diakonos will enter a special mode. In this mode, any key chord or sequence you press will make Diakonos report the function (and any function arguments) which are mapped to what you pressed. Try it now! When you are finished exploring, press to exit the key mapping exploration mode. Here is an example of what the key exploration mode might display. This is seen when you query what does: ctrl+s -> saveFile( ) This indicates that the keychord (ctrl+s) executes the saveFile function. The empty parentheses tell us that the saveFile function is not given any arguments. It is worth noting that some keys or chords may have strange-looking key sequences, depending on your terminal. For example, the key may not be a single keycode, but rather a sequence, like "esc [ 1 ~". There's nothing wrong with this, but you should be aware of it when customizing your keyboard layout. ## What do I need to press to _____? One way to determine the current key mapping for a given feature or function is to press to enter the help system, and then type some search keywords to search the help system for documentation describing the feature. All help documents have relevant key mappings described. Once you determine the key mapping for the function you're interested in, use to get the actual name of the function. Not all features may be documented at this time, though. If you can't find the key mapping for a function, the alternative is to open the configuration file (with ) and move down to the key configuration section. This section has many lines starting with the word "key", such as these lines: key left;cursorLeft key esc [ D;cursorLeft key right;cursorRight key esc [ C;cursorRight ## How do I specify a keychord or sequence? Diakonos has another built-in function to help you in mapping keys. Press , and Diakonos enters a key printing mode. In this mode, you can press any sequence of keystrokes or key chords, and Diakonos will display what string to use in the configuration file. Press when you have completed your sequence. Here are a couple of examples. If you press and then and , it will print the string "ctrl+d" into the current buffer. If you press and then and , and press , it will print something like "esc l esc [ 1 ~" into the current buffer (the exact string may vary depending on your terminal). Use these strings to configure Diakonos' key mapping (see below). ## Setting a key mapping Once you know the name of the function you want performed and the string for the key mapping, press to edit the configuration file. Add a new key mapping line to the key configuration area. It doesn't matter exactly where, but you should try to keep your configuration file organized to make it easier to adjust in the future. A key mapping line looks like this: key alt+b alt+! addNamedBookmark 1 It has these components: - the "key" configuration command - one or more keystrokes or keychords, in order ("alt+b alt+!") - two or more spaces - the Diakonos function ("addNamedBookmark") - any arguments to the function, separated by commas ("1") For example, suppose you wanted to make the keychord drop to the shell and execute 'ls' and show the results. You would set this up with a new line in the configuration file. Type 'key' and space: key then press , and to print out the string Diakonos expects for . Your line will then be: key esc l Then add a few spaces, and the shell command. Your final line will be: key esc l shell "ls" Press to save the configuration, and your new key mapping will be ready for use. Try it! ## Unsetting a key mapping If other configuration files (such as the system-wide one) are introducing a key mapping that you want to unmap, simply configure the key to have no function. For example: key ctrl+g Tags: key keys keyboard map mapping layout change config configure set different alternate function feature command unset unmap override shortcut shortcuts short cuts diakonos-0.9.0/help/line-numbers.dhf000066400000000000000000000015711161735554400173610ustar00rootroot00000000000000# Line Numbers Diakonos indicates on the status line (at the bottom right of the screen) the current line and column that the cursor is over. For example: L 6/ 8 C13 means that the cursor is on the 13th column of the 6th line of a file which is 8 lines long. ## Showing line numbers Default keychord can be used to toggle line numbering on and off. Line numbers appear in a left-side margin. Enable line numbering permanently by setting view.line_numbers to true in your config. Set view.line_numbers.width to the number of columns to use for the line numbering margin. view.line_numbers.number_format is the setting to use to define a sprintf format for the line numbers. Set the colour and brightness with view.line_numbers.format. Tags: line number numbers numbering sprintf format colour color config configuration set setting settings toggle show margindiakonos-0.9.0/help/macros.dhf000066400000000000000000000021351161735554400162420ustar00rootroot00000000000000# Macro Recording and Playback Diakonos has a macro system that allows you to record nearly any series of commands and play them back. At the same time, advanced users may wish to consider employing Diakonos' powerful Ruby scripting capabilities to leverage their programming knowledge to manipulate text more directly. ## Recording a Macro If necessary, move the cursor to the desired place before beginning to record. Press to begin recording a macro. Type any sequence of keystrokes or keychords. When you are finished entering the sequence, press again to stop recording. ## Playing the Recorded Macro After a macro is recorded, move the cursor to the spot where you wish to begin executing the macro. Press to play the recorded macro. ## Saving Macros Diakonos currently has no facility to save macros for future playback. If you want this feature in Diakonos, please visit the Diakonos technical support channel and voice your request. Tags: macro macros record recording play playback playing script scripting key keys keystroke keystrokes command commands function functionsdiakonos-0.9.0/help/new-file.dhf000066400000000000000000000002751161735554400164670ustar00rootroot00000000000000# Creating a New File Press to open a new, empty buffer. The buffer will have no filename associated with it until it is saved. Tags: create creating open opening new file filesdiakonos-0.9.0/help/open-file.dhf000066400000000000000000000016371161735554400166420ustar00rootroot00000000000000# Opening a File Press to open a file in Diakonos. You will be presented with a prompt in which you can type in the path to the file you wish to open. When entering a file path, you can use the key to complete partial paths, just as you can in your shell. Additionally, if a list of files is presented after tab-completion, you can use the and arrow keys to select one of the listed files, and press to open the selected file. You can also open files by passing one or more filenames as arguments to the "diakonos" command. For example: diakonos ~/.diakonos/diakonos.conf Diakonos can also open all files in a directory tree matching a regular expression, using the -m command line option: cd ~/project diakonos -m some_method_name Tags: open opening file files new existing dir directory regex regexes regexen regexp regexps regular expression expressions match matching grepdiakonos-0.9.0/help/quit.dhf000066400000000000000000000004041161735554400157350ustar00rootroot00000000000000# Quitting Diakonos To quit (close) the Diakonos text editor, press . If any open files have unsaved modifications, you will be prompted about what further action you would like to take. Tags: quit quitting exit exitting leave leaving close closing diakonos-0.9.0/help/resizing.dhf000066400000000000000000000012461161735554400166120ustar00rootroot00000000000000# Resizing Diakonos In most cases, Diakonos can automatically detect when the wrapping terminal or console changes size (due to a window resize or font change), and redraw itself. On some systems, however, Diakonos cannot handle a terminal resize. If your system exhibits problems after resizing, try this bash command before starting Diakonos: shopt -s checkwinsize Read more about the shopt built-in command here: http://linux.about.com/library/cmd/blcmdl1_shopt.htm Pressing will force Diakonos to redraw itself. Tags: bash size resize resizing window terminal console change draw redraw problem problems troubleshoot troubleshooting issue issuesdiakonos-0.9.0/help/ruby.dhf000066400000000000000000000010241161735554400157330ustar00rootroot00000000000000# Ruby Compatibility ## Ruby 1.9 Usage to date has shown that Diakonos is fully compatible with Ruby 1.9. There are no known problems. If you encounter any issues when running Diakonos under Ruby 1.9, please report them in IRC or with the issue tracker. ## Ruby 1.8 Support for Ruby 1.8 was dropped as of Diakonos version 0.8.8. 0.8.9 is the last version of Diakonos to somewhat run under Ruby 1.8. 0.8.10+ are known not to run at all under Ruby 1.8. Tags: ruby 1.9 1.8 19 18 compatible compatibility problems issues versiondiakonos-0.9.0/help/save-file.dhf000066400000000000000000000006361161735554400166350ustar00rootroot00000000000000# Saving a File Press to save the current file. Press to save the current file under a different filename or path. The strip_trailing_whitespace_on_save setting controls whether trailing whitespace is removed from the lines of a file when a buffer is saved. The default configuration has this setting turned on. Tags: save saving file filename as save-as trailing white space whitespacediakonos-0.9.0/help/scripting.dhf000066400000000000000000000062311161735554400167610ustar00rootroot00000000000000# Scripting Diakonos Diakonos has several features and mechanisms that allow you to manipulate it using Ruby, a beautiful yet powerful programming language (http://www.ruby-lang.org). ## Working with Selected Text Select the text you wish to operate on (by pressing and moving the cursor). You can then work with the text in one of three ways: 1. as a contiguous string of characters 2. iterating over each line 3. as an array of lines ### As a String Press to work with the text as if it were one big string (multiple for Ruby code that uses the variable "str". For example, entering str.upcase will convert the selected text to uppercase. ### Iterating Over Each Line Press to iterate over each line of selected text. You will be prompted for Ruby code which will act as the body of a Ruby block which uses the variable "line" and evaluates to a String. For example: line.strip.squeeze( ' ' ) will strip off whitespace from the beginning and end of each line and then collapse all consecutive sequences of spaces into single spaces. ### As an Array of Lines Press to work with the text as if it were an Array of lines. You will be prompted for Ruby code which operates on the array variable "lines". For example: lines.find_all { |l| /foo/ === l } will replace the selected lines with the lines that match the regular expression /foo/. lines.sort will sort the selected lines. ## Startup Scripts Any file placed in ~/.diakonos/scripts/ will be require-d (as Ruby code) when Diakonos starts up. Any valid Ruby code can be placed there. Advanced users can even manipulate Diakonos itself by referencing the $diakonos global variable. After the startup scripts are require-d, Diakonos evaluates any Ruby code given with the -e command line argument. Here is an example of using the -e argument to initiate a search on startup: diakonos -e 'find "search expression", case_sensitive: true' filename See also the documentation on extensions. ## Hooks Diakonos provides a means for you to execute arbitrary Ruby code when certain events occur. In other words, you can "hook" code onto the events. At present, the following hooks are available: :after_buffer_switch :after_open :after_save :after_startup To hook onto one of these events, place code into the ~/.diakonos/scripts/ directory. Example hook code can be seen at http://github.com/Pistos/dk-git/blob/master/git-branch.rb Your code should create a Proc object (possibly with a block parameter, depending on the hook), and then register it with the following syntax: $diakonos.register_proc( my_proc, :after_open ) The register_proc method takes an optional third parameter: an integer indicating the relative priority for your Proc. Lower numbers are used for greater priority (like the UNIX "niceness" level). Procs registered for the same hook are executed in order of priority. Tags: script scripts scripting program programming language ruby select selected text manipulate manipulating operate operating change changing work working line lines adjust adjusting hook hooks hooking proc procedure block trigger triggers method function functions start up startup diakonos-0.9.0/help/search.dhf000066400000000000000000000100511161735554400162170ustar00rootroot00000000000000# Searching for and Replacing Text ## Executive Summary ### Searching Begin search Find next Begin search and replace Clear match highlighting Begin case-sensitive search Begin upward search Find next upwards While typing search expression: Confirm search expression Abort search ### Grepping Grep current buffer Grep all buffers Grep a directory While typing grep expression: , Select a grep result to jump to Jump to selected grep result Decrease context around matches Increase context around matches Abort grep ## Searching for Text Press to perform a case-insensitive search for text. You will be prompted for what to search for. As you type your search expression, matching text will be highlighted. You can try it right now as you read this document! Press and then type the word "text". Press twice to abort the search. If the find.return_on_abort setting is set to true, then the cursor will return to where it was when the search began. Otherwise, it will remain where the last search brought it. What you type will be interpreted as a regular expression. (If you don't know what a regular expression is, search the Internet, or read the Wikipedia article: http://en.wikipedia.org/wiki/Regular_expression ) Press to submit your search expression, and Diakonos will keep the cursor on the first match it found and select it. That is, it selects the closest match below the point where you initiated the search. Press to move the cursor to the next match. To clear the highlighting on matches, press . ### Advanced Searching Use to do a case-sensitive regular expression search. will search upwards (backwards), and will repeat a search upwards. The findExact function will perform a search which does not consider the search expression to be a regular expression, but rather a literal string. There is no default key mapping for findExact; use to modify your configuration. Alternatively, you can press and enter "findExact" to execute the function directly. If you select text before searching, the search will be restricted to the selected text. Even repeated searches with will be restricted. ## Replacing Text Press to replace text. As with searching, you will be prompted for what to search for. Press to submit your search expression, and then you will be prompted for the replacement text. Press to submit the replacement text. Diakonos will then highlight each individual match and ask whether or not you wish to replace the selected text. You can also choose to replace all matches throughout the file at once. The search expression you provide is considered a regular expression. You can also use parentheses to capture groups, and refer to those groups on your replacement string with \1, \2, etc., which correspond to the first group, the second group, etc. ## Grepping Press to begin grepping files under a directory (recursively). Specify the directory, then press . Then begin typing a regular expression. The display will update as you type according to the matches found. If you see a match you'd like to jump to, use (and ) to select a match, and press to view that line of that file. Press twice to abort the grep. If you need to see more context around the matches, press during the grep. reduces the context. The grep.context setting is used for the default amount of context to show. Use to grep through all open buffers, to grep only the current buffer. Tags: search searching replace replacing find finding text string regex regexp regular expression grep grepping dir dirs directory buffer buffers file files diakonos-0.9.0/help/shell.dhf000066400000000000000000000043531161735554400160710ustar00rootroot00000000000000# External Programs Diakonos has several functions available that you can map to keys in order to execute external programs, scripts and applications: shell, execute and pasteShellResult. Each one takes an optional string argument, which is the shell command to execute. If no argument is given, the user is prompted for the command to execute. shell will run the command and show the results in a new buffer. execute will run the command, and allow you to interact with it, but discard the results. pasteShellResult will paste the command's results at the current cursor location. The shell command also takes an optional second parameter which lets you specify the file to which the shell results are to be written. Press to specify an arbitrary command to run with 'shell'. Press to specify an arbitrary command to run with 'execute'. ## Shell Variables The command strings to these commands given can contain any of the following variables: $f the current buffer's filepath $d the current buffer's directory $F all current buffer filepaths, space-separated $i a string obtained from user input $c temp file containing current clipboard text $k temp file containing current klipper (KDE clipboard) text $s temp file containing currently selected text ## Examples The following examples are found in the default configuration file. key ctrl+alt+c shell "ruby -c $f" Press to check the Ruby syntax of the current buffer. key esc d shell "diff -U 5 -w -b $c $s", "clipboard.diff" Press to diff the current clipboard text against the currently selected text, and write the result to a file named clipboard.diff. key esc l execute "aspell check $f" Press to interactively spell check the current file with the aspell program. (This keychord is not active in the default configuration.) key f9 shell "cd $d; git diff --ignore-space-change -- $f", 'git.diff' Press to see all changes made to the current buffer that have not been committed to the git repository yet. Tags: shell system exec execute spawn spawning executing shelling out external program programs application app apps applications variable variables substitute substitution spell spelling check git diff difference diakonos-0.9.0/help/speed.dhf000066400000000000000000000022421161735554400160550ustar00rootroot00000000000000# Speeding Up Diakonos Diakonos is known to run a little slower on some less-powerful systems. Here are some of the things you can do to speed up Diakonos. Each one involves a tradeoff between editor features and speed. You don't need to enact them all, just do whatever you need or can sacrifice. - Turn off the context line ("content.visible false" in the config file). - After a successful find, unhighlight the found items, if you don't need to see them any more (Ctrl-Alt-U by default). - Turn off syntax highlighting by specifying a file type of "text" (Alt-Shift-T to specify the type). Alternatively, just reduce the number or complexity of highlight definitions in the language you are using. More highlight definitions means more work for Diakonos during display. - If you are using a graphical desktop (such as KDE or Gnome), change the size of the window to something smaller, since this will mean fewer characters for Diakonos to redraw. Equivalently, for raw console (TTY) users, try a larger font size for a similar effect. Tags: slow diakonos speed speed-up speedup fast faster draw redraw screen font context line quick quicker syntax highlight highlightingdiakonos-0.9.0/help/support.dhf000066400000000000000000000013251161735554400164720ustar00rootroot00000000000000# Support You can chat about Diakonos in the #mathetes channel of the FreeNode IRC network. If you don't have an IRC client, or don't know what IRC is, you can direct your web browser to http://webchat.freenode.net/?channels=mathetes Go to the IRC channel for technical support, or to give feedback and commentary about Diakonos. It's the place go for bug reports, feature requests and tech support. Even if Pistos is not around, he will eventually read anything you have to say. If IRC is not your thing, you can file bug reports at the issue tracker: http://linis.purepistos.net/ticket/list/Diakonos Tags: help support technical tech contact email e-mail info information chat irc channel pistos author creatordiakonos-0.9.0/help/switch-buffers.dhf000066400000000000000000000013531161735554400177120ustar00rootroot00000000000000# Switching Buffers To switch between buffers, press Alt-number, with the number corresponding to the index of the buffer you wish to change to. For example, will switch to the first buffer, will switch to the third buffer, and so on. You can also browse through the buffers by pressing and . To bring up a list of the currently open files, press . There are two ways to select a buffer from this list: Either type the number or letter shown in the left column corresponding to the file you wish to switch to, or use the and arrow keys to select a buffer, and press to switch to it. Tags: switch switching buffer buffers file files change between list current currently opendiakonos-0.9.0/help/tabs.dhf000066400000000000000000000022341161735554400157070ustar00rootroot00000000000000# Tab Characters ## Indenting with tab characters instead of spaces By default, Diakonos indents with spaces. To insert a single tab character, press . To make Diakonos always indent with tab characters, look for the indent settings for the language whose behaviour you wish to configure. For example, to change the indentation of Ruby, add the following line to your configuration file (): lang.ruby.indent.using_tabs true ## Changing the width of tab characters The width of a tab character depends on the language of the file. To change the width for a specific language, change the tabsize setting for the language. For example, to change the tab size of Ruby files, open the configuration file by pressing , and look for a line like this: lang.ruby.tabsize 2 Then change the number 2 to whatever number you desire, such as 4. ## Converting tab characters Diakonos can convert tabs to spaces when files are opened. Set the convert_tabs configuration option to true: convert_tabs true By default Diakonos does not do this. Tags: tab tabs indent indenting indentation insert space spaces whitespace char character characters width size numberdiakonos-0.9.0/help/undo.dhf000066400000000000000000000003711161735554400157230ustar00rootroot00000000000000# Undoing Use to undo one or more of the most recent changes you've made to the current file. Each file has its own undo history. Use to redo one or more changes that you've undone. Tags: undo undoing mistake back revert redo diakonos-0.9.0/help/uninstall.dhf000066400000000000000000000013231161735554400167650ustar00rootroot00000000000000# Uninstalling Diakonos To uninstall Diakonos, simply run diakonos with an --uninstall switch: diakonos --uninstall Diakonos will list all the files and directories that will be removed from your system, and prompt you for confirmation. Diakonos does not install hidden files that are not shown to you. The only other Diakonos-related files on your system will be under your home directory, inside ~/.diakonos . These are not uninstalled, to allow you to upgrade Diakonos and preserve your settings and customizations. The ~/.diakonos directory can be removed manually, or even edited if you are an advanced user. Tags: install installing installation uninstall uninstalling uninstallation remove removal removingdiakonos-0.9.0/help/welcome.dhf000066400000000000000000000024301161735554400164070ustar00rootroot00000000000000# Welcome to Diakonos! Hello, and welcome to Diakonos! My name is Pistos; I am the author of Diakonos, and I would like to thank you for trying the Diakonos text editor. I have crafted Diakonos with ease of use in mind, so I hope you find it the most easy-to-use console text editor available for Linux. If you have any suggestions, questions or comments, please share your thoughts in the #mathetes channel of the FreeNode IRC network ( http://webchat.freenode.net/?channels=mathetes ). ## Getting Started Press at any time to activate Diakonos' interactive help system. ## Gnome Terminal Gnome Terminal by default has several keyboard shortcuts which conflict with Diakonos. For a smoother Diakonos experience, you should disable as many of these as you are comfortable with. To edit Gnome Terminal's keyboard shortcuts, go to the Edit menu, then select Keyboard Shortcuts. Double click a shortcut and press Backspace to disable it; repeat for each shortcut you wish to disable. ## Removing the Welcome Message To stop this welcome message from appearing, edit the configuration file (by pressing ), add the line "suppress_welcome true", and press to save your change. Tags: diakonos welcome intro introduction getting started starting new newb newbie remove message diakonos-0.9.0/help/word-wrap.dhf000066400000000000000000000012131161735554400166740ustar00rootroot00000000000000# Word Wrap Press and Diakonos will perform basic word wrapping of the paragraph under the cursor. Paragraphs are considered to be delineated by empty lines before and after. The wrap_margin setting of a language controls the column at which word wrapping will occur. For example, to change the margin for text files, set this setting: lang.text.wrap_margin 80 where 80 is the maximum line length allowed. Diakonos does not have any facility to do soft wrapping. Tags: word wrap wrapping hard soft cr carriage return paragraph format formatting margin margins column line length conf config configure configuring set setting settingsdiakonos-0.9.0/install.rb000077500000000000000000000146001161735554400153410ustar00rootroot00000000000000#!/usr/bin/env ruby require './lib/diakonos/version.rb' require 'fileutils' require 'pp' require 'rbconfig' module Diakonos class Installer def strip_prefix( str ) str.sub( %r{^#{Regexp.escape( @prefix )}/*}, '' ) end def initialize( argv = ARGV.dup ) rconfig = RbConfig::CONFIG bang_ruby = File.join( rconfig[ 'bindir' ], rconfig[ 'ruby_install_name' ] ) @shebang = "#!#{bang_ruby}" want_help = false @verbose = false @pretend = false @dest_dir = '/' @lib_dir = nil @conf_dir = nil @bin_dir = nil @doc_dir = nil @prefix = rconfig[ 'prefix' ] @bin_suffix = strip_prefix( rconfig[ 'bindir' ] ) @lib_suffix = strip_prefix( rconfig[ 'sitelibdir' ] ) @conf_dir = rconfig[ 'sysconfdir' ] @doc_suffix = strip_prefix( rconfig[ 'docdir' ].sub( /\$\(PACKAGE\)/, "diakonos-#{Diakonos::VERSION}" ) ) @data_suffix = strip_prefix( File.join(rconfig[ 'datadir' ], 'diakonos') ) while argv.any? arg = argv.shift case arg when '--dest-dir' @dest_dir = argv.shift when '--prefix' @prefix = argv.shift when '--bin-dir' @bin_dir = argv.shift when '--conf-dir' @conf_dir = argv.shift when '--doc-dir' @doc_dir = argv.shift when '--help-dir' @help_dir = argv.shift when '--lib-dir' @lib_dir = argv.shift when '-v', '--verbose' @verbose = true when '-p', '--pretend', '--dry-run' @pretend = true when '-h', '--help' want_help = true end end @bin_dir ||= File.join( @prefix, @bin_suffix ) @lib_dir ||= File.join( @prefix, @lib_suffix ) @doc_dir ||= File.join( @prefix, @doc_suffix ) @help_dir ||= File.join( @prefix, @data_suffix, 'help' ) if want_help print_usage_and_exit end if @pretend puts "(Dry run only; not actually writing any files or directories)" puts end if @verbose && @pretend self.extend FileUtils::DryRun elsif @verbose self.extend FileUtils::Verbose elsif @pretend self.extend FileUtils::NoWrite else self.extend FileUtils end @installed_files = [] @installed_dirs = [] end def print_usage_and_exit puts "#{$0} [options]" puts " -h / --help show usage (can be used with other options to preview paths)" puts " -v / --verbose print each step" puts " -p / --pretend don't actually do anything" puts " --prefix set installation prefix (default #{@prefix})" puts " --dest-dir set installation sandbox dir (default #{@dest_dir})" puts " --bin-dir set executable installation dir (default /#{@bin_suffix})" puts " --doc-dir set documentation installation dir (default /#{@doc_suffix})" puts " --conf-dir set configuration installation dir (default #{@conf_dir})" puts " --lib-dir set library installation dir (default /#{@lib_suffix})" exit 2 end def write_installation_settings installation_file = File.join( @lib_dir, 'diakonos', 'installation.rb' ) dest_file = File.join( @dest_dir, installation_file ) if @verbose puts "Writing installation settings to #{dest_file}" end return if @pretend @installed_files << installation_file File.open( dest_file, 'w' ) do |f| f.puts %| module Diakonos INSTALL_SETTINGS = { :prefix => #{@prefix.dump}, :bin_dir => #{@bin_dir.dump}, :doc_dir => #{@doc_dir.dump}, :help_dir => #{@help_dir.dump}, :conf_dir => #{@conf_dir.dump}, :lib_dir => #{@lib_dir.dump}, :installed => { :files => #{@installed_files.pretty_inspect.strip}, :dirs => #{@installed_dirs.pretty_inspect.strip}, }, } end | end end def cp_( source, dest ) Array( source ).each do |item| if File.directory? item dir = "#{dest}/#{File.basename( item )}" mkdir_ dir cp_ Dir[ "#{item}/*" ], dir else cp item, File.join( @dest_dir, dest ) dest_dir_installed_file = File.expand_path( File.join( @dest_dir, dest, File.basename( item ) ) ) chmod File.stat( item ).mode, dest_dir_installed_file installed_file = File.expand_path( File.join( dest, File.basename( item ) ) ) @installed_files << installed_file end end end def mkdir_( dir ) begin mkdir_p File.join( @dest_dir, dir ), :mode => 0755 @installed_dirs << dir rescue Errno::EEXIST # Don't panic if the directory already exists end end def install_( source, dest ) dest_file = File.join( dest, File.basename( source ) ) dest_dir_file = File.join( @dest_dir, dest_file ) install source, dest_dir_file, :mode => 0755 # Rewrite shebang line command = "sed -i_ '1s|.*|#{@shebang}|' #{dest_dir_file}" if @verbose puts command end if ! @pretend system command rm "#{dest_dir_file}_" end @installed_files << dest_file end def run ::Diakonos.check_ruby_version # Libraries mkdir_ @lib_dir cp_ 'lib/diakonos.rb', @lib_dir dir = "#{@lib_dir}/diakonos" mkdir_ dir lib_files = Dir[ 'lib/diakonos/*' ].reject { |f| f =~ /installation\.rb/ } cp_ lib_files, dir # Configuration mkdir_ @conf_dir cp_ %w( diakonos.conf diakonos-256-colour.conf ), @conf_dir # Executables mkdir_ @bin_dir install_ 'bin/diakonos', @bin_dir # Documentation mkdir_ @help_dir mkdir_ @doc_dir cp_ %w( README.rdoc CHANGELOG LICENCE ), @doc_dir cp_ Dir[ 'help/*' ], @help_dir write_installation_settings end end end installer = Diakonos::Installer.new installer.run puts %{ Diakonos #{Diakonos::VERSION} (#{Diakonos::LAST_MODIFIED}) installed. If Diakonos has been installed with a Linux distro's package manager, uninstall using that package manager. If Diakonos has been installed independently of a package manager, uninstall by running: diakonos --uninstall Thank you for installing Diakonos. Have a stupendous day! :) } diakonos-0.9.0/lib/000077500000000000000000000000001161735554400141105ustar00rootroot00000000000000diakonos-0.9.0/lib/diakonos.rb000077500000000000000000000363371161735554400162630ustar00rootroot00000000000000#!/usr/bin/env ruby # == Diakonos # # A Linux console text editor for the masses. # :title: Diakonos # # Author:: Pistos (irc.freenode.net) # http://diakonos.pist0s.ca/ # Copyright (c) 2004-2011 Pistos # # This software is released under the MIT licence. # See the LICENCE file included with this program, or # http://www.opensource.org/licenses/mit-license.php # require 'curses' require 'open3' require 'thread' require 'English' require 'set' require 'yaml' require 'digest/md5' require 'timeout' require 'diakonos/core-ext/object' require 'diakonos/core-ext/enumerable' require 'diakonos/core-ext/regexp' require 'diakonos/core-ext/hash' require 'diakonos/core-ext/string' require 'diakonos/core-ext/fixnum' require 'diakonos/core-ext/bignum' require 'diakonos/buffer-hash' require 'diakonos/sized-array' require 'diakonos/version' require 'diakonos/installation' require 'diakonos/about' require 'diakonos/buffer-management' require 'diakonos/config' require 'diakonos/cursor' require 'diakonos/functions' require 'diakonos/functions/basics' require 'diakonos/functions/bookmarking' require 'diakonos/functions/buffers' require 'diakonos/functions/clipboard' require 'diakonos/functions/cursor' require 'diakonos/functions/grepping' require 'diakonos/functions/indentation' require 'diakonos/functions/readline' require 'diakonos/functions/search' require 'diakonos/functions/selection' require 'diakonos/functions/sessions' require 'diakonos/functions/shell' require 'diakonos/functions/tags' require 'diakonos/functions/text-manipulation' require 'diakonos/functions-deprecated' require 'diakonos/help' require 'diakonos/display' require 'diakonos/display/format' require 'diakonos/grep' require 'diakonos/hooks' require 'diakonos/interaction' require 'diakonos/keying' require 'diakonos/logging' require 'diakonos/list' require 'diakonos/search' require 'diakonos/sessions' require 'diakonos/text-mark' require 'diakonos/bookmark' require 'diakonos/ctag' require 'diakonos/finding' require 'diakonos/buffer' require 'diakonos/buffer/bookmarking' require 'diakonos/buffer/cursor' require 'diakonos/buffer/delete' require 'diakonos/buffer/display' require 'diakonos/buffer/indentation' require 'diakonos/buffer/file' require 'diakonos/buffer/searching' require 'diakonos/buffer/selection' require 'diakonos/buffer/undo' require 'diakonos/clipboard' require 'diakonos/clipboard-klipper' require 'diakonos/clipboard-klipper-dbus' require 'diakonos/clipboard-xclip' require 'diakonos/extension' require 'diakonos/extension-set' require 'diakonos/key-map' require 'diakonos/mode' require 'diakonos/readline' require 'diakonos/readline/functions' require 'diakonos/vendor/fuzzy_file_finder' module Diakonos DONT_ADJUST_ROW = false ADJUST_ROW = true PROMPT_OVERWRITE = true DONT_PROMPT_OVERWRITE = false QUIET = true NOISY = false AFTER_CHAR = true ON_CHAR = false INCLUSIVE = true NOT_INCLUSIVE = false DEFAULT_TAB_SIZE = 8 FORCE_REVERT = true ASK_REVERT = false ASK_REPLACEMENT = true NO_REPLACEMENT = nil CASE_SENSITIVE = true CASE_INSENSITIVE = false LANG_TEXT = 'text' class Diakonos attr_reader :diakonos_home, :script_dir, :clipboard, :list_filename, :hooks, :indenters, :indenters_next_line, :unindenters, :closers, :functions_last, :there_was_non_movement, :do_display, :testing, :buffers include ::Diakonos::Functions def initialize( argv = [] ) @diakonos_home = File.expand_path( ( ENV[ 'HOME' ] || '' ) + '/.diakonos' ) mkdir @diakonos_home @script_dir = "#{@diakonos_home}/scripts" mkdir @script_dir @extensions = ExtensionSet.new( File.join( @diakonos_home, 'extensions' ) ) initialize_session @files = Array.new @read_only_files = Array.new @config_filename = nil parse_options argv init_help @debug = File.new( File.join( @diakonos_home, 'debug.log' ), 'w' ) @list_filename = File.join( @diakonos_home, 'listing.txt' ) @diff_filename = File.join( @diakonos_home, 'text.diff' ) @help_filename = File.join( @help_dir, 'about-help.dhf' ) @error_filename = File.join( @diakonos_home, 'diakonos.err' ) @about_filename = File.join( @diakonos_home, 'about.dhf' ) @win_main = nil @win_context = nil @win_status = nil @win_interaction = nil @win_line_numbers = nil @buffers = Array.new load_configuration @quitting = false @x = 0 @y = 0 @buffer_stack = Array.new @buffer_current = nil @cursor_stack = Array.new @cursor_stack_pointer = nil @bookmarks = Hash.new @macro_history = nil @macro_input_history = nil @macros = Hash.new @functions_last = SizedArray.new(2) @playing_macro = false @display_mutex = Mutex.new @display_queue_mutex = Mutex.new @display_queue = nil @do_display = true @iline_mutex = Mutex.new @tag_stack = Array.new @last_search_regexps = nil @iterated_choice = nil @choice_iterations = 0 @there_was_non_movement = false @status_vars = Hash.new # Readline histories @rlh_general = Array.new @rlh_files = Array.new @rlh_search = Array.new @rlh_shell = Array.new @rlh_help = Array.new @rlh_sessions = Array.new @hooks = { :after_buffer_switch => [], :after_open => [], :after_save => [], :after_startup => [], } end def mkdir( dir ) if ! FileTest.exists?( dir ) Dir.mkdir dir end end def parse_options( argv ) @post_load_script = "" while argv.length > 0 arg = argv.shift case arg when '-c', '--config' @config_filename = argv.shift if @config_filename.nil? print_usage exit 1 end when '-e', '--execute' post_load_script = argv.shift if post_load_script.nil? print_usage exit 1 else @post_load_script << "\n#{post_load_script}" end when '-h', '--help' print_usage exit 1 when '-m', '--open-matching' regexp = argv.shift files = `egrep -rl '#{regexp}' *`.split( /\n/ ) if files.any? @files.concat( files.map { |f| session_file_hash_for f } ) script = "\nfind '#{regexp}', case_sensitive: true" @post_load_script << script end when '-ro' filename = argv.shift if filename.nil? print_usage exit 1 else h = session_file_hash_for( filename ) h[ 'read_only' ] = true @read_only_files.push h end when '-s', '--load-session' @session_to_load = session_filepath_for( argv.shift ) when '--test', '--testing' @testing = true when '--uninstall' uninstall when '--uninstall-without-confirmation' uninstall false when '--version' puts "Diakonos #{::Diakonos::VERSION} (#{::Diakonos::LAST_MODIFIED})" exit 0 else # a name of a file to open @files.push session_file_hash_for( arg ) end end end def print_usage puts "Usage: #{$0} [options] [file] [file...]" puts "\t--help\tDisplay usage" puts "\t-c \tLoad this config file instead of ~/.diakonos/diakonos.conf" puts "\t-e, --execute \tExecute Ruby code (such as Diakonos commands) after startup" puts "\t-m, --open-matching \tOpen all matching files under current directory" puts "\t-ro \tLoad file as read-only" puts "\t-s, --load-session \tLoad a session" puts "\t--uninstall[-without-confirmation]\tUninstall Diakonos" end def clear_non_movement_flag @there_was_non_movement = false end # ----------------------------------------------------------------------- def start require 'diakonos/window' initialize_display @files.each do |file| @buffers << Buffer.new( file ) end @files = [] @read_only_files.each do |file| @buffers << Buffer.new( file ) end if ! @testing session_buffers = session_startup end session_buffer_number = @session[ 'buffer_current' ] || 1 @files.each do |file_info| @buffers << Buffer.new( file_info ) end if @buffers.empty? @buffers << Buffer.new end @buffers.each do |buffer| buffer.reset_display end if ENV[ 'COLORTERM' ] == 'gnome-terminal' help_key = 'Shift-F1' else help_key = 'F1' end set_iline "Diakonos #{VERSION} (#{LAST_MODIFIED}) #{help_key} for help F12 to configure Ctrl-Q to quit" scripts = @extensions.scripts + Dir[ "#{@script_dir}/*" ] scripts.each do |script| begin require script rescue Exception => e show_exception( e, [ "There is a syntax error in the script.", "An invalid hook name was used." ] ) end end @hooks.each do |hook_name, hook| hook.sort { |a,b| a[ :priority ] <=> b[ :priority ] } end if session_buffers session_buffers.each do |buffer| close_buffer buffer end end if @post_load_script eval @post_load_script end run_hook_procs :after_startup if ! switch_to_buffer_number( session_buffer_number ) debug_log "Failed to switch to buffer #{session_buffer_number.inspect}" switch_to_buffer_number 1 end @buffers.each do |b| run_hook_procs :after_open, b b.cursor_to( b.last_row, b.last_col, Buffer::DONT_DISPLAY ) end buffer_current.cursor_to( buffer_current.last_row, buffer_current.last_col, Buffer::DONT_DISPLAY ) if @config_problems.any? File.open( @error_filename, "w" ) do |f| f.puts "There are #{@config_problems.size} problems with the configuration file(s):" @config_problems.each do |p| f.puts p end end open_file @error_filename end if ! @testing && ! @settings[ 'suppress_welcome' ] open_file "#{@help_dir}/welcome.dhf" else conflict_regexp_source = '^<{4,}' if seek(conflict_regexp_source) find conflict_regexp_source end end begin # Main keyboard loop. while ! @quitting process_keystroke @win_main.refresh end rescue SignalException => e debug_log "Terminated by signal (#{e.message})" end cleanup_display cleanup_session @debug.close end def uninstall( confirm = true ) inst = ::Diakonos::INSTALL_SETTINGS[ :installed ] if confirm puts inst[ :files ].sort.join( "\n" ) puts puts inst[ :dirs ].sort.map { |d| "#{d}/" }.join( "\n" ) puts puts "The above files will be removed. The above directories will be removed if they are empty. Proceed? (y/n)" answer = $stdin.gets case answer when /^y/i puts "Deleting..." else puts "Uninstallation aborted." exit 1 end end require 'fileutils' inst[ :files ].each do |f| FileUtils.rm f end inst[ :dirs ].sort { |d1,d2| d2.length <=> d1.length }.each do |d| begin FileUtils.rmdir d rescue Errno::ENOTEMPTY end if File.exists? d $stderr.puts "(#{d} not removed)" end end exit 0 end def get_language_from_name( name ) @filemasks.each do |language,filemask| if name =~ filemask return language end end nil end def get_language_from_shabang( first_line ) @bangmasks.each do |language,bangmask| if first_line =~ bangmask return language end end nil end def show_exception( e, probable_causes = [ "Unknown" ] ) begin File.open( @error_filename, "w" ) do |f| f.puts "Diakonos Error:" f.puts f.puts "#{e.class}: #{e.message}" f.puts f.puts "Probable Causes:" f.puts probable_causes.each do |pc| f.puts "- #{pc}" end f.puts f.puts "----------------------------------------------------" f.puts "If you can reproduce this error, please report it at" f.puts "https://github.com/Pistos/diakonos/issues !" f.puts "----------------------------------------------------" f.puts e.backtrace end open_file @error_filename rescue Exception => e2 debug_log "EXCEPTION: #{e.message}" debug_log "\t#{e.backtrace}" end end def start_recording_macro( name = nil ) return if @macro_history @macro_name = name @macro_history = Array.new @macro_input_history = Array.new set_iline "Started macro recording." end def stop_recording_macro @macro_history.pop # Remove the stop_recording_macro command itself @macros[ @macro_name ] = [ @macro_history, @macro_input_history ] @macro_history = nil @macro_input_history = nil set_iline "Stopped macro recording." end def load_tags @tags = Hash.new if buffer_current && buffer_current.name path = File.expand_path( File.dirname( buffer_current.name ) ) tagfile = path + "/tags" else tagfile = "./tags" end if ! FileTest.exists? tagfile set_iline "(tags file not found)" else IO.foreach( tagfile ) do |line_| line = line_.chomp # \t\t\t tag, file, command, kind, rest = line.split( /\t/ ) command.gsub!( /;"$/, "" ) if command =~ /^\/.*\/$/ command = command[ 1...-1 ] end @tags[ tag ] ||= Array.new @tags[ tag ].push CTag.new( file, command, kind, rest ) end end end def escape_quotes( str ) temp = '' str.each_byte do |b| if b == 39 temp << 39 temp << 92 temp << 39 end temp << b end temp end # @return [Array] the filename and line number parsed def parse_filename_and_line_number( s ) if( # Ruby s =~ /from (.+):(\d+)/ || # Python s =~ /File "(.+)", line (\d+)/ || # Perl s =~ /at (.+) line (\d+)/ || # generic s =~ /^(.+):(\d+)/ ) [ $1, ( $2.to_i - 1 ) ] else [ s, nil ] end end end end ::Diakonos.check_ruby_version if __FILE__ == $PROGRAM_NAME $diakonos = Diakonos::Diakonos.new( ARGV ) $diakonos.start end diakonos-0.9.0/lib/diakonos/000077500000000000000000000000001161735554400157175ustar00rootroot00000000000000diakonos-0.9.0/lib/diakonos/about.rb000066400000000000000000000025561161735554400173660ustar00rootroot00000000000000module Diakonos class Diakonos def about_write File.open( @about_filename, "w" ) do |f| inst = ::Diakonos::INSTALL_SETTINGS configs = @configs.map { |h| source = h[:source] ? "(included by #{h[:source]})" : '' "#{h[:filename]}\t#{source}" }.join("\n") ext_loaded = @extensions.loaded_extensions.sort_by { |e| e.name.downcase }.map { |e| %{ ### #{e.name} #{e.version} #{e.description} }.strip }.join( "\n\n" ) ext_not_loaded = @extensions.not_loaded_extensions.sort.map { |e| "### #{e} (NOT LOADED)" }.join( "\n" ) f.puts %{ # About Diakonos Licence: MIT Licence Copyright: Copyright (c) 2004-#{ Time.now.year } Pistos ## Version Version: #{ ::Diakonos::VERSION } Code Date: #{ ::Diakonos::LAST_MODIFIED } Install Time: #{ File.mtime( File.join( inst[ :lib_dir ], 'diakonos', 'installation.rb' ) ) } ## Paths Home dir: #{ @diakonos_home } ### Installation Prefix: #{ inst[ :prefix ] } Executable dir: #{ inst[ :bin_dir ] } Help dir: #{ inst[ :help_dir ] } System config dir: #{ inst[ :conf_dir ] } System library dir: #{ inst[ :lib_dir ] } ### Configuration Files #{ configs } ## Extensions #{ ext_loaded } #{ ext_not_loaded } }.strip end end end enddiakonos-0.9.0/lib/diakonos/bookmark.rb000066400000000000000000000017061161735554400200550ustar00rootroot00000000000000module Diakonos class Bookmark attr_reader :buffer, :row, :col, :name def initialize( buffer, row, col, name = nil ) @buffer = buffer @row = row @col = col @name = name end def == (other) return false if other.nil? ( @buffer == other.buffer and @row == other.row and @col == other.col ) end def <=> (other) return nil if other.nil? comparison = ( $diakonos.buffer_to_number( @buffer ) <=> $diakonos.buffer_to_number( other.buffer ) ) return comparison if comparison != 0 comparison = ( @row <=> other.row ) return comparison if comparison != 0 @col <=> other.col end def < (other) ( ( self <=> other ) < 0 ) end def > (other) ( ( self <=> other ) > 0 ) end def shift( row_inc, col_inc ) row += row_inc col += col_inc end def to_s "[#{@name}|#{@buffer.name}:#{@row+1},#{@col+1}]" end end enddiakonos-0.9.0/lib/diakonos/buffer-hash.rb000066400000000000000000000015501161735554400204370ustar00rootroot00000000000000# A Hash which is iterated in insertion order. # Keys are assumed to be paths; these paths are expanded on read and write. class BufferHash < Hash def initialize @keys_ = [] end def [] ( key ) super File.expand_path( key.to_s ) end def []= ( key, value ) key = File.expand_path( key.to_s ) if not @keys_.include?( key ) @keys_ << key end super key, value end def each @keys_.each do |key| yield key, self[ key ] end end def each_key @keys_.each do |key| yield key end end def each_value @keys_.each do |key| yield self[ key ] end end def clear @keys_ = [] super end def delete( key ) @keys_.delete key super end def keys @keys_.dup end def values @keys_.map { |key| self[ key ] } end def length @keys_.length end end diakonos-0.9.0/lib/diakonos/buffer-management.rb000066400000000000000000000027221161735554400216320ustar00rootroot00000000000000module Diakonos class Diakonos attr_reader :buffer_current # @param [Buffer] the Buffer to switch to # @return [Boolean] true iff the buffer was successfully switched to def switch_to( buffer ) return false if buffer.nil? @buffer_stack -= [ @buffer_current ] if @buffer_current @buffer_stack.push @buffer_current end @buffer_current = buffer @session[ 'buffer_current' ] = buffer_to_number( buffer ) run_hook_procs( :after_buffer_switch, buffer ) update_status_line update_context_line display_buffer buffer true end # @param [Fixnum] buffer_number should be 1-based, not zero-based. # @return nil if no such buffer exists. def buffer_number_to_name( buffer_number ) return nil if buffer_number < 1 b = @buffers[ buffer_number - 1 ] if b b.name end end # @return [Fixnum] 1-based, not zero-based. # @return nil if no such buffer exists. def buffer_to_number( buffer ) i = @buffers.index( buffer ) if i i + 1 end end def show_buffer_file_diff( buffer = @buffer_current ) current_text_file = @diakonos_home + '/current-buffer' buffer.save_copy( current_text_file ) `#{@settings[ 'diff_command' ]} #{current_text_file} #{buffer.name} > #{@diff_filename}` diff_buffer = open_file( @diff_filename ) yield diff_buffer close_buffer diff_buffer end end enddiakonos-0.9.0/lib/diakonos/buffer.rb000066400000000000000000000451021161735554400175170ustar00rootroot00000000000000module Diakonos class Buffer attr_reader :name, :original_language, :changing_selection, :read_only, :tab_size, :selection_mode attr_writer :desired_column, :read_only TYPING = true STOPPED_TYPING = true STILL_TYPING = false NO_SNAPSHOT = true DO_DISPLAY = true DONT_DISPLAY = false READ_ONLY = true READ_WRITE = false ROUND_DOWN = false ROUND_UP = true PAD_END = true DONT_PAD_END = false MATCH_CLOSE = true MATCH_ANY = false START_FROM_BEGINNING = -1 DO_PITCH_CURSOR = true DONT_PITCH_CURSOR = false STRIP_LINE = true DONT_STRIP_LINE = false USE_INDENT_IGNORE = true DONT_USE_INDENT_IGNORE = false WORD_REGEXP = /\w+/ # Set name to nil to create a buffer that is not associated with a file. # @param [Hash] options # @option options [String] 'filepath' # A file path (which is expanded internally) # @option options [Boolean] 'read_only' (READ_WRITE) # Whether the buffer should be protected from modification # @option options [Hash] 'cursor' # A Hash containing 'row' and/or 'col' indicating where the cursor should # initially be placed. Defaults: 0 and 0 # @option options [Hash] 'display' # A Hash containing 'top_line' and 'left_column' indicating where the view # should be positioned in the file. Defaults: 0 and 0 # @see READ_WRITE # @see READ_ONLY def initialize( options = {} ) @name = options[ 'filepath' ] @modified = false @last_modification_check = Time.now @buffer_states = Array.new @cursor_states = Array.new if @name.nil? @lines = Array.new @lines[ 0 ] = "" else @name = File.expand_path( @name ) if FileTest.exists? @name @lines = IO.readlines( @name ) if ( @lines.length == 0 ) or ( @lines[ -1 ][ -1..-1 ] == "\n" ) @lines.push "" end @lines = @lines.collect do |line| line.chomp end else @lines = Array.new @lines[ 0 ] = "" end end @current_buffer_state = 0 options[ 'display' ] ||= Hash.new @top_line = options[ 'display' ][ 'top_line' ] || 0 @left_column = options[ 'display' ][ 'left_column' ] || 0 @desired_column = @left_column @mark_anchor = nil @text_marks = Hash.new @selection_mode = :normal @last_search_regexps = Array( options['last_search_regexps'] ).map { |r| Regexp.new(r) } @highlight_regexp = nil @last_search = nil @changing_selection = false @typing = false options[ 'cursor' ] ||= Hash.new @last_col = options[ 'cursor' ][ 'col' ] || 0 @last_row = options[ 'cursor' ][ 'row' ] || 0 @last_screen_y = @last_row - @top_line @last_screen_x = @last_col - @left_column @last_screen_col = @last_screen_x @read_only = options[ 'read_only' ] || READ_WRITE @bookmarks = Array.new @lang_stack = Array.new configure if @settings[ "convert_tabs" ] tabs_subbed = false @lines.collect! do |line| new_line = line.expand_tabs( @tab_size ) tabs_subbed = ( tabs_subbed or new_line != line ) # Return value for collect: new_line end @modified = ( @modified or tabs_subbed ) if tabs_subbed $diakonos.set_iline "(spaces substituted for tab characters)" end end @buffer_states[ @current_buffer_state ] = @lines @cursor_states[ @current_buffer_state ] = [ @last_row, @last_col ] end def configure( language = ( $diakonos.get_language_from_shabang( @lines[ 0 ] ) or $diakonos.get_language_from_name( @name ) or LANG_TEXT ) ) reset_display set_language language @original_language = @language end def reset_display @win_main = $diakonos.win_main @win_line_numbers = $diakonos.win_line_numbers end def set_language( language ) @settings = $diakonos.settings @language = language @surround_pairs = $diakonos.surround_pairs[ @language ] @token_regexps = $diakonos.token_regexps[ @language ] @close_token_regexps = $diakonos.close_token_regexps[ @language ] @token_formats = $diakonos.token_formats[ @language ] @indenters = $diakonos.indenters[ @language ] @indenters_next_line = $diakonos.indenters_next_line[ @language ] @unindenters = $diakonos.unindenters[ @language ] @preventers = @settings[ "lang.#{@language}.indent.preventers" ] @closers = $diakonos.closers[ @language ] || Hash.new @auto_indent = @settings[ "lang.#{@language}.indent.auto" ] @indent_size = ( @settings[ "lang.#{@language}.indent.size" ] || 4 ) @indent_roundup = @settings[ "lang.#{@language}.indent.roundup" ].nil? ? true : @settings[ "lang.#{@language}.indent.roundup" ] @indent_closers = @settings[ "lang.#{@language}.indent.closers" ].nil? ? false : @settings[ "lang.#{@language}.indent.closers" ] @default_formatting = ( @settings[ "lang.#{@language}.format.default" ] || Curses::A_NORMAL ) @selection_formatting = ( @settings[ "lang.#{@language}.format.selection" ] || Curses::A_REVERSE ) @indent_ignore_charset = ( @settings[ "lang.#{@language}.indent.ignore.charset" ] || "" ) @tab_size = ( @settings[ "lang.#{@language}.tabsize" ] || DEFAULT_TAB_SIZE ) end def [] ( arg ) @lines[ arg ] end def == (other) return false if other.nil? @name == other.name end def length @lines.length end def to_a @lines.dup end def modified? @modified end def nice_name @name || @settings[ "status.unnamed_str" ] end def replace_char( c ) row = @last_row col = @last_col take_snapshot TYPING @lines[ row ][ col ] = c set_modified end def insert_char( c ) row = @last_row col = @last_col take_snapshot( TYPING ) line = @lines[ row ] @lines[ row ] = line[ 0...col ] + c.chr + line[ col..-1 ] set_modified end def insert_string( str ) row = @last_row col = @last_col take_snapshot( TYPING ) line = @lines[ row ] @lines[ row ] = line[ 0...col ] + str + line[ col..-1 ] set_modified end def surround( text, parenthesis ) pattern, pair = @surround_pairs.select { |r, p| parenthesis =~ r }.to_a[ 0 ] if pair.nil? $diakonos.set_iline "No matching parentheses pair found." nil else pair.map! do |paren| parenthesis.gsub( pattern, paren ) end pair[ 0 ] + text.join( "\n" ) + pair[ 1 ] end end def join_lines_upward( row = @last_row, strip = DONT_STRIP_LINE ) return false if row == 0 take_snapshot line = @lines.delete_at( row ) old_line = @lines[ row-1 ] new_x_pos = old_line.length if strip line.strip! # Only prepend a space if the line above isn't empty. if ! old_line.strip.empty? line = ' ' + line new_x_pos += 1 end end @lines[ row-1 ] << line cursor_to( row-1, new_x_pos ) set_modified end def join_lines( row = @last_row, strip = DONT_STRIP_LINE ) take_snapshot( TYPING ) next_line = @lines.delete_at( row + 1 ) return false if next_line.nil? if strip next_line = ' ' + next_line.strip end @lines[ row ] << next_line set_modified end def close_code line = @lines[ @last_row ] @closers.each_value do |h| h[ :regexp ] =~ line lm = Regexp.last_match if lm str = case h[ :closer ] when String if lm[ 1 ].nil? h[ :closer ] else lm[ 1 ].gsub( Regexp.new( "(#{ Regexp.escape( lm[1] ) })" ), h[ :closer ] ) end when Proc h[ :closer ].call( lm ).to_s end r, c = @last_row, @last_col paste str, !TYPING, @indent_closers cursor_to r, c if /%_/ === str find [/%_/], direction: :down, replacement: '', auto_choice: CHOICE_YES_AND_STOP end end end end def collapse_whitespace if selection_mark remove_selection DONT_DISPLAY end line = @lines[ @last_row ] head = line[ 0...@last_col ] tail = line[ @last_col..-1 ] new_head = head.sub( /\s+$/, '' ) new_line = new_head + tail.sub( /^\s+/, ' ' ) if new_line != line take_snapshot( TYPING ) @lines[ @last_row ] = new_line cursor_to( @last_row, @last_col - ( head.length - new_head.length ) ) set_modified end end def columnize( delimiter = /=>?|:|,/, num_spaces_padding = 1 ) take_snapshot lines = selected_lines column_width = 0 lines.each do |line| pos = ( line =~ delimiter ) if pos column_width = [ pos, column_width ].max end end padding = ' ' * num_spaces_padding one_modified = false lines.each do |line| old_line = line.dup if line =~ /^(.+?)(#{delimiter.source})(.*)$/ pre = $1 del = $2 post = $3 if pre !~ /\s$/ del = " #{del}" end if post !~ /^\s/ del = "#{del} " end del.sub!( /^\s+/, ' ' * num_spaces_padding ) del.sub!( /\s+$/, ' ' * num_spaces_padding ) line.replace( ( "%-#{column_width}s" % pre ) + del + post ) end one_modified ||= ( line != old_line ) end if one_modified set_modified end end def comment_out take_snapshot one_modified = false selected_lines.each do |line| next if line.strip.empty? old_line = line.dup line.gsub!( /^(\s*)/, "\\1" + @settings[ "lang.#{@language}.comment_string" ].to_s ) line << @settings[ "lang.#{@language}.comment_close_string" ].to_s one_modified ||= ( line != old_line ) end if one_modified set_modified end end def uncomment take_snapshot comment_string = Regexp.escape( @settings[ "lang.#{@language}.comment_string" ].to_s ) comment_close_string = Regexp.escape( @settings[ "lang.#{@language}.comment_close_string" ].to_s ) one_modified = false selected_lines.each do |line| old_line = line.dup line.gsub!( /^(\s*)#{comment_string}/, "\\1" ) line.gsub!( /#{comment_close_string}$/, '' ) one_modified ||= ( line != old_line ) end if one_modified set_modified end end def carriage_return take_snapshot row = @last_row col = @last_col @lines = @lines[ 0...row ] + [ @lines[ row ][ 0...col ] ] + [ @lines[ row ][ col..-1 ] ] + @lines[ (row+1)..-1 ] cursor_to( row + 1, 0 ) parsed_indent if @auto_indent set_modified end def line_at( y ) row = @top_line + y if row < 0 nil else @lines[ row ] end end def current_line @lines[ @last_row ] end # Returns true iff the given column, x, is less than the length of the given line, y. def in_line( x, y ) x + @left_column < line_at( y ).length end # Translates the window column, x, to a buffer-relative column index. def column_of( x ) @left_column + x end # Translates the window row, y, to a buffer-relative row index. def row_of( y ) @top_line + y end # Returns nil if the row is off-screen. def row_to_y( row ) return nil if row.nil? y = row - @top_line y = nil if ( y < 0 ) or ( y > @top_line + $diakonos.main_window_height - 1 ) y end # Returns nil if the column is off-screen. def column_to_x( col ) return nil if col.nil? x = col - @left_column x = nil if ( x < 0 ) or ( x > @left_column + Curses::cols - 1 ) x end def current_row @last_row end def current_column @last_col end def pan_view_to( left_column, do_display = DO_DISPLAY ) @left_column = [ left_column, 0 ].max record_mark_start_and_end display if do_display end # Returns the amount the view was actually panned. def pan_view( x = 1, do_display = DO_DISPLAY ) old_left_column = @left_column pan_view_to( @left_column + x, do_display ) @left_column - old_left_column end def pitch_view_to( new_top_line, do_pitch_cursor = DONT_PITCH_CURSOR, do_display = DO_DISPLAY ) old_top_line = @top_line if new_top_line < 0 @top_line = 0 elsif new_top_line + $diakonos.main_window_height > @lines.length @top_line = [ @lines.length - $diakonos.main_window_height, 0 ].max else @top_line = new_top_line end old_row = @last_row old_col = @last_col changed = ( @top_line - old_top_line ) if changed != 0 && do_pitch_cursor @last_row += changed end height = [ $diakonos.main_window_height, @lines.length ].min @last_row = @last_row.fit( @top_line, @top_line + height - 1 ) if @last_row - @top_line < @settings[ "view.margin.y" ] @last_row = @top_line + @settings[ "view.margin.y" ] @last_row = @last_row.fit( @top_line, @top_line + height - 1 ) elsif @top_line + height - 1 - @last_row < @settings[ "view.margin.y" ] @last_row = @top_line + height - 1 - @settings[ "view.margin.y" ] @last_row = @last_row.fit( @top_line, @top_line + height - 1 ) end @last_col = @last_col.fit( @left_column, [ @left_column + Curses::cols - 1, @lines[ @last_row ].length ].min ) @last_screen_y = @last_row - @top_line @last_screen_x = tab_expanded_column( @last_col, @last_row ) - @left_column record_mark_start_and_end if changed != 0 if ! @changing_selection && selecting? remove_selection DONT_DISPLAY end highlight_matches if $diakonos.there_was_non_movement $diakonos.push_cursor_state( old_top_line, old_row, old_col ) end end display if do_display changed end # Returns the amount the view was actually pitched. def pitch_view( y = 1, do_pitch_cursor = DONT_PITCH_CURSOR, do_display = DO_DISPLAY ) pitch_view_to( @top_line + y, do_pitch_cursor, do_display ) end def wrap_paragraph start_row = end_row = cursor_row = @last_row cursor_col = @last_col until start_row == 0 || @lines[ start_row - 1 ].strip == '' start_row -= 1 end until end_row == @lines.size || @lines[ end_row ].strip == '' end_row += 1 end lines = [] line = '' words = @lines[ start_row...end_row ].join( ' ' ).scan( /\S+/ ) words.each do |word| if word =~ /^[a-z']+[.!?]$/ word = "#{word} " end if line.length + word.length + 1 > ( @settings[ "lang.#{@language}.wrap_margin" ] || 80 ) lines << line.strip line = '' end line << " #{word}" end line.strip! if ! line.empty? lines << line end if @lines[ start_row...end_row ] != lines take_snapshot @lines[ start_row...end_row ] = lines set_modified cursor_to start_row + lines.length, lines[-1].length end end def context retval = Array.new row = @last_row clevel = indentation_level( row ) while row > 0 && clevel < 0 row = row - 1 clevel = indentation_level( row ) end clevel = 0 if clevel < 0 while row > 0 row = row - 1 line = @lines[ row ] if ! line.strip.empty? && ( line !~ @settings[ "lang.#{@language}.context.ignore" ] ) level = indentation_level( row ) if level < clevel and level > -1 retval.unshift line clevel = level break if clevel == 0 end end end retval end def set_type( type ) return false if type.nil? configure( type ) display true end def word_under_cursor pos = word_under_cursor_pos return if pos.nil? col1 = pos[ 0 ][ 1 ] col2 = pos[ 1 ][ 1 ] @lines[ @last_row ][ col1...col2 ] end def word_under_cursor_pos( options = {} ) or_after = options[:or_after] @lines[ @last_row ].scan( WORD_REGEXP ) do |match_text| last_match = Regexp.last_match if ( last_match.begin( 0 ) <= @last_col && @last_col < last_match.end( 0 ) || or_after && last_match.begin(0) > @last_col ) return [ [ @last_row, last_match.begin( 0 ) ], [ @last_row, last_match.end( 0 ) ], ] end end nil end def word_before_cursor word = nil @lines[ @last_row ].scan( WORD_REGEXP ) do |match_text| last_match = Regexp.last_match if last_match.begin( 0 ) <= @last_col && @last_col <= last_match.end( 0 ) word = match_text break end end word end # TODO word_before_cursor_pos # Returns an array of lines of the current paragraph. def paragraph_under_cursor ( first, _ ), ( last, _ ) = paragraph_under_cursor_pos @lines[ first..last ] end # Returns the coordinates of the first and last line of the current # paragraph. def paragraph_under_cursor_pos if @lines[ @last_row ] =~ /^\s*$/ return [ [ @last_row, 0 ], [ @last_row, @lines[ @last_row ].length - 1 ] ] end upper_boundary = 0 lower_boundary = @lines.size - 1 @last_row.downto( 0 ) do |i| line = @lines[ i ] if line =~ /^\s*$/ upper_boundary = i + 1 break end end @last_row.upto( @lines.size - 1 ) do |i| line = @lines[ i ] if line =~ /^\s*$/ lower_boundary = i - 1 break end end [ [ upper_boundary, 0 ], [ lower_boundary, @lines[ lower_boundary ].length - 1 ] ] end # TODO paragraph_before_cursor(_pos)? def words( filter_regexp = nil ) w = @lines.join( ' ' ).scan( WORD_REGEXP ) filter_regexp ? w.grep( filter_regexp ) : w end end end diakonos-0.9.0/lib/diakonos/buffer/000077500000000000000000000000001161735554400171705ustar00rootroot00000000000000diakonos-0.9.0/lib/diakonos/buffer/bookmarking.rb000066400000000000000000000021211161735554400220140ustar00rootroot00000000000000module Diakonos class Buffer def go_to_next_bookmark cur_pos = Bookmark.new( self, @last_row, @last_col ) next_bm = @bookmarks.find do |bm| bm > cur_pos end if next_bm cursor_to( next_bm.row, next_bm.col, DO_DISPLAY ) end end def go_to_previous_bookmark cur_pos = Bookmark.new( self, @last_row, @last_col ) # There's no reverse_find method, so, we have to do this manually. prev = nil @bookmarks.reverse_each do |bm| if bm < cur_pos prev = bm break end end if prev cursor_to( prev.row, prev.col, DO_DISPLAY ) end end def toggle_bookmark bookmark = Bookmark.new( self, @last_row, @last_col ) existing = @bookmarks.find do |bm| bm == bookmark end if existing @bookmarks.delete existing $diakonos.set_iline "Bookmark #{existing.to_s} deleted." else @bookmarks.push bookmark @bookmarks.sort $diakonos.set_iline "Bookmark #{bookmark.to_s} set." end end end enddiakonos-0.9.0/lib/diakonos/buffer/cursor.rb000066400000000000000000000211551161735554400210360ustar00rootroot00000000000000module Diakonos class Buffer attr_reader :last_col, :last_row, :last_screen_x, :last_screen_y, :last_screen_col # Returns true iff the cursor changed positions in the buffer. def cursor_to( row, col, do_display = DONT_DISPLAY, stopped_typing = STOPPED_TYPING, adjust_row = ADJUST_ROW ) old_last_row = @last_row old_last_col = @last_col row = row.fit( 0, @lines.length - 1 ) if col < 0 if adjust_row if row > 0 row = row - 1 col = @lines[ row ].length else col = 0 end else col = 0 end elsif col > @lines[ row ].length if adjust_row if row < @lines.length - 1 row = row + 1 col = 0 else col = @lines[ row ].length end else col = @lines[ row ].length end end if adjust_row @desired_column = col else goto_col = [ @desired_column, @lines[ row ].length ].min if col < goto_col col = goto_col end end new_col = tab_expanded_column( col, row ) view_changed = show_character( row, new_col ) @last_screen_y = row - @top_line @last_screen_x = new_col - @left_column @typing = false if stopped_typing @last_row = row @last_col = col @last_screen_col = new_col record_mark_start_and_end removed = false if not @changing_selection and selecting? remove_selection( DONT_DISPLAY ) removed = true end old_pair = @text_marks[ :pair ] if @settings[ 'view.pairs.highlight' ] highlight_pair elsif old_pair clear_pair_highlight end highlight_changed = old_pair != @text_marks[ :pair ] if removed || ( do_display && ( selecting? || view_changed || highlight_changed ) ) display else $diakonos.display_mutex.synchronize do @win_main.setpos( @last_screen_y, @last_screen_x ) end end $diakonos.update_status_line $diakonos.update_context_line ( @last_row != old_last_row || @last_col != old_last_col ) end def cursor_to_eof cursor_to( @lines.length - 1, @lines[ -1 ].length, DO_DISPLAY ) end def cursor_to_bol row = @last_row case @settings[ "bol_behaviour" ] when BOL_ZERO col = 0 when BOL_FIRST_CHAR col = ( ( @lines[ row ] =~ /\S/ ) or 0 ) when BOL_ALT_ZERO if @last_col == 0 col = ( @lines[ row ] =~ /\S/ ) else col = 0 end #when BOL_ALT_FIRST_CHAR else first_char_col = ( ( @lines[ row ] =~ /\S/ ) or 0 ) if @last_col == first_char_col col = 0 else col = first_char_col end end cursor_to( row, col, DO_DISPLAY ) end def cursor_to_eol y = @win_main.cury end_col = line_at( y ).length last_char_col = line_at( y ).rstrip.length case @settings[ 'eol_behaviour' ] when EOL_END col = end_col when EOL_LAST_CHAR col = last_char_col when EOL_ALT_LAST_CHAR if @last_col == last_char_col col = end_col else col = last_char_col end else if @last_col == end_col col = last_char_col else col = end_col end end cursor_to( @last_row, col, DO_DISPLAY ) end # Top of view def cursor_to_tov cursor_to( row_of( 0 ), @last_col, DO_DISPLAY ) end # Bottom of view def cursor_to_bov cursor_to( row_of( 0 + $diakonos.main_window_height - 1 ), @last_col, DO_DISPLAY ) end # col and row are given relative to the buffer, not any window or screen. # Returns true if the view changed positions. def show_character( row, col ) old_top_line = @top_line old_left_column = @left_column while row < @top_line + @settings[ "view.margin.y" ] amount = (-1) * @settings[ "view.jump.y" ] break if( pitch_view( amount, DONT_PITCH_CURSOR, DONT_DISPLAY ) != amount ) end while row > @top_line + $diakonos.main_window_height - 1 - @settings[ "view.margin.y" ] amount = @settings[ "view.jump.y" ] break if( pitch_view( amount, DONT_PITCH_CURSOR, DONT_DISPLAY ) != amount ) end while col < @left_column + @settings[ "view.margin.x" ] amount = (-1) * @settings[ "view.jump.x" ] break if( pan_view( amount, DONT_DISPLAY ) != amount ) end while col > @left_column + $diakonos.main_window_width - @settings[ "view.margin.x" ] - 2 amount = @settings[ "view.jump.x" ] break if( pan_view( amount, DONT_DISPLAY ) != amount ) end @top_line != old_top_line or @left_column != old_left_column end def go_to_line( line = nil, column = nil, do_display = DO_DISPLAY ) cursor_to( line || @last_row, column || 0, do_display ) end def go_block_outer initial_level = indentation_level( @last_row ) new_row = @last_row passed = false new_level = initial_level ( 0...@last_row ).reverse_each do |row| next if @lines[ row ].strip.empty? level = indentation_level( row ) if ! passed passed = ( level < initial_level ) new_level = level else if level < new_level new_row = ( row+1..@last_row ).find { |r| ! @lines[ r ].strip.empty? } break end end end go_to_line( new_row, @lines[ new_row ].index( /\S/ ) ) end def go_block_inner initial_level = indentation_level( @last_row ) new_row = @lines.length ( @last_row...@lines.length ).each do |row| next if @lines[ row ].strip.empty? level = indentation_level( row ) if level > initial_level new_row = row break elsif level < initial_level new_row = @last_row break end end go_to_line( new_row, @lines[ new_row ].index( /\S/ ) ) end def go_block_next initial_level = indentation_level( @last_row ) new_row = @last_row passed = false ( @last_row+1...@lines.length ).each do |row| next if @lines[ row ].strip.empty? level = indentation_level( row ) if ! passed if level < initial_level passed = true end else if level == initial_level new_row = row break elsif level < initial_level - 1 break end end end go_to_line( new_row, @lines[ new_row ].index( /\S/ ) ) end def go_block_previous initial_level = indentation_level( @last_row ) new_row = @last_row passed = false # search for unindent passed2 = false # search for reindent ( 0...@last_row ).reverse_each do |row| next if @lines[ row ].strip.empty? level = indentation_level( row ) if ! passed if level < initial_level passed = true end else if ! passed2 if level >= initial_level new_row = row passed2 = true elsif level <= initial_level - 2 # No previous block break end else if level < initial_level new_row = ( row+1..@last_row ).find { |r| ! @lines[ r ].strip.empty? } break end end end end go_to_line( new_row, @lines[ new_row ].index( /\S/ ) ) end def go_to_char( char, after = ON_CHAR ) r = @last_row i = @lines[ r ].index( char, @last_col + 1 ) if i if after i += 1 end return cursor_to r, i, DO_DISPLAY end loop do r += 1 break if r >= @lines.size i = @lines[ r ].index( char ) if i if after i += 1 end return cursor_to r, i, DO_DISPLAY end end end def go_to_char_previous( char, after = ON_CHAR ) r = @last_row search_from = @last_col - 1 if search_from >= 0 i = @lines[ r ].rindex( char, search_from ) if i if after i += 1 end return cursor_to r, i, DO_DISPLAY end end loop do r -= 1 break if r < 0 i = @lines[ r ].rindex( char ) if i if after i += 1 end return cursor_to r, i, DO_DISPLAY end end end end enddiakonos-0.9.0/lib/diakonos/buffer/delete.rb000066400000000000000000000103071161735554400207600ustar00rootroot00000000000000module Diakonos class Buffer # x and y are given window-relative, not buffer-relative. def delete if selection_mark delete_selection else row = @last_row col = @last_col if ( row >= 0 ) and ( col >= 0 ) line = @lines[ row ] if col == line.length if row < @lines.length - 1 # Delete newline, and concat next line join_lines( row ) cursor_to( @last_row, @last_col ) end else take_snapshot( TYPING ) @lines[ row ] = line[ 0...col ] + line[ (col + 1)..-1 ] set_modified end end end end def delete_line remove_selection( DONT_DISPLAY ) if selection_mark row = @last_row take_snapshot retval = nil if @lines.length == 1 retval = @lines[ 0 ] @lines[ 0 ] = "" else retval = @lines[ row ] @lines.delete_at row end cursor_to( row, 0 ) set_modified retval end def delete_to_eol remove_selection( DONT_DISPLAY ) if selection_mark row = @last_row col = @last_col take_snapshot if @settings[ 'delete_newline_on_delete_to_eol' ] and col == @lines[ row ].size next_line = @lines.delete_at( row + 1 ) @lines[ row ] << next_line retval = [ "\n" ] else retval = [ @lines[ row ][ col..-1 ] ] @lines[ row ] = @lines[ row ][ 0...col ] end set_modified retval end def delete_from_to( row_from, col_from, row_to, col_to ) take_snapshot if row_to == row_from retval = [ @lines[ row_to ].slice!( col_from, col_to - col_from ) ] else pre_head = @lines[ row_from ][ 0...col_from ] post_tail = @lines[ row_to ][ col_to..-1 ] head = @lines[ row_from ].slice!( col_from..-1 ) tail = @lines[ row_to ].slice!( 0...col_to ) retval = [ head ] + @lines.slice!( row_from + 1, row_to - row_from ) + [ tail ] @lines[ row_from ] = pre_head + post_tail end set_modified retval end def delete_to( char ) remove_selection( DONT_DISPLAY ) if selection_mark first_row = row = @last_row index = @lines[ @last_row ].index( char, @last_col+1 ) while row < @lines.length - 1 && index.nil? row += 1 index = @lines[ row ].index( char ) end if index delete_from_to( first_row, @last_col, row, index ) end end def delete_from( char ) remove_selection( DONT_DISPLAY ) if selection_mark first_row = row = @last_row index = @lines[ @last_row ].rindex( char, @last_col-1 ) while row > 0 && index.nil? row -= 1 index = @lines[ row ].rindex( char ) end if index deleted_text = delete_from_to( row, index+1, first_row, @last_col ) cursor_to( row, index+1 ) deleted_text end end def delete_to_and_from( char, inclusive = NOT_INCLUSIVE ) remove_selection( DONT_DISPLAY ) if selection_mark start_char = end_char = char case char when '(' end_char = ')' when '{' end_char = '}' when '[' end_char = ']' when '<' end_char = '>' when ')' end_char = '(' when '}' end_char = '{' when ']' end_char = '[' when '>' end_char = '<' end row = @last_row start_index = @lines[ @last_row ].rindex( start_char, @last_col ) while row > 0 && start_index.nil? row -= 1 start_index = @lines[ row ].rindex( start_char ) end start_row = row row = @last_row end_index = @lines[ row ].index( end_char, @last_col+1 ) while row < @lines.length - 1 && end_index.nil? row += 1 end_index = @lines[ row ].index( end_char ) end end_row = row if start_index && end_index if inclusive end_index += 1 else start_index += 1 end cursor_to( start_row, start_index ) delete_from_to( start_row, start_index, end_row, end_index ) end end end end diakonos-0.9.0/lib/diakonos/buffer/display.rb000066400000000000000000000265731161735554400211770ustar00rootroot00000000000000module Diakonos class Buffer attr_reader :top_line, :left_column def find_opening_match( line, match_close = true, bos_allowed = true ) open_index = line.length open_token_class = nil open_match_text = nil match = nil match_text = nil @token_regexps.each do |token_class,regexp| if match = regexp.match( line ) if match.length > 1 index = match.begin 1 match_text = match[ 1 ] whole_match_index = match.begin 0 else whole_match_index = index = match.begin( 0 ) match_text = match[ 0 ] end if ( not regexp.uses_bos ) or ( bos_allowed and ( whole_match_index == 0 ) ) if index < open_index if ( ( not match_close ) or @close_token_regexps[ token_class ] ) open_index = index open_token_class = token_class open_match_text = match_text end end end end end [ open_index, open_token_class, open_match_text ] end def find_closing_match( line_, regexp, bos_allowed = true, start_at = 0 ) close_match_text = nil close_index = nil if start_at > 0 line = line_[ start_at..-1 ] else line = line_ end line.scan( regexp ) do |m| match = Regexp.last_match if match.length > 1 index = match.begin 1 match_text = match[ 1 ] else index = match.begin 0 match_text = match[ 0 ] end if ( not regexp.uses_bos ) or ( bos_allowed and ( index == 0 ) ) close_index = index close_match_text = match_text break end end [ close_index, close_match_text ] end # Prints text to the screen, truncating where necessary. # Returns nil if the string is completely off-screen. # write_cursor_col is buffer-relative, not screen-relative def truncate_off_screen( string, write_cursor_col ) retval = string # Truncate based on left edge of display area if write_cursor_col < @left_column retval = retval[ (@left_column - write_cursor_col)..-1 ] write_cursor_col = @left_column end if retval # Truncate based on right edge of display area if write_cursor_col + retval.length > @left_column + Curses::cols - 1 new_length = ( @left_column + Curses::cols - write_cursor_col ) if new_length <= 0 retval = nil else retval = retval[ 0...new_length ] end end end retval == "" ? nil : retval end # Worker function for painting only part of a row. def paint_single_row_mark( row, text_mark, string, curx, cury ) expanded_col = tab_expanded_column( text_mark.start_col, row ) if expanded_col < @left_column + Curses::cols left = [ expanded_col - @left_column, 0 ].max right = tab_expanded_column( text_mark.end_col, row ) - @left_column if left < right @win_main.setpos( cury, curx + left ) @win_main.addstr string[ left...right ] end end end def paint_marks( row ) string = @lines[ row ][ @left_column ... @left_column + Curses::cols ] return if string.nil? or string == "" string = string.expand_tabs( @tab_size ) cury = @win_main.cury curx = @win_main.curx @text_marks.values.flatten.reverse_each do |text_mark| next if text_mark.nil? @win_main.attrset text_mark.formatting case @selection_mode when :normal if ( (text_mark.start_row + 1) .. (text_mark.end_row - 1) ) === row @win_main.setpos( cury, curx ) @win_main.addstr string elsif row == text_mark.start_row and row == text_mark.end_row paint_single_row_mark( row, text_mark, string, curx, cury ) elsif row == text_mark.start_row expanded_col = tab_expanded_column( text_mark.start_col, row ) if expanded_col < @left_column + Curses::cols left = [ expanded_col - @left_column, 0 ].max @win_main.setpos( cury, curx + left ) @win_main.addstr string[ left..-1 ] end elsif row == text_mark.end_row right = tab_expanded_column( text_mark.end_col, row ) - @left_column @win_main.setpos( cury, curx ) @win_main.addstr string[ 0...right ] else # This row not in selection. end when :block if( text_mark.start_row <= row && row <= text_mark.end_row || text_mark.end_row <= row && row <= text_mark.start_row ) paint_single_row_mark( row, text_mark, string, curx, cury ) end end end end def paint_column_markers $diakonos.column_markers.each_value do |data| column = data[ :column ] next if column.nil? next if column > Curses::cols - @left_column || column - @left_column < 0 num_lines_to_paint = [ $diakonos.main_window_height, @lines.size - @top_line ].min ( 0...num_lines_to_paint ).each do |row| @win_main.setpos( row, column - @left_column ) @win_main.attrset data[ :format ] @win_main.addstr( @lines[ @top_line + row ][ column + @left_column ] || ' ' ) end end end def print_string( string, formatting = ( @token_formats[ @continued_format_class ] or @default_formatting ) ) return if not @pen_down return if string.nil? @win_main.attrset formatting @win_main.addstr string end # This method assumes that the cursor has been setup already at # the left-most column of the correct on-screen row. # It merely unintelligently prints the characters on the current curses line, # refusing to print characters of the in-buffer line which are offscreen. def print_line( line ) i = 0 substr = nil index = nil while i < line.length substr = line[ i..-1 ] if @continued_format_class close_index, close_match_text = find_closing_match( substr, @close_token_regexps[ @continued_format_class ], i == 0 ) if close_match_text.nil? print_string truncate_off_screen( substr, i ) print_padding_from( line.length ) i = line.length else end_index = close_index + close_match_text.length print_string truncate_off_screen( substr[ 0...end_index ], i ) @continued_format_class = nil i += end_index end else first_index, first_token_class, first_word = find_opening_match( substr, MATCH_ANY, i == 0 ) if @lang_stack.length > 0 prev_lang, close_token_class = @lang_stack[ -1 ] close_index, close_match_text = find_closing_match( substr, $diakonos.close_token_regexps[ prev_lang ][ close_token_class ], i == 0 ) if close_match_text and close_index <= first_index if close_index > 0 # Print any remaining text in the embedded language print_string truncate_off_screen( substr[ 0...close_index ], i ) i += substr[ 0...close_index ].length end @lang_stack.pop set_language prev_lang print_string( truncate_off_screen( substr[ close_index...(close_index + close_match_text.length) ], i ), @token_formats[ close_token_class ] ) i += close_match_text.length # Continue printing from here. next end end if first_word if first_index > 0 # Print any preceding text in the default format print_string truncate_off_screen( substr[ 0...first_index ], i ) i += substr[ 0...first_index ].length end print_string( truncate_off_screen( first_word, i ), @token_formats[ first_token_class ] ) i += first_word.length if @close_token_regexps[ first_token_class ] if change_to = @settings[ "lang.#{@language}.tokens.#{first_token_class}.change_to" ] @lang_stack.push [ @language, first_token_class ] set_language change_to else @continued_format_class = first_token_class end end else print_string truncate_off_screen( substr, i ) i += substr.length break end end end print_padding_from i end def print_padding_from( col ) return if not @pen_down if col < @left_column remainder = Curses::cols else remainder = @left_column + Curses::cols - col end if remainder > 0 print_string( " " * remainder ) end end def display @continued_format_class = nil @pen_down = true # First, we have to "draw" off-screen, in order to check for opening of # multi-line highlights. # So, first look backwards from the @top_line to find the first opening # regexp match, if any. index = @top_line - 1 @lines[ [ 0, @top_line - @settings[ "view.lookback" ] ].max...@top_line ].reverse_each do |line| open_index = -1 open_token_class = nil open_match_text = nil open_index, open_token_class, open_match_text = find_opening_match( line ) if open_token_class @pen_down = false @lines[ index...@top_line ].each do |line| print_line line end @pen_down = true break end index = index - 1 end # Draw each on-screen line. y = 0 @lines[ @top_line...($diakonos.main_window_height + @top_line) ].each_with_index do |line, row| if @win_line_numbers @win_line_numbers.setpos( y, 0 ) @win_line_numbers.attrset @settings[ 'view.line_numbers.format' ] n = ( @top_line+row+1 ).to_s @win_line_numbers.addstr( @settings[ 'view.line_numbers.number_format' ] % [ n[ -[ @settings[ 'view.line_numbers.width' ], n.length ].min..-1 ] ] ) end @win_main.setpos( y, 0 ) print_line line.expand_tabs( @tab_size ) @win_main.setpos( y, 0 ) paint_marks @top_line + row y += 1 end # Paint the empty space below the file if the file is too short to fit in one screen. ( y...$diakonos.main_window_height ).each do |y| if @win_line_numbers @win_line_numbers.setpos( y, 0 ) @win_line_numbers.attrset @settings[ 'view.line_numbers.format' ] @win_line_numbers.addstr( ' ' * @settings[ 'view.line_numbers.width' ] ) end @win_main.setpos( y, 0 ) @win_main.attrset @default_formatting linestr = " " * Curses::cols if @settings[ "view.nonfilelines.visible" ] linestr[ 0 ] = ( @settings[ "view.nonfilelines.character" ] or "~" ) end @win_main.addstr linestr end paint_column_markers if @win_line_numbers @win_line_numbers.refresh end @win_main.setpos( @last_screen_y , @last_screen_x ) @win_main.refresh if @language != @original_language set_language( @original_language ) end end end enddiakonos-0.9.0/lib/diakonos/buffer/file.rb000066400000000000000000000072471161735554400204460ustar00rootroot00000000000000module Diakonos class Buffer def save( filename = nil, prompt_overwrite = DONT_PROMPT_OVERWRITE ) if filename name = File.expand_path( filename ) else name = @name end if @read_only && FileTest.exists?( @name ) && FileTest.exists?( name ) && ( File.stat( @name ).ino == File.stat( name ).ino ) $diakonos.set_iline "#{name} cannot be saved since it is read-only." else @read_only = false if name.nil? $diakonos.save_file_as else proceed = true if prompt_overwrite && FileTest.exists?( name ) proceed = false choice = $diakonos.get_choice( "Overwrite existing '#{name}'?", [ CHOICE_YES, CHOICE_NO ], CHOICE_NO ) case choice when CHOICE_YES proceed = true when CHOICE_NO proceed = false end end if file_modified? proceed = ! $diakonos.revert( "File has been altered externally. Load on-disk version?" ) end if proceed save_copy name @name = name @last_modification_check = File.mtime( @name ) saved = true if @name =~ /#{$diakonos.diakonos_home}\/.*\.conf/ $diakonos.load_configuration $diakonos.initialize_display end @modified = false display $diakonos.update_status_line end end end saved end # Returns true on successful write. def save_copy( filename ) return false if filename.nil? name = File.expand_path( filename ) File.open( name, "w" ) do |f| @lines[ 0..-2 ].each do |line| if @settings[ 'strip_trailing_whitespace_on_save' ] line.rstrip! end f.puts line end line = @lines[ -1 ] if @settings[ 'strip_trailing_whitespace_on_save' ] line.rstrip! end if line != "" # No final newline character if @settings[ "eof_newline" ] line << "\n" @lines << '' end f.print line end if @settings[ 'strip_trailing_whitespace_on_save' ] if @last_col > @lines[ @last_row ].size cursor_to @last_row, @lines[ @last_row ].size end end end end # Check if the file which is being edited has been modified since # the last time we checked it. # @return true if file has been modified # @return false if file has not been modified def file_modified? modified = false if @name begin mtime = File.mtime( @name ) if mtime > @last_modification_check modified = true @last_modification_check = mtime end rescue Errno::ENOENT # Ignore if file doesn't exist end end modified end # Compares MD5 sums of buffer and actual file on disk. # Returns true if there is no file on disk. def file_different? if @name && File.exist?( @name ) Digest::MD5.hexdigest( @lines.join( "\n" ) ) != Digest::MD5.hexdigest( File.read( @name ) ) else true end end def set_modified( do_display = DO_DISPLAY, use_md5 = DONT_USE_MD5 ) if @read_only $diakonos.set_iline "Warning: Modifying a read-only file." end @modified = use_md5 ? file_different? : true clear_matches if do_display $diakonos.update_status_line display end end end end diakonos-0.9.0/lib/diakonos/buffer/indentation.rb000066400000000000000000000077321161735554400220420ustar00rootroot00000000000000module Diakonos class Buffer def tab_expanded_column( col, row ) delta = 0 line = @lines[ row ] for i in 0...col if line[ i ] == "\t" delta += ( @tab_size - ( (i+delta) % @tab_size ) ) - 1 end end col + delta end def set_indent( row, level, do_display = DO_DISPLAY ) @lines[ row ] =~ /^([\s#{@indent_ignore_charset}]*)(.*)$/ current_indent_text = ( $1 or "" ) rest = ( $2 or "" ) current_indent_text.gsub!( /\t/, ' ' * @tab_size ) indentation = @indent_size * [ level, 0 ].max if current_indent_text.length >= indentation indent_text = current_indent_text[ 0...indentation ] else indent_text = current_indent_text + " " * ( indentation - current_indent_text.length ) end if @settings[ "lang.#{@language}.indent.using_tabs" ] num_tabs = 0 indent_text.gsub!( / {#{@tab_size}}/ ) { |match| num_tabs += 1 "\t" } indentation -= num_tabs * ( @tab_size - 1 ) end take_snapshot( TYPING ) if do_display @lines[ row ] = indent_text + rest cursor_to( row, indentation ) if do_display set_modified end def indentation_level( row, use_indent_ignore = USE_INDENT_IGNORE ) line = @lines[ row ] if use_indent_ignore if line =~ /^[\s#{@indent_ignore_charset}]*$/ or line == "" level = 0 elsif line =~ /^([\s#{@indent_ignore_charset}]+)[^\s#{@indent_ignore_charset}]/ whitespace = $1.expand_tabs( @tab_size ) level = whitespace.length / @indent_size if @indent_roundup && ( whitespace.length % @indent_size > 0 ) level += 1 end else level = 0 end else level = 0 if line =~ /^([\s]+)/ whitespace = $1.expand_tabs( @tab_size ) level = whitespace.length / @indent_size if @indent_roundup && ( whitespace.length % @indent_size > 0 ) level += 1 end end end level end def parsed_indent( row = @last_row, do_display = DO_DISPLAY ) if row == 0 || @lines[ row ] =~ @settings[ "lang.#{@language}.indent.not_indented" ] level = 0 else # Look upwards for the nearest line on which to base this line's indentation. i = 1 while ( @lines[ row - i ] =~ /^[\s#{@indent_ignore_charset}]*$/ || @lines[ row - i ] =~ @settings[ "lang.#{@language}.indent.ignore" ] || @lines[ row - i ] =~ @settings[ "lang.#{@language}.indent.not_indented" ] ) i += 1 end if row - i < 0 level = 0 else prev_line = @lines[ row - i ] second_prev_line = '' if ! ( ( row - i - i ) < 0 ) second_prev_line = @lines[ row - i - 1 ] end level = indentation_level( row - i ) line = @lines[ row ] if @preventers prev_line = prev_line.gsub( @preventers, "" ) line = line.gsub( @preventers, "" ) end indenter_index = ( prev_line =~ @indenters ) if prev_line =~ @indenters_next_line level += 1 elsif indenter_index level += 1 unindenter_index = (prev_line =~ @unindenters) if unindenter_index and unindenter_index != indenter_index level += -1 end end if line =~ @unindenters || second_prev_line =~ @indenters_next_line level += -1 end end end set_indent( row, level, do_display ) end def indent( row = @last_row, do_display = DO_DISPLAY ) level = indentation_level( row, DONT_USE_INDENT_IGNORE ) set_indent( row, level + 1, do_display ) end def unindent( row = @last_row, do_display = DO_DISPLAY ) level = indentation_level( row, DONT_USE_INDENT_IGNORE ) set_indent( row, level - 1, do_display ) end end end diakonos-0.9.0/lib/diakonos/buffer/searching.rb000066400000000000000000000344651161735554400214740ustar00rootroot00000000000000module Diakonos class Buffer attr_reader :num_matches_found, :last_search_regexps CHARACTER_PAIRS = { '(' => { partner: ')', direction: :forward }, '<' => { partner: '>', direction: :forward }, '{' => { partner: '}', direction: :forward }, '[' => { partner: ']', direction: :forward }, ')' => { partner: '(', direction: :backward }, '>' => { partner: '<', direction: :backward }, '}' => { partner: '{', direction: :backward }, ']' => { partner: '[', direction: :backward }, } def search_area? !! @search_area end def search_area=( mark ) @search_area = mark if mark.nil? @text_marks.delete :search_area_pre @text_marks.delete :search_area_post else @text_marks[ :search_area_pre ] = TextMark.new( 0, 0, mark.start_row, mark.start_col, @settings[ 'view.non_search_area.format' ] ) @text_marks[ :search_area_post ] = TextMark.new( mark.end_row, mark.end_col, @lines.length - 1, @lines[ -1 ].length, @settings[ 'view.non_search_area.format' ] ) end end def establish_finding( regexps, search_area, from_row, from_col, match ) found_text = match[ 0 ] finding = Finding.new( from_row, from_col, from_row, from_col + found_text.length ) if finding.match( regexps, @lines ) if( search_area.contains?( finding.start_row, finding.start_col ) && search_area.contains?( finding.end_row, finding.end_col - 1 ) ) throw :found, [ finding, match ] end end end # Takes an array of Regexps, which represents a user-provided regexp, # split across newline characters. Once the first element is found, # each successive element must match against lines following the first # element. # @return [Fixnum] the number of replacements made def find( regexps, options = {} ) return if regexps.nil? regexp = regexps[ 0 ] return if regexp.nil? || regexp == // direction = options[ :direction ] replacement = options[ :replacement ] auto_choice = options[ :auto_choice ] from_row = options[ :starting_row ] || @last_row from_col = options[ :starting_col ] || @last_col show_context_after = options[ :show_context_after ] if options[:starting] @num_matches_found = nil end num_replacements = 0 search_area = @search_area || TextMark.new( 0, 0, @lines.size - 1, @lines[ -1 ].size, nil ) if ! search_area.contains?( from_row, from_col ) from_row, from_col = search_area.start_row, search_area.start_col end if direction == :opposite case @last_search_direction when :up direction = :down else direction = :up end end @last_search_regexps = regexps @last_search_direction = direction wrapped = false finding, match = catch :found do if direction == :down # Check the current row first. index = @lines[ from_row ].index( regexp, ( @last_finding ? @last_finding.start_col : from_col ) + 1 ) if index establish_finding( regexps, search_area, from_row, index, Regexp.last_match ) end # Check below the cursor. ( (from_row + 1)..search_area.end_row ).each do |i| line = @lines[ i ] if i == search_area.end_row line = line[ 0...search_area.end_col ] end index = line.index( regexp ) if index establish_finding( regexps, search_area, i, index, Regexp.last_match ) end end if index establish_finding( regexps, search_area, search_area.end_row, index, Regexp.last_match ) end # Wrap around. wrapped = true index = @lines[ search_area.start_row ].index( regexp, search_area.start_col ) if index establish_finding( regexps, search_area, search_area.start_row, index, Regexp.last_match ) end ( search_area.start_row+1...from_row ).each do |i| index = @lines[ i ].index( regexp ) if index establish_finding( regexps, search_area, i, index, Regexp.last_match ) end end # And finally, the other side of the current row. if from_row == search_area.start_row index_col = search_area.start_col else index_col = 0 end if index = @lines[ from_row ].index( regexp, index_col ) if index <= ( @last_finding ? @last_finding.start_col : from_col ) establish_finding( regexps, search_area, from_row, index, Regexp.last_match ) end end elsif direction == :up # Check the current row first. col_to_check = ( @last_finding ? @last_finding.end_col : from_col ) - 1 if ( col_to_check >= 0 ) && ( index = @lines[ from_row ][ 0...col_to_check ].rindex( regexp ) ) establish_finding( regexps, search_area, from_row, index, Regexp.last_match ) end # Check above the cursor. (from_row - 1).downto( 0 ) do |i| if index = @lines[ i ].rindex( regexp ) establish_finding( regexps, search_area, i, index, Regexp.last_match ) end end # Wrap around. wrapped = true (@lines.length - 1).downto(from_row + 1) do |i| if index = @lines[ i ].rindex( regexp ) establish_finding( regexps, search_area, i, index, Regexp.last_match ) end end # And finally, the other side of the current row. search_col = ( @last_finding ? @last_finding.start_col : from_col ) + 1 if index = @lines[ from_row ].rindex( regexp ) if index > search_col establish_finding( regexps, search_area, from_row, index, Regexp.last_match ) end end end end if ! finding remove_selection DONT_DISPLAY clear_matches DO_DISPLAY if ! options[ :quiet ] && ( replacement.nil? || num_replacements == 0 ) $diakonos.set_iline "/#{regexp.source}/ not found." end else if wrapped && ! options[ :quiet ] if @search_area $diakonos.set_iline( "(search wrapped around to start of search area)" ) else $diakonos.set_iline( "(search wrapped around BOF/EOF)" ) end end remove_selection( DONT_DISPLAY ) @last_finding = finding if @settings[ "found_cursor_start" ] anchor_selection( finding.end_row, finding.end_col, DONT_DISPLAY ) cursor_to( finding.start_row, finding.start_col ) else anchor_selection( finding.start_row, finding.start_col, DONT_DISPLAY ) cursor_to( finding.end_row, finding.end_col ) end if show_context_after watermark = Curses::lines / 6 if @last_row - @top_line > watermark pitch_view( @last_row - @top_line - watermark ) end end @changing_selection = false if regexps.length == 1 @highlight_regexp = regexp highlight_matches else clear_matches end display if replacement # Substitute placeholders (e.g. \1) in str for the group matches of the last match. actual_replacement = replacement.dup actual_replacement.gsub!( /\\(\\|\d+)/ ) { |m| ref = $1 if ref == "\\" "\\" else match[ ref.to_i ] end } choice = auto_choice || $diakonos.get_choice( "#{num_matches_found} match#{ num_matches_found != 1 ? 'es' : '' } - Replace this one?", [ CHOICE_YES, CHOICE_NO, CHOICE_ALL, CHOICE_CANCEL, CHOICE_YES_AND_STOP ], CHOICE_YES ) case choice when CHOICE_YES paste [ actual_replacement ] num_replacements += 1 + find( regexps, direction: direction, replacement: replacement ) when CHOICE_ALL num_replacements += replace_all( regexp, replacement ) when CHOICE_NO num_replacements += find( regexps, direction: direction, replacement: replacement ) when CHOICE_CANCEL # Do nothing further. when CHOICE_YES_AND_STOP paste [ actual_replacement ] num_replacements += 1 # Do nothing further. end end end num_replacements end # @return [Fixnum] the number of replacements made def replace_all( regexp, replacement ) return if( regexp.nil? or replacement.nil? ) num_replacements = 0 take_snapshot @lines = @lines.collect { |line| num_replacements += line.scan(regexp).size line.gsub( regexp, replacement ) } set_modified clear_matches display num_replacements end def highlight_matches( regexp = @highlight_regexp ) @highlight_regexp = regexp return if @highlight_regexp.nil? found_marks = @lines.grep_indices( @highlight_regexp ).collect do |line_index, start_col, end_col| TextMark.new( line_index, start_col, line_index, end_col, @settings[ "lang.#{@language}.format.found" ] ) end @text_marks[ :found ] = found_marks @num_matches_found ||= found_marks.size end def clear_matches( do_display = DONT_DISPLAY ) @text_marks[ :found ] = [] @highlight_regexp = nil display if do_display end def pos_of_next( regexp, start_row, start_col ) row, col = start_row, start_col col = @lines[ row ].index( regexp, col ) while col.nil? && row < @lines.length - 1 row += 1 col = @lines[ row ].index( regexp ) end if col [ row, col, Regexp.last_match( 0 ) ] end end def pos_of_prev( regexp, start_row, start_col ) row, col = start_row, start_col if col < 0 row -= 1 col = -1 end col = @lines[ row ].rindex( regexp, col ) while col.nil? && row > 0 row -= 1 col = @lines[ row ].rindex( regexp ) end if col [ row, col, Regexp.last_match( 0 ) ] end end def pos_of_pair_match( row = @last_row, col = @last_col ) c = @lines[ row ][ col ] data = CHARACTER_PAIRS[ c ] return if data.nil? d = data[ :partner ] c_ = Regexp.escape c d_ = Regexp.escape d target = /(?:#{c_}|#{d_})/ case data[ :direction ] when :forward row, col, char = pos_of_next( target, row, col + 1 ) while char == c # Take care of nested pairs row, col = pos_of_pair_match( row, col ) break if col.nil? row, col, char = pos_of_next( target, row, col + 1 ) end when :backward row, col, char = pos_of_prev( target, row, col - 1 ) while char == c # Take care of nested pairs row, col = pos_of_pair_match( row, col ) break if col.nil? row, col, char = pos_of_prev( target, row, col - 1 ) end end [ row, col ] end def go_to_pair_match row, col = pos_of_pair_match if row && col if cursor_to( row, col ) highlight_pair display end end end def highlight_pair match_row, match_col = pos_of_pair_match( @last_row, @last_col ) if match_col.nil? @text_marks[ :pair ] = nil else @text_marks[ :pair ] = TextMark.new( match_row, match_col, match_row, match_col + 1, @settings[ "lang.#{@language}.format.pair" ] || @settings[ "lang.shared.format.pair" ] ) end end def clear_pair_highlight @text_marks[ :pair ] = nil end def find_again( last_search_regexps, direction = @last_search_direction ) if @last_search_regexps.nil? || @last_search_regexps.empty? @last_search_regexps = last_search_regexps end if @last_search_regexps find @last_search_regexps, direction: direction end end def seek( regexp, direction = :down ) return if regexp.nil? || regexp == // found_row = nil found_col = nil found_text = nil catch :found do if direction == :down # Check the current row first. index, match_text = @lines[ @last_row ].group_index( regexp, @last_col + 1 ) if index found_row = @last_row found_col = index found_text = match_text throw :found end # Check below the cursor. ( (@last_row + 1)...@lines.length ).each do |i| index, match_text = @lines[ i ].group_index( regexp ) if index found_row = i found_col = index found_text = match_text throw :found end end else # Check the current row first. col_to_check = @last_col - 1 if col_to_check >= 0 index, match_text = @lines[ @last_row ].group_rindex( regexp, col_to_check ) if index found_row = @last_row found_col = index found_text = match_text throw :found end end # Check above the cursor. (@last_row - 1).downto( 0 ) do |i| index, match_text = @lines[ i ].group_rindex( regexp ) if index found_row = i found_col = index found_text = match_text throw :found end end end end if found_text cursor_to( found_row, found_col ) display true end end # Returns an Array of results, where each result is a String usually # containing \n's due to context def grep( regexp_source ) ::Diakonos.grep_array( Regexp.new( regexp_source ), @lines, $diakonos.settings[ 'grep.context' ], "#{File.basename( @name )}:", @name ) end end end diakonos-0.9.0/lib/diakonos/buffer/selection.rb000066400000000000000000000224321161735554400215050ustar00rootroot00000000000000module Diakonos class Buffer # @mark_start[ "col" ] is inclusive, # @mark_end[ "col" ] is exclusive. def record_mark_start_and_end if @mark_anchor.nil? @text_marks[ :selection ] = nil return end crow = @last_row ccol = @last_col arow = @mark_anchor[ 'row' ] acol = @mark_anchor[ 'col' ] case @selection_mode when :normal anchor_first = true if crow < arow anchor_first = false elsif crow > arow anchor_first = true else if ccol < acol anchor_first = false end end if anchor_first @text_marks[ :selection ] = TextMark.new( arow, acol, crow, ccol, @selection_formatting ) else @text_marks[ :selection ] = TextMark.new( crow, ccol, arow, acol, @selection_formatting ) end when :block if crow < arow if ccol < acol # Northwest @text_marks[ :selection ] = TextMark.new( crow, ccol, arow, acol, @selection_formatting ) else # Northeast @text_marks[ :selection ] = TextMark.new( crow, acol, arow, ccol, @selection_formatting ) end else if ccol < acol # Southwest @text_marks[ :selection ] = TextMark.new( arow, ccol, crow, acol, @selection_formatting ) else # Southeast @text_marks[ :selection ] = TextMark.new( arow, acol, crow, ccol, @selection_formatting ) end end end end def selection_mark @text_marks[ :selection ] end def selecting? !!selection_mark end def select_current_line selection_mode_normal anchor_selection( @last_row, 0, DONT_DISPLAY ) if @last_row == @lines.size - 1 row = @last_row col = @lines[ @last_row ].size else row = @last_row + 1 col = 0 end cursor_to( row, col, DO_DISPLAY ) end def set_selection_current_line @text_marks[ :selection ] = TextMark.new( @last_row, 0, @last_row, @lines[ @last_row ].size, @selection_formatting ) @lines[ @last_row ] end def select_all selection_mode_normal anchor_selection( 0, 0, DONT_DISPLAY ) cursor_to( @lines.length - 1, @lines[ -1 ].length, DO_DISPLAY ) end def select_wrapping_block block_level = indentation_level( @last_row ) if selecting? block_level -= 1 end if block_level <= 0 return select_all end end_row = start_row = @last_row # Find block end ( @last_row...@lines.size ).each do |row| next if @lines[ row ].strip.empty? if indentation_level( row ) < block_level end_row = row break end end # Go to block beginning ( 0...@last_row ).reverse_each do |row| next if @lines[ row ].strip.empty? if indentation_level( row ) < block_level start_row = row + 1 break end end anchor_selection( end_row, 0 ) cursor_to( start_row, 0, DO_DISPLAY ) end def select_word coords = word_under_cursor_pos( or_after: true ) if coords.nil? remove_selection else cursor_to *coords[0] anchor_selection cursor_to *coords[1] display end end def select_word_another m = selection_mark if m.nil? select_word else row, col, _ = pos_of_next( /\w\b/, @last_row, @last_col ) if row && col cursor_to row, col+1, DO_DISPLAY end end end def select( from_regexp, to_regexp, include_ending = true ) start_row = nil @lines[ 0..@last_row ].reverse.each_with_index do |line,index| if line =~ from_regexp start_row = @last_row - index break end end if start_row end_row = nil @lines[ start_row..-1 ].each_with_index do |line,index| if line =~ to_regexp end_row = start_row + index break end end if end_row if include_ending end_row += 1 end anchor_selection( start_row, 0, DONT_DISPLAY ) cursor_to( end_row, 0 ) display end end end def set_selection( start_row, start_col, end_row, end_col ) @text_marks[ :selection ] = TextMark.new( start_row, start_col, end_row, end_col, @selection_formatting ) @changing_selection = false end def anchor_selection( row = @last_row, col = @last_col, do_display = DO_DISPLAY ) @mark_anchor = ( @mark_anchor or Hash.new ) @mark_anchor[ "row" ] = row @mark_anchor[ "col" ] = col record_mark_start_and_end @changing_selection = true display if do_display end def remove_selection( do_display = DO_DISPLAY ) return if selection_mark.nil? @mark_anchor = nil record_mark_start_and_end @changing_selection = false @last_finding = nil display if do_display end def toggle_selection if @changing_selection remove_selection else anchor_selection end end def copy_selection selected_text end def selected_text selection = selection_mark if selection.nil? nil elsif selection.start_row == selection.end_row [ @lines[ selection.start_row ][ selection.start_col...selection.end_col ] ] else if @selection_mode == :block @lines[ selection.start_row .. selection.end_row ].collect { |line| line[ selection.start_col ... selection.end_col ] } else [ @lines[ selection.start_row ][ selection.start_col..-1 ] ] + ( @lines[ (selection.start_row + 1) .. (selection.end_row - 1) ] or [] ) + [ @lines[ selection.end_row ][ 0...selection.end_col ] ] end end end def selected_string lines = selected_text if lines lines.join( "\n" ) else nil end end def selected_lines selection = selection_mark if selection if selection.end_col == 0 end_row = selection.end_row - 1 else end_row = selection.end_row end @lines[ selection.start_row..end_row ] else [ @lines[ @last_row ] ] end end def selection_mode_block @selection_mode = :block end def selection_mode_normal @selection_mode = :normal end def delete_selection( do_display = DO_DISPLAY ) return if @text_marks[ :selection ].nil? take_snapshot selection = @text_marks[ :selection ] start_row = selection.start_row start_col = selection.start_col end_row = selection.end_row end_col = selection.end_col start_line = @lines[ start_row ] if end_row == selection.start_row @lines[ start_row ] = start_line[ 0...start_col ] + start_line[ end_col..-1 ] else case @selection_mode when :normal end_line = @lines[ end_row ] @lines[ start_row ] = start_line[ 0...start_col ] + end_line[ end_col..-1 ] @lines = @lines[ 0..start_row ] + @lines[ (end_row + 1)..-1 ] when :block @lines[ start_row..end_row ] = @lines[ start_row..end_row ].collect { |line| line[ 0...start_col ] + ( line[ end_col..-1 ] || '' ) } end end cursor_to start_row, start_col remove_selection DONT_DISPLAY set_modified do_display end # text is an array of Strings, or a String with zero or more newlines ("\n") def paste( text, typing = ! TYPING, do_parsed_indent = false ) return if text.nil? if not text.kind_of? Array s = text.to_s if s.include?( "\n" ) text = s.split( "\n", -1 ) else text = [ s ] end end take_snapshot typing delete_selection DONT_DISPLAY row = @last_row col = @last_col new_col = nil line = @lines[ row ] if text.length == 1 @lines[ row ] = line[ 0...col ] + text[ 0 ] + line[ col..-1 ] if do_parsed_indent parsed_indent row, DONT_DISPLAY end cursor_to( @last_row, @last_col + text[ 0 ].length, DONT_DISPLAY, ! typing ) elsif text.length > 1 case @selection_mode when :normal @lines[ row ] = line[ 0...col ] + text[ 0 ] @lines[ row + 1, 0 ] = text[ -1 ] + line[ col..-1 ] @lines[ row + 1, 0 ] = text[ 1..-2 ] new_col = column_of( text[ -1 ].length ) when :block @lines += [ '' ] * [ 0, ( row + text.length - @lines.length ) ].max @lines[ row...( row + text.length ) ] = @lines[ row...( row + text.length ) ].collect.with_index { |line,index| pre = line[ 0...col ].ljust( col ) post = line[ col..-1 ] "#{pre}#{text[ index ]}#{post}" } new_col = col + text[ -1 ].length end new_row = @last_row + text.length - 1 if do_parsed_indent ( row..new_row ).each do |r| parsed_indent r, DONT_DISPLAY end end cursor_to( new_row, new_col ) end set_modified end end enddiakonos-0.9.0/lib/diakonos/buffer/undo.rb000066400000000000000000000043041161735554400204630ustar00rootroot00000000000000module Diakonos class Buffer DO_USE_MD5 = true DONT_USE_MD5 = false def take_snapshot( typing = false ) do_it = false if ! @modified && file_modified? && file_different? return if $diakonos.revert( "File has been altered externally. Load on-disk version?" ) end if @typing != typing @typing = typing # If we just started typing, take a snapshot, but don't continue # taking snapshots for every keystroke if typing do_it = true end end if not @typing do_it = true end if do_it undo_size = 0 @buffer_states[ 1..-1 ].each do |state| undo_size += state.length end while ( ( undo_size + @lines.length ) >= @settings[ "max_undo_lines" ] ) and @buffer_states.length > 1 @cursor_states.pop popped_state = @buffer_states.pop undo_size = undo_size - popped_state.length end if @current_buffer_state > 0 @buffer_states.unshift @lines.deep_clone @cursor_states.unshift [ @last_row, @last_col ] end @buffer_states.unshift @lines.deep_clone @cursor_states.unshift [ @last_row, @last_col ] @current_buffer_state = 0 @lines = @buffer_states[ @current_buffer_state ] end end def undo return if @current_buffer_state >= @buffer_states.length - 1 @current_buffer_state += 1 @lines = @buffer_states[ @current_buffer_state ] cursor_to( @cursor_states[ @current_buffer_state - 1 ][ 0 ], @cursor_states[ @current_buffer_state - 1 ][ 1 ] ) $diakonos.set_iline "Undo level: #{@current_buffer_state} of #{@buffer_states.length - 1}" set_modified DO_DISPLAY, DO_USE_MD5 end # Since redo is a Ruby keyword... def unundo return if @current_buffer_state <= 0 @current_buffer_state += -1 @lines = @buffer_states[ @current_buffer_state ] cursor_to( @cursor_states[ @current_buffer_state ][ 0 ], @cursor_states[ @current_buffer_state ][ 1 ] ) $diakonos.set_iline "Undo level: #{@current_buffer_state} of #{@buffer_states.length - 1}" set_modified DO_DISPLAY, DO_USE_MD5 end end enddiakonos-0.9.0/lib/diakonos/clipboard-klipper-dbus.rb000066400000000000000000000036721161735554400226120ustar00rootroot00000000000000module Diakonos # Same interface as Diakonos::Clipboard, except interacts with Klipper in KDE4 (via dbus) class ClipboardKlipperDBus def initialize end # Returns true iff some text was copied to klipper. def send_to_klipper( text ) return false if text.nil? clip_filename = write_to_clip_file( text.join( "\n" ) ) # A little shell sorcery to ensure the shell doesn't strip off trailing newlines. # Thank you to pgas from irc.freenode.net#bash for help with this. `clipping=$(cat #{clip_filename};printf "_"); dbus-send --type=method_call --dest=org.kde.klipper /klipper org.kde.klipper.klipper.setClipboardContents string:"${clipping%_}"` true end def write_to_clip_file( text ) clip_filename = $diakonos.diakonos_home + "/clip.txt" File.open( clip_filename, "w" ) do |f| f.print text end clip_filename end # ------------------------------ def clip text = `dbus-send --print-reply --dest=org.kde.klipper /klipper org.kde.klipper.klipper.getClipboardContents | awk 'BEGIN { output = ""; } { if ( NR > 1 ) { output = output $0 "\\n"; } } END { print substr(output, 12, length(output) - 13); }'`.split( "\n", -1 ) # getClipboardContents puts an extra newline on end; pop it off. text.pop text end # text is an array of Strings # Returns true iff a clip was added, # and only non-nil text can be added. def add_clip( text ) return false if text.nil? send_to_klipper text end # no-op. def each end # text is an array of Strings (lines) # Appends the lines to the current clip. # If no current clip, then a new clip is created. # Returns true iff the text was successfully appended. def append_to_clip( text ) return false if text.nil? last_clip = clip last_clip.pop if last_clip[ -1 ] == "" send_to_klipper last_clip + text end end end diakonos-0.9.0/lib/diakonos/clipboard-klipper.rb000066400000000000000000000032571161735554400216560ustar00rootroot00000000000000module Diakonos # Same interface as Diakonos::Clipboard, except interacts with Klipper in KDE 3 (via dcop) class ClipboardKlipper def initialize end # Returns true iff some text was copied to klipper. def send_to_klipper( text ) return false if text.nil? clip_filename = write_to_clip_file( text.join( "\n" ) ) # A little shell sorcery to ensure the shell doesn't strip off trailing newlines. # Thank you to pgas from irc.freenode.net#bash for help with this. `clipping=$(cat #{clip_filename};printf "_"); dcop klipper klipper setClipboardContents "${clipping%_}"` true end def write_to_clip_file( text ) clip_filename = $diakonos.diakonos_home + "/clip.txt" File.open( clip_filename, "w" ) do |f| f.print text end clip_filename end # ------------------------------ def clip text = `dcop klipper klipper getClipboardContents`.split( "\n", -1 ) # getClipboardContents puts an extra newline on end; pop it off. text.pop text end # text is an array of Strings # Returns true iff a clip was added, # and only non-nil text can be added. def add_clip( text ) return false if text.nil? send_to_klipper text end # no-op. def each end # text is an array of Strings (lines) # Appends the lines to the current clip. # If no current clip, then a new clip is created. # Returns true iff the text was successfully appended. def append_to_clip( text ) return false if text.nil? last_clip = clip last_clip.pop if last_clip[ -1 ] == "" send_to_klipper last_clip + text end end end diakonos-0.9.0/lib/diakonos/clipboard-xclip.rb000066400000000000000000000025571161735554400213310ustar00rootroot00000000000000module Diakonos # Same interface as Diakonos::Clipboard, except interacts with xclip class ClipboardXClip def initialize end # Returns true iff some text was copied to xclip. def send_to_xclip( text ) return false if text.nil? clip_filename = write_to_clip_file( text.join( "\n" ) ) t = Thread.new do `xclip -i #{clip_filename}` end `xclip -o` # Unfreeze xclip t.terminate true end def write_to_clip_file( text ) clip_filename = $diakonos.diakonos_home + "/clip.txt" File.open( clip_filename, "w" ) do |f| f.print text end clip_filename end # ------------------------------ def clip `xclip -o`.split( "\n", -1 ) end # text is an array of Strings # Returns true iff a clip was added, # and only non-nil text can be added. def add_clip( text ) return false if text.nil? send_to_xclip text end # no-op. def each end # text is an array of Strings (lines) # Appends the lines to the current clip. # If no current clip, then a new clip is created. # Returns true iff the text was successfully appended. def append_to_clip( text ) return false if text.nil? last_clip = clip last_clip.pop if last_clip[ -1 ] == "" send_to_xclip last_clip + text end end end diakonos-0.9.0/lib/diakonos/clipboard.rb000066400000000000000000000017751161735554400202150ustar00rootroot00000000000000module Diakonos class Clipboard def initialize( max_clips ) @clips = Array.new @max_clips = max_clips end def [] ( arg ) @clips[ arg ] end def clip @clips[ 0 ] end # text is an array of Strings # Returns true iff a clip was added, # and only non-nil text can be added. def add_clip( text ) return false if text.nil? @clips.unshift text @clips.pop if @clips.length > @max_clips true end def each @clips.each do |clip| yield clip end end # text is an array of Strings (lines) # Appends the lines to the current clip. # If no current clip, then a new clip is created. # Returns true iff the text was successfully appended. def append_to_clip( text ) return false if text.nil? return add_clip( text ) if @clips.length == 0 last_clip = @clips[ 0 ] last_clip.pop if last_clip[ -1 ] == "" @clips[ 0 ] = last_clip + text true end end end diakonos-0.9.0/lib/diakonos/config.rb000066400000000000000000000353601161735554400175200ustar00rootroot00000000000000module Diakonos BOL_ZERO = 0 BOL_FIRST_CHAR = 1 BOL_ALT_ZERO = 2 BOL_ALT_FIRST_CHAR = 3 EOL_END = 0 EOL_LAST_CHAR = 1 EOL_ALT_END = 2 EOL_ALT_LAST_CHAR = 3 class Diakonos attr_reader :token_regexps, :close_token_regexps, :token_formats, :diakonos_conf, :column_markers, :surround_pairs, :settings def fetch_conf( location = "v#{VERSION}" ) require 'open-uri' found = false puts "Fetching configuration from #{location}..." begin open( "http://github.com/Pistos/diakonos/tree/#{location}/diakonos.conf?raw=true" ) do |http| text = http.read if text =~ /key/ and text =~ /colour/ and text =~ /lang/ found = true File.open( @diakonos_conf, 'w' ) do |f| f.puts text end end end rescue SocketError, OpenURI::HTTPError => e $stderr.puts "Failed to fetch from #{location}." end found end def load_configuration # Set defaults first conf_dir = INSTALL_SETTINGS[ :conf_dir ] @global_diakonos_conf = "#{conf_dir}/diakonos.conf" if ! @testing @diakonos_conf = @config_filename || "#{@diakonos_home}/diakonos.conf" if ! FileTest.exists?( @diakonos_conf ) if FileTest.exists?( @global_diakonos_conf ) puts "No personal configuration file found." puts "Would you like to copy the system-wide configuration file (#{@global_diakonos_conf}) to use" $stdout.print "as a basis for your personal configuration (recommended)? (y/n)"; $stdout.flush answer = $stdin.gets if answer =~ /^y/i require 'fileutils' FileUtils.cp @global_diakonos_conf, @diakonos_conf end else if @testing File.open( @diakonos_conf, 'w' ) do |f| f.puts File.read( './diakonos.conf' ) end else puts "diakonos.conf not found in any of:" puts " #{conf_dir}" puts " #{@diakonos_home}" puts "At least one configuration file must exist." $stdout.print "Would you like to download one right now from the Diakonos repository? (y/n)"; $stdout.flush answer = $stdin.gets case answer when /^y/i if not fetch_conf fetch_conf 'master' end end end if not FileTest.exists?( @diakonos_conf ) puts "Terminating due to lack of configuration file." exit 1 end end end end @logfilename = @diakonos_home + "/diakonos.log" @modes = { 'edit' => Mode.new, 'input' => Mode.new, } @token_regexps = Hash.new { |h,k| h[ k ] = Hash.new } @close_token_regexps = Hash.new { |h,k| h[ k ] = Hash.new } @token_formats = Hash.new { |h,k| h[ k ] = Hash.new } @column_markers = Hash.new { |h,k| h[ k ] = Hash.new } @indenters = Hash.new @indenters_next_line = Hash.new @unindenters = Hash.new @filemasks = Hash.new @bangmasks = Hash.new @closers = Hash.new @surround_pairs = Hash.new { |h,k| h[ k ] = Hash.new} @fuzzy_ignores = Array.new @settings = Hash.new @setting_strings = Hash.new # Setup some defaults @settings[ "context.format" ] = Curses::A_REVERSE @modes[ 'edit' ].keymap[ Curses::KEY_RESIZE ] = [ "redraw", nil ] @modes[ 'edit' ].keymap[ RESIZE2 ] = [ "redraw", nil ] @colour_pairs = Array.new @configs = [] @config_problems = [] parse_configuration_file @global_diakonos_conf parse_configuration_file @diakonos_conf languages = @surround_pairs.keys | @token_regexps.keys | @close_token_regexps.keys | @token_formats.keys languages.each do |language| @surround_pairs[ language ] = @surround_pairs[ 'all' ].merge( @surround_pairs[ language ] ) @token_regexps[ language ] = @token_regexps[ 'all' ].merge( @token_regexps[ language ] ) @close_token_regexps[ language ] = @close_token_regexps[ 'all' ].merge( @close_token_regexps[ language ] ) @token_formats[ language ] = @token_formats[ 'all' ].merge( @token_formats[ language ] ) end merge_session_settings case @settings[ 'clipboard.external' ] when 'klipper', 'klipper-dcop' @clipboard = ClipboardKlipper.new when 'klipper-dbus' @clipboard = ClipboardKlipperDBus.new when 'xclip' @clipboard = ClipboardXClip.new else @clipboard = Clipboard.new( @settings[ "max_clips" ] ) end @log = File.open( @logfilename, "a" ) if @buffers @buffers.each do |buffer| buffer.configure end end end def get_token_regexp( hash, arg, match ) language = match[ 1 ] token_class = match[ 2 ] case_insensitive = ( match[ 3 ] != nil ) hash[ language ] = ( hash[ language ] or Hash.new ) if case_insensitive hash[ language ][ token_class ] = Regexp.new( arg, Regexp::IGNORECASE ) else hash[ language ][ token_class ] = Regexp.new arg end end def map_key( arg, keymap = @modes['edit'].keymap ) return if arg.nil? if / / === arg keystrings, function_and_args = arg.split( / {2,}/, 2 ) else keystrings, function_and_args = arg.split( /;/, 2 ) end keystrokes = Array.new keystrings.split( /\s+/ ).each do |ks_str| codes = Keying.keycodes_for( ks_str ) if codes.empty? puts "Unknown keystring: #{ks_str}" else keystrokes.concat codes end end if function_and_args.nil? keymap.delete_key_path( keystrokes ) else function, function_args = function_and_args.split( /\s+/, 2 ) keymap.set_key_path( keystrokes, [ function, function_args ] ) end end # @param [String] filename_ the config file to parse # @param [String] including_filename the config file which calls include on this one # @return an Array of problem descriptions (Strings) def parse_configuration_file( filename_, including_filename = nil ) return if filename_.nil? begin filename = File.realpath( filename_ ) rescue Errno::ENOENT s = "Configuration file #{filename_.inspect} was not found" if including_filename s << " (referenced from #{including_filename.inspect}" end @config_problems << s return end return if @configs.any? { |c| c[:filename] == filename } @configs << { filename: filename, source: including_filename } IO.readlines( filename ).each_with_index do |line,line_number| line.chomp! # Skip comments next if line[ 0 ] == ?# if line =~ /^\s*(\S+)\s*=\s*(\S+)\s*$/ # Inheritance command, arg = $1, @setting_strings[ $2 ] end if arg.nil? command, arg = line.split( /\s+/, 2 ) next if command.nil? if arg.nil? @config_problems << "Configuration file #{filename.inspect} has an error on line #{line_number+1}" next end end command = command.downcase @setting_strings[ command ] = arg case command when "include" parse_configuration_file( File.expand_path( arg ), filename ) when 'load_extension' @extensions.load( arg ).each do |conf_file| parse_configuration_file conf_file end when /^lang\.(.+?)\.surround\.pair$/ language = $1 args = arg.split( /"\s+"/ ) args.map! do |s| s.gsub( /(? number, :fg => fg, :bg => bg } when /^lang\.(.+?)\.indent\.indenters(\.case_insensitive)?$/ case_insensitive = ( $2 != nil ) if case_insensitive @indenters[ $1 ] = Regexp.new( arg, Regexp::IGNORECASE ) else @indenters[ $1 ] = Regexp.new arg end when /^lang\.(.+?)\.indent\.indenters_next_line(\.case_insensitive)?$/ case_insensitive = ( $2 != nil ) if case_insensitive @indenters_next_line[ $1 ] = Regexp.new( arg, Regexp::IGNORECASE ) else @indenters_next_line[ $1 ] = Regexp.new arg end when /^lang\.(.+?)\.indent\.unindenters(\.case_insensitive)?$/ case_insensitive = ( $2 != nil ) if case_insensitive @unindenters[ $1 ] = Regexp.new( arg, Regexp::IGNORECASE ) else @unindenters[ $1 ] = Regexp.new arg end when /^lang\.(.+?)\.indent\.(?:preventers|ignore|not_indented)(\.case_insensitive)?$/, /^lang\.(.+?)\.context\.ignore(\.case_insensitive)?$/ case_insensitive = ( $2 != nil ) if case_insensitive @settings[ command ] = Regexp.new( arg, Regexp::IGNORECASE ) else @settings[ command ] = Regexp.new arg end when /^lang\.(.+?)\.filemask$/ @filemasks[ $1 ] = Regexp.new arg when /^lang\.(.+?)\.bangmask$/ @bangmasks[ $1 ] = Regexp.new arg when /^lang\.(.+?)\.closers\.(.+?)\.(.+?)$/ @closers[ $1 ] ||= Hash.new @closers[ $1 ][ $2 ] ||= Hash.new @closers[ $1 ][ $2 ][ $3.to_sym ] = case $3 when 'regexp' Regexp.new arg when 'closer' begin if arg =~ /^\{.+\}$/ eval( "Proc.new " + arg ) else arg end rescue Exception => e show_exception( e, [ "Failed to process Proc for #{command}.", ] ) end end when "context.visible", "context.combined", "eof_newline", "view.nonfilelines.visible", /^lang\.(.+?)\.indent\.(?:auto|roundup|using_tabs|closers)$/, "found_cursor_start", "convert_tabs", 'delete_newline_on_delete_to_eol', 'suppress_welcome', 'strip_trailing_whitespace_on_save', 'find.return_on_abort', 'fuzzy_file_find', 'view.line_numbers', 'find.show_context_after', 'view.pairs.highlight', 'open_as_first_buffer' @settings[ command ] = arg.to_b when "context.format", "context.separator.format", "status.format", 'view.line_numbers.format', 'view.non_search_area.format' @settings[ command ] = Display.to_formatting( arg ) when /view\.column_markers\.(.+?)\.format/ @column_markers[ $1 ][ :format ] = Display.to_formatting( arg ) when "logfile" @logfilename = File.expand_path( arg ) when "context.separator", /^lang\..+?\.indent\.ignore\.charset$/, /^lang\.(.+?)\.tokens\.([^.]+)\.change_to$/, /^lang\.(.+?)\.column_delimiters$/, "view.nonfilelines.character", 'diff_command', 'session.default_session', 'clipboard.external' @settings[ command ] = arg when /^lang\..+?\.comment_(?:close_)?string$/, 'view.line_numbers.number_format', "status.filler", "status.left", "status.right", "status.modified_str", "status.unnamed_str", "status.selecting_str", "status.read_only_str", 'interaction.blink_string' @settings[ command ] = arg.gsub( /^["']|["']$/, '' ) when "status.vars" @settings[ command ] = arg.split( /\s+/ ) when /^lang\.(.+?)\.indent\.size$/, /^lang\.(.+?)\.(?:tabsize|wrap_margin)$/, "context.max_levels", "context.max_segment_width", "max_clips", "max_undo_lines", "view.margin.x", "view.margin.y", "view.scroll_amount", "view.lookback", 'grep.context', 'view.line_numbers.width', 'fuzzy_file_find.max_files' @settings[ command ] = arg.to_i when "view.jump.x", "view.jump.y" @settings[ command ] = [ arg.to_i, 1 ].max when /view\.column_markers\.(.+?)\.column/ @column_markers[ $1 ][ :column ] = [ arg.to_i, 1 ].max when "bol_behaviour", "bol_behavior" case arg.downcase when "zero" @settings[ "bol_behaviour" ] = BOL_ZERO when "first-char" @settings[ "bol_behaviour" ] = BOL_FIRST_CHAR when "alternating-zero" @settings[ "bol_behaviour" ] = BOL_ALT_ZERO else # default @settings[ "bol_behaviour" ] = BOL_ALT_FIRST_CHAR end when "eol_behaviour", "eol_behavior" case arg.downcase when "end" @settings[ "eol_behaviour" ] = EOL_END when "last-char" @settings[ "eol_behaviour" ] = EOL_LAST_CHAR when "alternating-last-char" @settings[ "eol_behaviour" ] = EOL_ALT_FIRST_CHAR else # default @settings[ "eol_behaviour" ] = EOL_ALT_END end when "context.delay", 'interaction.blink_duration', 'interaction.choice_delay' @settings[ command ] = arg.to_f when 'fuzzy_file_find.ignore' @fuzzy_ignores << arg end end end end end diakonos-0.9.0/lib/diakonos/core-ext/000077500000000000000000000000001161735554400174455ustar00rootroot00000000000000diakonos-0.9.0/lib/diakonos/core-ext/bignum.rb000066400000000000000000000000531161735554400212510ustar00rootroot00000000000000class Bignum def ord self end end diakonos-0.9.0/lib/diakonos/core-ext/enumerable.rb000066400000000000000000000006311161735554400221110ustar00rootroot00000000000000module Enumerable # Returns [array-index, string-index, string-index] triples for each match. def grep_indices( regexp ) array = Array.new each_with_index do |element,index| element.scan( regexp ) do |match_text| match = Regexp.last_match strindex = match.begin( 0 ) array.push [ index, strindex, strindex + match[ 0 ].length ] end end array end end diakonos-0.9.0/lib/diakonos/core-ext/fixnum.rb000066400000000000000000000002571161735554400213040ustar00rootroot00000000000000class Fixnum def fit( min, max ) return self if max < min return min if self < min return max if self > max return self end def ord self end end diakonos-0.9.0/lib/diakonos/core-ext/hash.rb000066400000000000000000000024031161735554400207140ustar00rootroot00000000000000class Hash # path is an array of hash keys # This method deletes a path of hash keys, with each step in the path # being a recursively deeper key in a hash tree. # Returns the possibly modified hash. def delete_key_path( path ) if path.length > 1 subtree = self[ path[ 0 ] ] if subtree.respond_to?( :delete_key_path ) subtree.delete_key_path( path[ 1..-1 ] ) if subtree.empty? delete( path[ 0 ] ) end end elsif path.length == 1 delete( path[ 0 ] ) end self end def set_key_path( path, leaf ) if path.length > 1 node = self[ path[ 0 ] ] if not node.respond_to?( :set_key_path ) node = self[ path[ 0 ] ] = Hash.new end node.set_key_path( path[ 1..-1 ], leaf ) elsif path.length == 1 self[ path[ 0 ] ] = leaf end self end def get_node( path ) node = self[ path[ 0 ] ] if path.length > 1 if node and node.respond_to?( :get_node ) return node.get_node( path[ 1..-1 ] ) end elsif path.length == 1 return node end nil end def get_leaf( path ) node = get_node( path ) if node.respond_to?( :get_node ) # Only want a leaf node nil else node end end end diakonos-0.9.0/lib/diakonos/core-ext/object.rb000066400000000000000000000001231161735554400212340ustar00rootroot00000000000000class Object def deep_clone Marshal::load( Marshal.dump( self ) ) end end diakonos-0.9.0/lib/diakonos/core-ext/regexp.rb000066400000000000000000000000751161735554400212660ustar00rootroot00000000000000class Regexp def uses_bos source[ 0 ] == ?^ end end diakonos-0.9.0/lib/diakonos/core-ext/string.rb000066400000000000000000000057171161735554400213120ustar00rootroot00000000000000class String def to_b case downcase when "true", "t", "1", "yes", "y", "on", "+" true else false end end def expand_tabs( tab_size ) s = dup while s.sub!( /\t/ ) { |match_text| match = Regexp.last_match index = match.begin( 0 ) " " * ( tab_size - ( index % tab_size ) ) } end s end def newline_split retval = split( /\\n/ ) if self =~ /\\n$/ retval << "" end if retval.length > 1 retval[ 0 ] << "$" retval[ 1..-2 ].collect do |el| "^" << el << "$" end retval[ -1 ] = "^" << retval[ -1 ] end retval end # Works like normal String#index except returns the index # of the first matching regexp group if one or more groups are specified # in the regexp. Both the index and the matched text are returned. def group_index( regexp, offset = 0 ) if regexp.class != Regexp return index( regexp, offset ) end i = nil match_text = nil working_offset = 0 loop do index( regexp, working_offset ) match = Regexp.last_match if match i = match.begin( 0 ) match_text = match[ 0 ] if match.length > 1 # Find first matching group 1.upto( match.length - 1 ) do |match_item_index| if match[ match_item_index ] i = match.begin( match_item_index ) match_text = match[ match_item_index ] break end end end break if i >= offset else i = nil break end working_offset += 1 end [ i, match_text ] end # Works like normal String#rindex except returns the index # of the first matching regexp group if one or more groups are specified # in the regexp. Both the index and the matched text are returned. def group_rindex( regexp, offset = length ) if regexp.class != Regexp return rindex( regexp, offset ) end i = nil match_text = nil working_offset = length loop do rindex( regexp, working_offset ) match = Regexp.last_match if match i = match.end( 0 ) - 1 match_text = match[ 0 ] if match.length > 1 # Find first matching group 1.upto( match.length - 1 ) do |match_item_index| if match[ match_item_index ] i = match.end( match_item_index ) - 1 match_text = match[ match_item_index ] break end end end if match_text == "" # Assume that an empty string means that it matched $ i += 1 end break if i <= offset else i = nil break end working_offset -= 1 end [ i, match_text ] end end diakonos-0.9.0/lib/diakonos/ctag.rb000066400000000000000000000010241161735554400171570ustar00rootroot00000000000000module Diakonos class CTag attr_reader :file, :command, :kind, :rest def initialize( file, command, kind, rest ) @file = file @command = command @kind = kind @rest = rest end def to_s "#{@file}:#{@command} (#{@kind}) #{@rest}" end def == ( other ) ( other and @file == other.file and @command == other.command and @kind == other.kind and @rest == other.rest ) end end enddiakonos-0.9.0/lib/diakonos/cursor.rb000066400000000000000000000011351161735554400175610ustar00rootroot00000000000000module Diakonos class Diakonos def cursor_stack_remove_buffer( buffer ) @cursor_stack.delete_if { |frame| frame[ :buffer ] == buffer } end def push_cursor_state( top_line, row, col, clear_stack_pointer = CLEAR_STACK_POINTER ) new_state = { buffer: buffer_current, top_line: top_line, row: row, col: col } if ! @cursor_stack.include? new_state @cursor_stack << new_state if clear_stack_pointer @cursor_stack_pointer = nil end clear_non_movement_flag end end end enddiakonos-0.9.0/lib/diakonos/display.rb000066400000000000000000000247401161735554400177200ustar00rootroot00000000000000module Diakonos DO_REDRAW = true DONT_REDRAW = false class Diakonos attr_reader :win_main, :display_mutex, :win_line_numbers def cleanup_display return if @testing @win_main.close if @win_main @win_status.close if @win_status @win_interaction.close if @win_interaction @win_context.close if @win_context @win_line_numbers.close if @win_line_numbers Curses::close_screen end def initialize_display if ! @testing cleanup_display Curses::init_screen Curses::nonl Curses::raw Curses::noecho if Curses::has_colors? Curses::start_color Curses::init_pair( Curses::COLOR_BLACK, Curses::COLOR_BLACK, Curses::COLOR_BLACK ) Curses::init_pair( Curses::COLOR_RED, Curses::COLOR_RED, Curses::COLOR_BLACK ) Curses::init_pair( Curses::COLOR_GREEN, Curses::COLOR_GREEN, Curses::COLOR_BLACK ) Curses::init_pair( Curses::COLOR_YELLOW, Curses::COLOR_YELLOW, Curses::COLOR_BLACK ) Curses::init_pair( Curses::COLOR_BLUE, Curses::COLOR_BLUE, Curses::COLOR_BLACK ) Curses::init_pair( Curses::COLOR_MAGENTA, Curses::COLOR_MAGENTA, Curses::COLOR_BLACK ) Curses::init_pair( Curses::COLOR_CYAN, Curses::COLOR_CYAN, Curses::COLOR_BLACK ) Curses::init_pair( Curses::COLOR_WHITE, Curses::COLOR_WHITE, Curses::COLOR_BLACK ) @colour_pairs.each do |cp| Curses::init_pair( cp[ :number ], cp[ :fg ], cp[ :bg ] ) end end end if settings[ 'view.line_numbers' ] @win_line_numbers = ::Diakonos::Window.new( main_window_height, settings[ 'view.line_numbers.width' ], 0, 0 ) @win_main = ::Diakonos::Window.new( main_window_height, Curses::cols - settings[ 'view.line_numbers.width' ], 0, settings[ 'view.line_numbers.width' ] ) else @win_main = ::Diakonos::Window.new( main_window_height, Curses::cols, 0, 0 ) @win_line_numbers = nil end @win_status = ::Diakonos::Window.new( 1, Curses::cols, Curses::lines - 2, 0 ) @win_status.attrset @settings[ 'status.format' ] @win_interaction = ::Diakonos::Window.new( 1, Curses::cols, Curses::lines - 1, 0 ) if @settings[ 'context.visible' ] if @settings[ 'context.combined' ] pos = 1 else pos = 3 end @win_context = ::Diakonos::Window.new( 1, Curses::cols, Curses::lines - pos, 0 ) else @win_context = nil end if ! @testing @win_main.keypad( true ) @win_status.keypad( true ) @win_interaction.keypad( true ) if @win_line_numbers @win_line_numbers.keypad( true ) end if @win_context @win_context.keypad( true ) end end @modes[ 'edit' ].window = @win_main @modes[ 'input' ].window = @win_interaction @win_interaction.refresh @win_main.refresh if @win_line_numbers @win_line_numbers.refresh end if @buffers @buffers.each do |buffer| buffer.reset_display end end end def redraw load_configuration initialize_display update_status_line update_context_line display_buffer buffer_current end def main_window_height # One line for the status line # One line for the input line # One line for the context line retval = Curses::lines - 2 if @settings[ "context.visible" ] and not @settings[ "context.combined" ] retval = retval - 1 end retval end def main_window_width Curses::cols end # Display text on the interaction line. def set_iline( string = "" ) return if @testing return if @readline @iline = string Curses::curs_set 0 @win_interaction.setpos( 0, 0 ) @win_interaction.addstr( "%-#{Curses::cols}s" % @iline ) @win_interaction.refresh Curses::curs_set 1 string.length end def set_iline_if_empty( string ) if @iline.nil? || @iline.empty? set_iline string end end def set_status_variable( identifier, value ) @status_vars[ identifier ] = value end def build_status_line( truncation = 0 ) var_array = Array.new @settings[ "status.vars" ].each do |var| case var when "buffer_number" var_array.push buffer_to_number( buffer_current ) when "col" var_array.push( buffer_current.last_screen_col + 1 ) when "filename" name = buffer_current.nice_name var_array.push name[ ([ truncation, name.length ].min)..-1 ] when "modified" if buffer_current.modified? var_array.push @settings[ "status.modified_str" ] else var_array.push "" end when "num_buffers" var_array.push @buffers.length when "num_lines" var_array.push buffer_current.length when "row", "line" var_array.push( buffer_current.last_row + 1 ) when "read_only" if buffer_current.read_only var_array.push @settings[ "status.read_only_str" ] else var_array.push "" end when "selecting" if buffer_current.changing_selection var_array.push @settings[ "status.selecting_str" ] else var_array.push "" end when 'selection_mode' case buffer_current.selection_mode when :block var_array.push 'block' else var_array.push '' end when 'session_name' var_array.push @session[ 'name' ] when "type" var_array.push buffer_current.original_language when /^@/ var_array.push @status_vars[ var ] end end str = nil begin status_left = @settings[ "status.left" ] field_count = status_left.count "%" status_left = status_left % var_array[ 0...field_count ] status_right = @settings[ "status.right" ] % var_array[ field_count..-1 ] filler_string = @settings[ "status.filler" ] fill_amount = (Curses::cols - status_left.length - status_right.length) / filler_string.length if fill_amount > 0 filler = filler_string * fill_amount else filler = "" end str = status_left + filler + status_right rescue ArgumentError, TypeError => e debug_log e debug_log e.backtrace[ 0 ] debug_log "var_array: #{var_array.inspect}" str = "%-#{Curses::cols}s" % "(status line configuration error)" end str end protected :build_status_line def update_status_line return if @testing str = build_status_line if str.length > Curses::cols str = build_status_line( str.length - Curses::cols ) end Curses::curs_set 0 @win_status.setpos( 0, 0 ) @win_status.addstr str @win_status.refresh Curses::curs_set 1 end def update_context_line return if @testing return if @win_context.nil? @context_thread.exit if @context_thread @context_thread = Thread.new do context = buffer_current.context Curses::curs_set 0 @win_context.setpos( 0, 0 ) chars_printed = 0 if context.length > 0 truncation = [ @settings[ "context.max_levels" ], context.length ].min max_length = [ ( Curses::cols / truncation ) - @settings[ "context.separator" ].length, ( @settings[ "context.max_segment_width" ] or Curses::cols ) ].min line = nil context_subset = context[ 0...truncation ] context_subset = context_subset.collect do |line| line.strip[ 0...max_length ] end context_subset.each do |line| @win_context.attrset @settings[ "context.format" ] @win_context.addstr line chars_printed += line.length @win_context.attrset @settings[ "context.separator.format" ] @win_context.addstr @settings[ "context.separator" ] chars_printed += @settings[ "context.separator" ].length end end @iline_mutex.synchronize do @win_context.attrset @settings[ "context.format" ] @win_context.addstr( " " * ( Curses::cols - chars_printed ) ) @win_context.refresh end @display_mutex.synchronize do @win_main.setpos( buffer_current.last_screen_y, buffer_current.last_screen_x ) @win_main.refresh end Curses::curs_set 1 end @context_thread.priority = -2 end def display_buffer( buffer ) return if @testing return if ! @do_display Thread.new do if ! @display_mutex.try_lock @display_queue_mutex.synchronize do @display_queue = buffer end else begin Curses::curs_set 0 buffer.display Curses::curs_set 1 rescue Exception => e $diakonos.log( "Display Exception:" ) $diakonos.log( e.message ) $diakonos.log( e.backtrace.join( "\n" ) ) show_exception e end @display_mutex.unlock @display_queue_mutex.synchronize do if @display_queue b = @display_queue @display_queue = nil display_buffer b end end end end end def show_message( message, non_interaction_duration = @settings[ 'interaction.choice_delay' ] ) terminate_message @message_expiry = Time.now + non_interaction_duration @message_thread = Thread.new do time_left = @message_expiry - Time.now while time_left > 0 set_iline "(#{time_left.round}) #{message}" @win_main.setpos( @saved_main_y, @saved_main_x ) sleep 1 time_left = @message_expiry - Time.now end set_iline message @win_main.setpos( @saved_main_y, @saved_main_x ) end end def terminate_message if @message_thread and @message_thread.alive? @message_thread.terminate @message_thread = nil end end def refresh_all @win_main.refresh if @win_context @win_context.refresh end @win_status.refresh @win_interaction.refresh if @win_line_numbers @win_line_numbers.refresh end end end end diakonos-0.9.0/lib/diakonos/display/000077500000000000000000000000001161735554400173645ustar00rootroot00000000000000diakonos-0.9.0/lib/diakonos/display/format.rb000066400000000000000000000041611161735554400212030ustar00rootroot00000000000000module Diakonos module Display def self.to_colour_constant( str ) case str.downcase when "black", "0" Curses::COLOR_BLACK when "red", "1" Curses::COLOR_RED when "green", "2" Curses::COLOR_GREEN when "yellow", "brown", "3" Curses::COLOR_YELLOW when "blue", "4" Curses::COLOR_BLUE when "magenta", "purple", "5" Curses::COLOR_MAGENTA when "cyan", "6" Curses::COLOR_CYAN when "white", "7" Curses::COLOR_WHITE else str.to_i end end def self.to_formatting( str ) formatting = Curses::A_NORMAL str.split( /\s+/ ).each do |format| colour_number = format.to_i if colour_number > Curses::COLOR_WHITE formatting |= Curses::color_pair( colour_number ) elsif format.downcase == 'normal' formatting = Curses::A_NORMAL else formatting |= case format.downcase when "black", "0" Curses::color_pair( Curses::COLOR_BLACK ) when "red", "1" Curses::color_pair( Curses::COLOR_RED ) when "green", "2" Curses::color_pair( Curses::COLOR_GREEN ) when "yellow", "brown", "3" Curses::color_pair( Curses::COLOR_YELLOW ) when "blue", "4" Curses::color_pair( Curses::COLOR_BLUE ) when "magenta", "purple", "5" Curses::color_pair( Curses::COLOR_MAGENTA ) when "cyan", "6" Curses::color_pair( Curses::COLOR_CYAN ) when "white", "7" Curses::color_pair( Curses::COLOR_WHITE ) when "standout", "s", "so" Curses::A_STANDOUT when "underline", "u", "un", "ul" Curses::A_UNDERLINE when "reverse", "r", "rev", "inverse", "i", "inv" Curses::A_REVERSE when "blink", "bl", "blinking" Curses::A_BLINK when "dim", "d" Curses::A_DIM when "bold", "b", "bo" Curses::A_BOLD else 0 end end end formatting end end enddiakonos-0.9.0/lib/diakonos/extension-set.rb000066400000000000000000000023211161735554400210470ustar00rootroot00000000000000module Diakonos class ExtensionSet def initialize( root_dir ) @extensions = Hash.new @root_dir = File.expand_path( root_dir ) end def scripts @extensions.values.find_all { |e| e }.map { |e| e.scripts }.flatten end # @return an Array of configuration filenames to parse def load( dir ) @extensions[ dir ] = false confs_to_parse = [] ext_dir = File.join( @root_dir, dir ) info = YAML.load_file( File.join( ext_dir, 'info.yaml' ) ) if info[ 'requirements' ] && info[ 'requirements' ][ 'diakonos' ] this_version = ::Diakonos.parse_version( ::Diakonos::VERSION ) min_version = ::Diakonos.parse_version( info[ 'requirements' ][ 'diakonos' ][ 'minimum' ] ) if min_version && this_version >= min_version extension = Extension.new( ext_dir ) @extensions[ dir ] = extension confs_to_parse += extension.confs end end confs_to_parse end def loaded?( ext_dir ) @extensions[ ext_dir ] end def loaded_extensions @extensions.values.find_all { |e| e } end def not_loaded_extensions @extensions.keys.find_all { |e| ! loaded?( e ) } end end enddiakonos-0.9.0/lib/diakonos/extension.rb000066400000000000000000000011561161735554400202630ustar00rootroot00000000000000module Diakonos class Extension attr_reader :dir, :scripts, :confs def initialize( dir ) @scripts = [] @confs = [] @dir = File.basename( dir ) @info = YAML.load_file( File.join( dir, 'info.yaml' ) ) Dir[ File.join( dir, '**', '*.rb' ) ].each do |ext_file| @scripts << ext_file end Dir[ File.join( dir, "*.conf" ) ].each do |conf_file| @confs << conf_file end end def []( key ) @info[ key ] end [ 'name', 'description', 'version' ].each do |m| define_method( m ) do @info[ m ] end end end enddiakonos-0.9.0/lib/diakonos/finding.rb000066400000000000000000000011641161735554400176640ustar00rootroot00000000000000module Diakonos class Finding attr_reader :start_row, :start_col, :end_row, :end_col attr_writer :end_row, :end_col def initialize( start_row, start_col, end_row, end_col ) @start_row = start_row @start_col = start_col @end_row = end_row @end_col = end_col end def match( regexps, lines ) retval = true i = @start_row + 1 regexps[ 1..-1 ].each do |re| if lines[ i ] !~ re retval = false break end @end_row = i @end_col = Regexp.last_match[ 0 ].length i += 1 end retval end end enddiakonos-0.9.0/lib/diakonos/functions-deprecated.rb000066400000000000000000000077561161735554400223710ustar00rootroot00000000000000module Diakonos class Diakonos alias_method :loadConfiguration, :load_configuration end module Functions alias_method :addNamedBookmark, :add_named_bookmark alias_method :anchorSelection, :anchor_selection alias_method :carriageReturn, :carriage_return alias_method :changeSessionSetting, :change_session_setting alias_method :clearMatches, :clear_matches alias_method :closeFile, :close_buffer alias_method :close_file, :close_buffer alias_method :collapseWhitespace, :collapse_whitespace alias_method :copySelection, :copy_selection alias_method :cursorDown, :cursor_down alias_method :cursorLeft, :cursor_left alias_method :cursorRight, :cursor_right alias_method :cursorUp, :cursor_up alias_method :cursorBOF, :cursor_bof alias_method :cursorBOL, :cursor_bol alias_method :cursorEOL, :cursor_eol alias_method :cursorEOF, :cursor_eof alias_method :cursorTOV, :cursor_tov alias_method :cursorBOV, :cursor_bov alias_method :cursorReturn, :cursor_return alias_method :cutSelection, :cut_selection alias_method :deleteAndStoreLine, :delete_and_store_line alias_method :deleteLine, :delete_line alias_method :deleteToEOL, :delete_to_eol alias_method :findAgain, :find_again alias_method :findAndReplace, :search_and_replace alias_method :findExact, :find_exact alias_method :goToLineAsk, :go_to_line_ask alias_method :goToNamedBookmark, :go_to_named_bookmark alias_method :goToNextBookmark, :go_to_next_bookmark alias_method :goToPreviousBookmark, :go_to_previous_bookmark alias_method :goToTag, :go_to_tag alias_method :goToTagUnderCursor, :go_to_tag_under_cursor alias_method :insertSpaces, :insert_spaces alias_method :insertTab, :insert_tab alias_method :joinLines, :join_lines alias_method :loadScript, :load_script alias_method :newFile, :open_file alias_method :openFile, :open_file alias_method :openFileAsk, :open_file_ask alias_method :operateOnString, :operate_on_string alias_method :operateOnLines, :operate_on_lines alias_method :operateOnEachLine, :operate_on_each_line alias_method :pageUp, :page_up alias_method :pageDown, :page_down alias_method :parsedIndent, :parsed_indent alias_method :playMacro, :play_macro alias_method :popTag, :pop_tag alias_method :printKeychain, :print_keychain alias_method :removeNamedBookmark, :remove_named_bookmark alias_method :removeSelection, :remove_selection alias_method :repeatLast, :repeat_last alias_method :saveFile, :save_file alias_method :saveFileAs, :save_file_as alias_method :scrollDown, :scroll_down alias_method :scrollUp, :scroll_up alias_method :searchAndReplace, :search_and_replace alias_method :setBufferType, :set_buffer_type alias_method :setReadOnly, :set_read_only alias_method :showClips, :show_clips alias_method :pasteShellResult, :paste_shell_result alias_method :toggleMacroRecording, :toggle_macro_recording alias_method :switchToBufferNumber, :switch_to_buffer_number alias_method :switchToNextBuffer, :switch_to_next_buffer alias_method :switchToPreviousBuffer, :switch_to_previous_buffer alias_method :toggleBookmark, :toggle_bookmark alias_method :toggleSelection, :toggle_selection alias_method :toggleSessionSetting, :toggle_session_setting end enddiakonos-0.9.0/lib/diakonos/functions.rb000066400000000000000000000210171161735554400202550ustar00rootroot00000000000000module Diakonos # The Diakonos::Functions module contains all the methods that can be mapped # to keys in Diakonos. New methods can be added to this module by # extensions. module Functions # Shows the About page, which gives information on Diakonos. def about about_write open_file @about_filename end # Deletes characters up to, but not including, a given character. # Also puts the deleted text into the clipboard. def delete_to( char = nil ) if char.nil? set_iline "Type character to delete to..." char = @win_main.getch set_iline end if char removed_text = buffer_current.delete_to char if removed_text @clipboard.add_clip removed_text else set_iline "'#{char}' not found." end end end # Deletes characters starting from (but not including) a given character # up to (but not including) the current cursor position. # Also puts the deleted text into the clipboard. def delete_from( char = nil ) if char.nil? set_iline "Type character to delete from..." char = @win_main.getch set_iline end if char removed_text = buffer_current.delete_from(char) if removed_text @clipboard.add_clip removed_text else set_iline "'#{char}' not found." end end end # Deletes characters between, but not including, a given pair of # characters. Also puts the deleted text into the clipboard. # Brace characters are intelligently matched with their opposite-side # counterparts if the left-side brace is given (e.g. '['). def delete_to_and_from( inclusive = nil, char = nil ) if char.nil? set_iline "Type character to delete to and from..." char = @win_main.getch set_iline end if char removed_text = buffer_current.delete_to_and_from( char, inclusive == :inclusive ? INCLUSIVE : NOT_INCLUSIVE ) if removed_text @clipboard.add_clip( [ removed_text ] ) else set_iline "'#{char}' not found." end end end # Evaluates (executes) Ruby code. def evaluate( code_ = nil ) if code_.nil? if buffer_current.changing_selection selected_text = buffer_current.copy_selection[ 0 ] end code = get_user_input( "Ruby code: ", history: @rlh_general, initial_text: selected_text || "", completion_array: ::Diakonos::Functions.public_instance_methods.map { |m| m.to_s } ) else code = code_ end if code begin eval code rescue Exception => e show_exception( e, [ "The code given to evaluate has a syntax error.", "The code given to evaluate refers to a Diakonos command which does not exist, or is misspelled.", "The code given to evaluate refers to a Diakonos command with missing arguments.", "The code given to evaluate refers to a variable or method which does not exist.", ] ) end end end # Starts the interactive help system. def help( prefill = '' ) if ! File.exist?( @help_dir ) || Dir[ "#{@help_dir}/*" ].size == 0 set_iline 'There are no help files installed.' return end open_help_buffer matching_docs = nil selected = get_user_input( "Search terms: ", history: @rlh_help, initial_text: prefill, completion_array: @help_tags ) { |input| next if input.length < 3 and input[ 0..0 ] != '/' matching_docs = matching_help_documents( input ) with_list_file do |list| list.puts matching_docs.join( "\n" ) end open_list_buffer } close_help_buffer case selected when /\|/ open_help_document selected when nil # Help search aborted; do nothing else # Not a selected help document if matching_docs.nil? or matching_docs.empty? matching_docs = matching_help_documents( selected ) end case matching_docs.size when 1 open_help_document matching_docs[ 0 ] when 0 File.open( @error_filename, 'w' ) do |f| f.puts "There were no help documents matching your search." f.puts "(#{selected.strip})" end error_file = open_file( @error_filename ) choice = get_choice( "Would you like to send your search terms over the Internet to help improve Diakonos?", [ CHOICE_YES, CHOICE_NO ] ) case choice when CHOICE_YES require 'net/http' require 'uri' res = Net::HTTP.post_form( URI.parse( 'http://dh.pist0s.ca/' ), { 'q' => selected } ) # TODO: let them choose "never" and "always" end close_buffer error_file else help selected end end end # Loads Ruby code from file using Kernel#load. def load_script( name_ = nil ) if name_.nil? name = get_user_input( "File to load as script: ", history: @rlh_files ) else name = name_ end if name thread = Thread.new( name ) do |f| begin load( f ) rescue Exception => e show_exception( e, [ "The filename given does not exist.", "The filename given is not accessible or readable.", "The loaded script does not reference Diakonos commands as members of the global Diakonos object. e.g. cursor_bol instead of $diakonos.cursor_bol", "The loaded script has syntax errors.", "The loaded script references objects or object members which do not exist." ] ) end set_iline "Loaded script '#{name}'." end loop do if thread.status != "run" break else sleep 0.1 end end thread.join end end def play_macro( name = nil ) macro, input_history = @macros[ name ] if input_history @macro_input_history = input_history.deep_clone if macro @playing_macro = true macro.each do |command| eval command end @playing_macro = false @macro_input_history = nil end end end def print_mapped_function @capturing_mapping = true set_iline "Type any chain of keystrokes or key chords, or press Enter to stop." end def print_keychain @capturing_keychain = true set_iline "Type any chain of keystrokes or key chords, then press Enter..." end # Quits Diakonos (gracefully). def quit @quitting = true to_all = nil save_session @buffers.each do |buffer| next if ! buffer.modified? switch_to buffer closure_choice = close_buffer( buffer, to_all ) case closure_choice when CHOICE_CANCEL @quitting = false break when CHOICE_YES_TO_ALL, CHOICE_NO_TO_ALL to_all = closure_choice end end end def repeat_last eval @functions_last[ -1 ] if not @functions_last.empty? end # Send the Diakonos job to background, as if with Ctrl-Z def suspend Curses::close_screen Process.kill( "SIGSTOP", $PID ) Curses::init_screen refresh_all end # Starts or stops macro recording. def toggle_macro_recording( name = nil ) if @macro_history stop_recording_macro else start_recording_macro name end end # Undoes the latest change made to the current buffer, # or reopens the file that was just closed. def undo( buffer = buffer_current ) if @functions_last[-1] == 'close_buffer' open_file( @buffer_closed.name, 'cursor' => { 'row' => @buffer_closed.last_row, 'col' => @buffer_closed.last_col, }, 'display' => { 'top_line' => @buffer_closed.top_line, 'left_col' => @buffer_closed.left_column, } ) else buffer.undo end end # Redoes the latest change undone on the current buffer. def unundo( buffer = buffer_current ) buffer.unundo end end end diakonos-0.9.0/lib/diakonos/functions/000077500000000000000000000000001161735554400177275ustar00rootroot00000000000000diakonos-0.9.0/lib/diakonos/functions/basics.rb000066400000000000000000000014741161735554400215260ustar00rootroot00000000000000module Diakonos module Functions # Move one character left, then delete one character. # # @see Diakonos::Buffer#delete def backspace if( buffer_current.changing_selection || cursor_left( Buffer::STILL_TYPING ) ) delete end end # Insert a carriage return (newline) at the current cursor location. # Deletes any currently selected text. def carriage_return buffer_current.carriage_return buffer_current.delete_selection end # Calls Buffer#delete on the current buffer. def delete buffer_current.delete end # Deletes the current line and adds it to the clipboard. def delete_line removed_text = buffer_current.delete_line if removed_text @clipboard.add_clip( [ removed_text, "" ] ) end end end enddiakonos-0.9.0/lib/diakonos/functions/bookmarking.rb000066400000000000000000000025521161735554400225630ustar00rootroot00000000000000module Diakonos module Functions def add_named_bookmark( name_ = nil ) if name_.nil? name = get_user_input "Bookmark name: " else name = name_ end if name @bookmarks[ name ] = Bookmark.new( buffer_current, buffer_current.current_row, buffer_current.current_column, name ) set_iline "Added bookmark #{@bookmarks[ name ].to_s}." end end def go_to_named_bookmark( name_ = nil ) if name_.nil? name = get_user_input "Bookmark name: " else name = name_ end if name bookmark = @bookmarks[ name ] if bookmark switch_to( bookmark.buffer ) bookmark.buffer.cursor_to( bookmark.row, bookmark.col, Buffer::DO_DISPLAY ) else set_iline "No bookmark named '#{name}'." end end end def go_to_next_bookmark buffer_current.go_to_next_bookmark end def go_to_previous_bookmark buffer_current.go_to_previous_bookmark end def remove_named_bookmark( name_ = nil ) if name_.nil? name = get_user_input "Bookmark name: " else name = name_ end if name bookmark = @bookmarks.delete name set_iline "Removed bookmark #{bookmark.to_s}." end end def toggle_bookmark buffer_current.toggle_bookmark end end enddiakonos-0.9.0/lib/diakonos/functions/buffers.rb000066400000000000000000000335201161735554400217130ustar00rootroot00000000000000module Diakonos module Functions # Closes a buffer. # # @param [Diakonos::Buffer] buffer # The buffer to close. If no buffer is provided, defaults to the current buffer. # @param [Fixnum] to_all # The CHOICE to assume for the prompt. # @return [Fixnum] the choice the user made, or nil if the user was not prompted to choose. # @see Diakonos::CHOICE_YES # @see Diakonos::CHOICE_NO def close_buffer( buffer = buffer_current, to_all = nil ) return nil if buffer.nil? choice = nil if ! @buffers.include?( buffer ) log "No such buffer: #{buffer.name}" return nil end do_closure = true if buffer.modified? && ! buffer.read_only if to_all choice = to_all else choices = [ CHOICE_YES, CHOICE_NO, CHOICE_CANCEL ] if @quitting choices.concat [ CHOICE_YES_TO_ALL, CHOICE_NO_TO_ALL ] end choice = get_choice( "Save changes to #{buffer.nice_name}?", choices, CHOICE_CANCEL ) end case choice when CHOICE_YES, CHOICE_YES_TO_ALL do_closure = true save_file buffer when CHOICE_NO, CHOICE_NO_TO_ALL do_closure = true when CHOICE_CANCEL do_closure = false end end if do_closure del_buffer = nil previous_buffer = nil to_switch_to = nil switching = false # Search the buffer hash for the buffer we want to delete, # and mark the one we will switch to after deletion. @buffers.each do |b| if switching to_switch_to = b break end if b == buffer del_buffer = b switching = true next end previous_buffer = b end buf = nil while( @buffer_stack.any? && ! @buffers.include?( buf ) || buf == del_buffer ) do buf = @buffer_stack.pop end if @buffers.include?( buf ) to_switch_to = buf end if to_switch_to switch_to to_switch_to elsif previous_buffer switch_to previous_buffer else # No buffers left. Open a new blank one. open_file end @buffer_closed = del_buffer @buffers.delete del_buffer cursor_stack_remove_buffer del_buffer save_session update_status_line update_context_line end choice end # Opens the special "buffer selection" buffer, and prompts the user # to select a buffer. The user can select a buffer either with the # arrow keys and the Enter key, or by pressing the key corresponding # to an index presented in a left-hand column in the list. def list_buffers bullets = ( ('0'..'9').to_a + ('a'..'z').to_a ).map { |s| "#{s} " } buffers_unnamed = @buffers.find_all { |b| b.name.nil? } buffers_named = @buffers.find_all { |b| b.name } with_list_file do |f| if buffers_unnamed.size == 1 bullet = bullets.shift f.puts "#{bullet}(unnamed buffer)" else buffers_unnamed.each_with_index do |b,i| bullet = bullets.shift f.puts "#{bullet}(unnamed buffer #{i+1})" end end buffers_named.collect { |b| b.name }.sort.each_with_index do |name, index| bullet = bullets.shift f.puts "#{bullet}#{name}" end end open_list_buffer filename = get_user_input( "Switch to buffer: ", numbered_list: true ) buffer = buffers_named.find { |b| b.name == filename } if buffer switch_to buffer elsif filename =~ /\(unnamed buffer( \d+)?/ switch_to( buffers_unnamed[ $1.to_i - 1 ] ) end end # Opens a file into a new Buffer. # @param filename # The file to open. If nil, an empty, unnamed buffer is opened. # @param [Hash] meta # metadata containing additional information on how to open the file # @option meta [Hash] 'cursor' (nil) # A Hash containing the 'row' and 'col' to position the cursor after opening. # @option meta [Hash] 'display' (nil) # A Hash containing the 'top_line' and 'left_column' to use to position # the view after opening. # @option meta [Boolean] 'read_only' (false) # Whether to open the file in read-only (unmodifiable) mode # @option meta [Boolean] 'revert' (false) # Whether to skip asking about reverting to on-disk file contents (if different) # @return [Buffer] the buffer of the opened file # @return [NilClass] nil on failure def open_file( filename = nil, meta = {} ) read_only = !!meta[ 'read_only' ] force_revert = meta[ 'revert' ] || ASK_REVERT if meta[ 'cursor' ] last_row = meta[ 'cursor' ][ 'row' ] last_col = meta[ 'cursor' ][ 'col' ] end if meta[ 'display' ] top_line = meta[ 'display' ][ 'top_line' ] left_column = meta[ 'display' ][ 'left_column' ] end do_open = true buffer = nil if filename filename, last_row_ = parse_filename_and_line_number( filename ) last_row = last_row_ || last_row existing_buffer = @buffers.find { |b| b.name == filename } if existing_buffer do_open = force_revert || ( filename =~ /\.diakonos/ ) switch_to existing_buffer if ! do_open && existing_buffer.file_different? show_buffer_file_diff( existing_buffer ) do choice = get_choice( "Load on-disk version of #{existing_buffer.nice_name}?", [ CHOICE_YES, CHOICE_NO ] ) case choice when CHOICE_YES do_open = true when CHOICE_NO do_open = false end end end end if FileTest.exist?( filename ) # Don't try to open non-files (i.e. directories, pipes, sockets, etc.) do_open &&= FileTest.file?( filename ) end end if do_open # Is file readable? # Does the "file" utility exist? if( filename && @settings[ 'use_magic_file' ] && FileTest.exist?( "/usr/bin/file" ) && FileTest.exist?( filename ) && /\blisting\.txt\b/ !~ filename ) file_type = `/usr/bin/file -L #{filename}` if file_type !~ /text/ && file_type !~ /empty$/ choice = get_choice( "#{filename} does not appear to be readable. Try to open it anyway?", [ CHOICE_YES, CHOICE_NO ], CHOICE_NO ) case choice when CHOICE_NO do_open = false end end end if do_open buffer = Buffer.new( 'filepath' => filename, 'read_only' => read_only, 'display' => { 'top_line' => top_line, 'left_column' => left_column, }, 'cursor' => { 'row' => last_row, 'col' => last_col, } ) if existing_buffer @buffers[ @buffers.index( existing_buffer ) ] = buffer else if @settings['open_as_first_buffer'] @buffers.unshift buffer else @buffers << buffer end end run_hook_procs( :after_open, buffer ) save_session if switch_to( buffer ) if last_row buffer.cursor_to last_row, last_col || 0 else display_buffer buffer end end end elsif existing_buffer && last_row existing_buffer.cursor_to last_row, last_col || 0 end buffer || existing_buffer end alias_method :new_file, :open_file # Prompts the user for a file to open, then opens it with #open_file . # @see #open_file def open_file_ask prefill = '' if buffer_current if buffer_current.current_line =~ %r#(/\w+)+/\w+\.\w+# prefill = $& elsif buffer_current.name prefill = File.expand_path( File.dirname( buffer_current.name ) ) + "/" end end if @settings[ 'fuzzy_file_find' ] prefill = '' finder_block = lambda { |input| finder = FuzzyFileFinder.new( @session[ 'dir' ], @settings['fuzzy_file_find.max_dir_size'] || 8192, @fuzzy_ignores ) matches = finder.find( input ).sort_by { |m| [ -m[:score], m[:path] ] } with_list_file do |list| list.puts matches.map { |m| m[ :path ] } end open_list_buffer } end file = get_user_input( "Filename: ", history: @rlh_files, initial_text: prefill, &finder_block ) if file open_file file update_status_line update_context_line end end # Opens all files within a directory whose contents match a regular # expression. # @param regexp [String] # The regular expression used to match against. If nil, the user is # prompted for a value. # @param search_root [String] # The directory under which to recursively search for matches. If nil, # the user is prompted for a value. def open_matching_files( regexp = nil, search_root = nil ) regexp ||= get_user_input( "Regexp: ", history: @rlh_search ) return if regexp.nil? if buffer_current.current_line =~ %r{\w*/[/\w.]+} prefill = $& else prefill = File.expand_path( File.dirname( buffer_current.name ) ) + "/" end search_root ||= get_user_input( "Search within: ", history: @rlh_files, initial_text: prefill ) return if search_root.nil? files = `egrep -rl '#{regexp.gsub( /'/, "'\\\\''" )}' #{search_root}/*`.split( /\n/ ) if files.any? if files.size > 5 choice = get_choice( "Open #{files.size} files?", [ CHOICE_YES, CHOICE_NO ] ) return if choice == CHOICE_NO end files.each do |f| open_file f end find regexp, direction: :down, case_sensitive: true end end # Places a buffer at a new position in the array of Buffers # after shifting down (index+1) all existing Buffers from that position onwards. # @param to [Fixnum] The new 1-based position of the buffer to move # @param from [Fixnum] The original 1-based position of the buffer to move. Default: current buffer def renumber_buffer( to, from = nil ) if to < 1 raise "Invalid buffer index: #{to.inspect}" end if from && from < 1 raise "Invalid buffer index: #{from.inspect}" end from ||= buffer_to_number( buffer_current ) from_ = from - 1 to_ = to - 1 b = @buffers[from_] @buffers.delete_at from_ @buffers.insert( to_, b ) @buffers.compact! update_status_line end # If the prompt is non-nil, ask the user yes or no question first. def revert( prompt = nil ) do_revert = true if prompt show_buffer_file_diff do choice = get_choice( prompt, [ CHOICE_YES, CHOICE_NO ] ) case choice when CHOICE_NO do_revert = false end end end if do_revert open_file( buffer_current.name, 'read_only' => false, 'revert' => FORCE_REVERT, 'cursor' => { 'row' => buffer_current.last_row, 'col' => buffer_current.last_col } ) end end # Saves a buffer, then runs the :after_save hook on it. # @param [Buffer] buffer # The buffer to save. If nil, defaults to the current buffer. def save_file( buffer = buffer_current ) buffer.save run_hook_procs( :after_save, buffer ) end def save_file_as if buffer_current && buffer_current.name path = File.expand_path( File.dirname( buffer_current.name ) ) + "/" file = get_user_input( "Filename: ", history: @rlh_files, initial_text: path ) else file = get_user_input( "Filename: ", history: @rlh_files ) end if file old_name = buffer_current.name if buffer_current.save( file, PROMPT_OVERWRITE ) save_session end end end # Sets the type (language) of the current buffer. # @param [String] type_ # The type to set the current buffer to. # If nil, the user is prompted for a value. def set_buffer_type( type_ = nil ) type = type_ || get_user_input( "Content type: " ) if type if buffer_current.set_type( type ) update_status_line update_context_line end end end # If read_only is nil, the read_only state of the current buffer is toggled. # Otherwise, the read_only state of the current buffer is set to read_only. def set_read_only( read_only = nil ) if read_only buffer_current.read_only = read_only else buffer_current.read_only = ( ! buffer_current.read_only ) end update_status_line end def switch_to_buffer_number( buffer_number_ ) buffer_number = buffer_number_.to_i return if buffer_number < 1 if @buffer_number_last && buffer_number == buffer_to_number(buffer_current) buffer_number = @buffer_number_last end @buffer_number_last = buffer_to_number(buffer_current) switch_to @buffers[ buffer_number - 1 ] end def switch_to_next_buffer switch_to_buffer_number( buffer_to_number( buffer_current ) + 1 ) end def switch_to_previous_buffer switch_to_buffer_number( buffer_to_number( buffer_current ) - 1 ) end end end diakonos-0.9.0/lib/diakonos/functions/clipboard.rb000066400000000000000000000037531161735554400222230ustar00rootroot00000000000000module Diakonos module Functions # Copies the currently selected text to clipboard then unselects. def copy_selection @clipboard.add_clip buffer_current.copy_selection remove_selection end # Copies the currently selected text to clipboard, then deletes it. def cut_selection if @clipboard.add_clip( buffer_current.copy_selection ) delete end end # Deletes the current line, and adds it to the clipboard. # If the previous command was also delete_and_store_line, # append the line to the previous clip instead of making # a new clip. def delete_and_store_line removed_text = buffer_current.delete_line if removed_text clip = [ removed_text, "" ] if @functions_last[ -1 ] =~ /^delete_and_store_line/ @clipboard.append_to_clip clip else @clipboard.add_clip clip end end end # Deletes the text from the current cursor position to the end of the line, # then adds the deleted text to the clipboard. def delete_to_eol removed_text = buffer_current.delete_to_eol if removed_text @clipboard.add_clip removed_text end end # Pastes the current clipboard item at the current cursor position. def paste buffer_current.paste @clipboard.clip end # Opens a new buffer showing a list of all internal clipboard items. # Only for use when no external clipboard is used. def show_clips clip_filename = @diakonos_home + "/clips.txt" File.open( clip_filename, "w" ) do |f| case @settings[ 'clipboard.external' ] when 'klipper' f.puts 'Access Klipper directly (tray icon) to get at all clips.' when 'xclip' f.puts 'xclip does not keep a history of clips.' else @clipboard.each do |clip| f.puts clip f.puts "---------------------------" end end end open_file clip_filename end end end diakonos-0.9.0/lib/diakonos/functions/cursor.rb000066400000000000000000000172731161735554400216030ustar00rootroot00000000000000module Diakonos CLEAR_STACK_POINTER = true DONT_CLEAR_STACK_POINTER = false DIFFERENT_FILE = true NOT_DIFFERENT_FILE = false module Functions # @return [true,false] true iff the cursor changed positions def cursor_down buffer_current.cursor_to( buffer_current.last_row + 1, buffer_current.last_col, Buffer::DO_DISPLAY, Buffer::STOPPED_TYPING, DONT_ADJUST_ROW ) end # @return [true,false] true iff the cursor changed positions def cursor_left( stopped_typing = Buffer::STOPPED_TYPING ) buffer_current.cursor_to( buffer_current.last_row, buffer_current.last_col - 1, Buffer::DO_DISPLAY, stopped_typing ) end # Pops the cursor stack. # @param [Symbol] direction # Either :backward (default) or :forward. # @param [Boolean] different_file # Whether to pop just one frame (default), or many frames until a different file is reached. # @see Diakonos::DIFFERENT_FILE # @see Diakonos::NOT_DIFFERENT_FILE def cursor_return( direction = :backward, different_file = NOT_DIFFERENT_FILE ) delta = 0 if @cursor_stack_pointer.nil? push_cursor_state( buffer_current.top_line, buffer_current.last_row, buffer_current.last_col, DONT_CLEAR_STACK_POINTER ) delta = 1 end orig_ptr = @cursor_stack_pointer case direction when :backward @cursor_stack_pointer = ( @cursor_stack_pointer || @cursor_stack.length ) - 1 - delta while different_file && @cursor_stack[ @cursor_stack_pointer ] && @cursor_stack[ @cursor_stack_pointer ][ :buffer ] == buffer_current @cursor_stack_pointer -= 1 end when :forward @cursor_stack_pointer = ( @cursor_stack_pointer || 0 ) + 1 while different_file && @cursor_stack[ @cursor_stack_pointer ] && @cursor_stack[ @cursor_stack_pointer ][ :buffer ] == buffer_current @cursor_stack_pointer += 1 end end if @cursor_stack[ @cursor_stack_pointer ].nil? && orig_ptr @cursor_stack_pointer = orig_ptr end return_pointer = @cursor_stack_pointer if @cursor_stack_pointer < 0 return_pointer = @cursor_stack_pointer = 0 elsif @cursor_stack_pointer >= @cursor_stack.length return_pointer = @cursor_stack_pointer = @cursor_stack.length - 1 else cursor_state = @cursor_stack[ @cursor_stack_pointer ] if cursor_state buffer = cursor_state[ :buffer ] switch_to buffer buffer.pitch_view( cursor_state[ :top_line ] - buffer.top_line, Buffer::DONT_PITCH_CURSOR, Buffer::DO_DISPLAY ) buffer.cursor_to( cursor_state[ :row ], cursor_state[ :col ] ) update_status_line end end set_iline "Location: #{return_pointer+1}/#{@cursor_stack.size}" end # @return [true,false] true iff the cursor changed positions def cursor_right( stopped_typing = Buffer::STOPPED_TYPING, amount = 1 ) buffer_current.cursor_to( buffer_current.last_row, buffer_current.last_col + amount, Buffer::DO_DISPLAY, stopped_typing ) end # @return [true,false] true iff the cursor changed positions def cursor_up buffer_current.cursor_to( buffer_current.last_row - 1, buffer_current.last_col, Buffer::DO_DISPLAY, Buffer::STOPPED_TYPING, DONT_ADJUST_ROW ) end # Moves the cursor to the beginning of the current buffer. # @return [true,false] true iff the cursor changed positions def cursor_bof buffer_current.cursor_to( 0, 0, Buffer::DO_DISPLAY ) end # Moves the cursor to the beginning of the current line. def cursor_bol buffer_current.cursor_to_bol end # Moves the cursor to the end of the current line. def cursor_eol buffer_current.cursor_to_eol end # Moves the cursor to the end of the current buffer. def cursor_eof buffer_current.cursor_to_eof end # Moves the cursor to the top of the viewport of the current buffer. def cursor_tov buffer_current.cursor_to_tov end # Moves the cursor to the bottom of the viewport of the current buffer. def cursor_bov buffer_current.cursor_to_bov end # Moves the cursor to the beginning of the parent code block. def go_block_outer buffer_current.go_block_outer end # Moves the cursor to the beginning of the first child code block. def go_block_inner buffer_current.go_block_inner end # Moves the cursor to the beginning of the next code block at the same # indentation level as the current one. def go_block_next buffer_current.go_block_next end # Moves the cursor to the beginning of the previous code block at the same # indentation level as the current one. def go_block_previous buffer_current.go_block_previous end # Moves the cursor to the next occurrence of the given character. # @param [String] char The character to go to def go_to_char( after = nil, char = nil ) char ||= get_char( "Type character to go to..." ) if char moved = buffer_current.go_to_char( char, after == :after ? AFTER_CHAR : ON_CHAR ) if ! moved set_iline "'#{char}' not found." end end end # Moves the cursor to the closest previous occurrence of the given character. # @param [String] char The character to go to def go_to_char_previous( after = nil, char = nil ) char ||= get_char( "Type character to go to..." ) if char moved = buffer_current.go_to_char_previous( char, after == :after ? AFTER_CHAR : ON_CHAR ) if ! moved set_iline "'#{char}' not found." end end end # Prompts the user for a line number or line delta, with optional column # number. Moves the cursor there. def go_to_line_ask input = get_user_input( "Go to [line number|+lines][,column number]: " ) if input row = nil col = 0 if input =~ /([+-]\d+)/ row = buffer_current.last_row + $1.to_i col = buffer_current.last_col else input = input.split( /\D+/ ).collect { |n| n.to_i } if input.size > 0 if input[ 0 ] == 0 row = nil else row = input[ 0 ] - 1 end if input[ 1 ] col = input[ 1 ] - 1 end end end if row buffer_current.go_to_line( row, col ) end end end # Pitches the current buffer's view one screenful down. def page_down if buffer_current.pitch_view( main_window_height, Buffer::DO_PITCH_CURSOR ) == 0 buffer_current.cursor_to_eof end update_status_line update_context_line end # Pitches the current buffer's view one screenful up. def page_up if buffer_current.pitch_view( -main_window_height, Buffer::DO_PITCH_CURSOR ) == 0 cursor_bof end update_status_line update_context_line end # Scrolls the current buffer's view down, as determined by the # view.scroll_amount setting. def scroll_down buffer_current.pitch_view( @settings[ "view.scroll_amount" ] || 1 ) update_status_line update_context_line end # Scrolls the current buffer's view up, as determined by the # view.scroll_amount setting. def scroll_up if @settings[ "view.scroll_amount" ] buffer_current.pitch_view( -@settings[ "view.scroll_amount" ] ) else buffer_current.pitch_view( -1 ) end update_status_line update_context_line end end end diakonos-0.9.0/lib/diakonos/functions/grepping.rb000066400000000000000000000042431161735554400220720ustar00rootroot00000000000000module Diakonos module Functions def grep( regexp_source = nil ) grep_( regexp_source, buffer_current ) end def grep_buffers( regexp_source = nil ) grep_( regexp_source, *@buffers ) end def grep_session_dir( regexp_source = nil ) grep_dir regexp_source, @session[ 'dir' ] end def grep_dir( regexp_source = nil, dir = nil ) if dir.nil? dir = get_user_input( "Grep directory: ", history: @rlh_files, initial_text: @session[ 'dir' ], do_complete: DONT_COMPLETE, on_dirs: :accept_dirs ) return if dir.nil? end dir = File.expand_path( dir ) original_buffer = buffer_current if buffer_current.changing_selection selected_text = buffer_current.copy_selection[ 0 ] end starting_row, starting_col = buffer_current.last_row, buffer_current.last_col selected = get_user_input( "Grep regexp: ", history: @rlh_search, initial_text: regexp_source || selected_text || "" ) { |input| next if input.length < 2 escaped_input = input.gsub( /'/ ) { "\\047" } matching_files = `egrep '#{escaped_input}' -rniIl #{dir}`.split( /\n/ ) grep_results = matching_files.map { |f| ::Diakonos.grep_array( Regexp.new( input ), File.read( f ).split( /\n/ ), settings[ 'grep.context' ], "#{File.basename( f )}:", f ) }.flatten if settings[ 'grep.context' ] == 0 join_str = "\n" else join_str = "\n---\n" end with_list_file do |list| list.puts grep_results.join( join_str ) end list_buffer = open_list_buffer regexp = nil begin list_buffer.highlight_matches Regexp.new( input ) rescue RegexpError => e # ignore end display_buffer list_buffer } if selected spl = selected.split( "| " ) if spl.size > 1 open_file spl[ -1 ] end else original_buffer.cursor_to starting_row, starting_col end end end enddiakonos-0.9.0/lib/diakonos/functions/indentation.rb000066400000000000000000000033761161735554400226010ustar00rootroot00000000000000module Diakonos module Functions def indent if ! buffer_current.changing_selection buffer_current.indent else @do_display = false mark = buffer_current.selection_mark if mark.end_col > 0 end_row = mark.end_row else end_row = mark.end_row - 1 end (mark.start_row..end_row).each do |row| buffer_current.indent row, Buffer::DONT_DISPLAY end @do_display = true display_buffer buffer_current end end def insert_spaces( num_spaces ) if num_spaces > 0 buffer_current.delete_selection buffer_current.insert_string( " " * num_spaces ) cursor_right( Buffer::STILL_TYPING, num_spaces ) end end def insert_tab type_character TAB end def parsed_indent if( buffer_current.changing_selection ) @do_display = false mark = buffer_current.selection_mark (mark.start_row..mark.end_row).each do |row| buffer_current.parsed_indent row, Buffer::DONT_DISPLAY end @do_display = true display_buffer buffer_current else buffer_current.parsed_indent end update_status_line update_context_line end def unindent if( buffer_current.changing_selection ) @do_display = false mark = buffer_current.selection_mark if mark.end_col > 0 end_row = mark.end_row else end_row = mark.end_row - 1 end (mark.start_row..end_row).each do |row| buffer_current.unindent row, Buffer::DONT_DISPLAY end @do_display = true display_buffer buffer_current else buffer_current.unindent end end end enddiakonos-0.9.0/lib/diakonos/functions/readline.rb000066400000000000000000000032071161735554400220410ustar00rootroot00000000000000module Diakonos module Functions def readline_abort @readline.abort end def readline_accept @readline.accept current_list_item end def readline_backspace @readline.backspace end def readline_complete_input @readline.complete_input end def readline_cursor_left @readline.cursor_left end def readline_cursor_right @readline.cursor_right end def readline_cursor_bol @readline.cursor_bol end def readline_cursor_eol @readline.cursor_eol end def readline_cursor_up if showing_list? if list_item_selected? previous_list_item end @readline.set_input select_list_item else @readline.history_up end @readline.cursor_write_input end def readline_cursor_down if showing_list? if list_item_selected? next_list_item end @readline.set_input select_list_item else @readline.history_down end @readline.cursor_write_input end def readline_delete @readline.delete end def readline_delete_line @readline.delete_line end def readline_delete_word @readline.delete_word end def readline_grep_context_decrease decrease_grep_context @readline.call_block end def readline_grep_context_increase increase_grep_context @readline.call_block end def readline_page_down page_down @readline.list_sync select_list_item end def readline_page_up page_up @readline.list_sync select_list_item end end enddiakonos-0.9.0/lib/diakonos/functions/search.rb000066400000000000000000000141741161735554400215300ustar00rootroot00000000000000module Diakonos module Functions # Searches for matches of a regular expression in the current buffer. # @param [String] regexp_source_ # The regular expression to search for. # @param [Hash] options # Options that alter how the search is performed # @option options [Symbol] :direction (:down) # The direction to search; :down or :up. # @option options [Boolean] :case_sensitive (false) # Whether or not the search should be case_sensitive. # @option options [String] replacement # If provided, do a find and replace, and replace matches with replacement. # @option options [Boolean] :word_only (false) # Whether or not to search with word boundaries # @see #find_exact # @see #find_again # @see #find_clip def find( regexp_source_ = nil, options = {} ) direction = options[:direction] || :down case_sensitive = options[:case_sensitive] replacement = options[:replacement] word_only = options[:word_only] if regexp_source_ regexp_source = regexp_source_ else buffer_current.search_area = nil m = buffer_current.selection_mark if m if m.start_row != m.end_row buffer_current.search_area = buffer_current.selection_mark buffer_current.remove_selection else selected_text = buffer_current.copy_selection[ 0 ] end end starting_row, starting_col = buffer_current.last_row, buffer_current.last_col regexp_source = get_user_input( "Search regexp: ", history: @rlh_search, initial_text: selected_text || "" ) { |input| if input.length > 1 regexp_source = word_only ? "\\b#{input}\\b" : input find_( direction: direction, case_sensitive: case_sensitive, regexp_source: regexp_source, starting_row: starting_row, starting_col: starting_col, quiet: true ) else buffer_current.remove_selection Buffer::DONT_DISPLAY buffer_current.clear_matches Buffer::DO_DISPLAY end } end if regexp_source if word_only regexp_source = "\\b#{regexp_source}\\b" end num_replacements = find_( direction: direction, case_sensitive: case_sensitive, regexp_source: regexp_source, replacement: replacement, starting_row: starting_row, starting_col: starting_col, quiet: false ) show_number_of_matches_found( replacement ? num_replacements : nil ) elsif starting_row && starting_col buffer_current.clear_matches if @settings[ 'find.return_on_abort' ] buffer_current.cursor_to starting_row, starting_col, Buffer::DO_DISPLAY end end end # Searches for matches of the latest clipboard item in the current buffer. # Note that the clipboard item is interpreted as a regular expression. # Only the last line of multi-line clipboard items is used. # @param [String] direction # The direction to search. :down (default) or :up. # @param [Boolean] case_sensitive # Whether or not the search should be case_sensitive. Default is insensitive. # @see #find def find_clip( direction = :down, case_sensitive = CASE_INSENSITIVE ) find @clipboard.clip[-1], direction: direction, case_sensitive: case_sensitive end # Search again for the most recently sought search term. # @param [String] direction # The direction to search; :down or :up. # @see #find # @see #find_exact def find_again( direction = :down ) if direction buffer_current.find_again( @last_search_regexps, direction ) else buffer_current.find_again( @last_search_regexps ) end show_number_of_matches_found end # Search for an exact string (not a regular expression). # @param [Symbol] direction # The direction to search; :down (default) or :up. # @param [String] search_term_ # The thing to search for. # @see #find # @see #find_again def find_exact( direction = :down, search_term_ = nil ) buffer_current.search_area = nil if search_term_.nil? if buffer_current.changing_selection selected_text = buffer_current.copy_selection[ 0 ] end search_term = get_user_input( "Search for: ", history: @rlh_search, initial_text: selected_text || "" ) else search_term = search_term_ end if search_term regexp = [ Regexp.new( Regexp.escape( search_term ) ) ] buffer_current.find( regexp, :direction => direction ) @last_search_regexps = regexp end end # Moves the cursor to the pair match of the current character, if any. def go_to_pair_match buffer_current.go_to_pair_match end # Wrapper method for calling #find for search and replace. # @see #find def search_and_replace( case_sensitive = CASE_INSENSITIVE ) find nil, case_sensitive: case_sensitive, replacement: ASK_REPLACEMENT end alias_method :find_and_replace, :search_and_replace # Immediately moves the cursor to the next match of a regular expression. # The user is not prompted for any value. # @param [String] regexp_source # The regular expression to search for. # @param [Symbol] direction # The direction to search; :down (default) or :up. def seek( regexp_source, direction = :down ) if regexp_source regexp = Regexp.new( regexp_source ) buffer_current.seek( regexp, direction ) end end def show_number_of_matches_found( num_replacements = nil ) return if buffer_current.num_matches_found.nil? num_found = buffer_current.num_matches_found if num_found != 1 plural = 'es' end if num_replacements set_iline_if_empty "#{num_replacements} out of #{num_found} match#{plural} replaced" else set_iline_if_empty "#{num_found} match#{plural} found" end end end end diakonos-0.9.0/lib/diakonos/functions/selection.rb000066400000000000000000000045731161735554400222520ustar00rootroot00000000000000module Diakonos module Functions # Begins selecting text by anchoring (marking) the start of a selection. def anchor_selection buffer_current.anchor_selection update_status_line end # Removes the highlighting from any text that matches the most recent # search. def clear_matches buffer_current.clear_matches Buffer::DO_DISPLAY end # Unselects any current selection (stops selecting). def remove_selection buffer_current.remove_selection update_status_line end # Selects the entire buffer contents. def select_all buffer_current.select_all end # Selects text between two regexps. def select_block( beginning = nil, ending = nil, including_ending = true ) if beginning.nil? input = get_user_input( "Start at regexp: " ) if input beginning = Regexp.new input end end if beginning and ending.nil? input = get_user_input( "End before regexp: " ) if input ending = Regexp.new input end end if beginning and ending buffer_current.select( beginning, ending, including_ending ) end end # Changes selection mode to block mode (rectangular selection). def selection_mode_block buffer_current.selection_mode_block update_status_line end # Changes selection mode to normal mode (flow selection). def selection_mode_normal buffer_current.selection_mode_normal update_status_line end # If currently selecting, stops selecting. # If not currently selecting, begins selecting. def toggle_selection buffer_current.toggle_selection update_status_line end # Selects the current line. def select_line buffer_current.select_current_line update_status_line end # Selects the code block which wraps the current cursor position. # Execute multiple times in succession to select increasingly outer code blocks. def select_wrapping_block buffer_current.select_wrapping_block update_status_line end # Selects the word at the current cursor position. # If the cursor is not on a word character, the first word following the cursor is selected. def select_word buffer_current.select_word end def select_word_another buffer_current.select_word_another end end end diakonos-0.9.0/lib/diakonos/functions/sessions.rb000066400000000000000000000054631161735554400221320ustar00rootroot00000000000000module Diakonos module Functions def merge_session_settings @settings.merge! @session[ 'settings' ] end def change_session_setting( key_ = nil, value = nil, do_redraw = DONT_REDRAW ) if key_.nil? key = get_user_input( "Setting: " ) else key = key_ end if key if value.nil? value = get_user_input( "Value: " ) end case @settings[ key ] when String value = value.to_s when Fixnum value = value.to_i when TrueClass, FalseClass value = value.to_b end @session[ 'settings' ][ key ] = value merge_session_settings redraw if do_redraw set_iline "#{key} = #{value}" end end def load_session( session_id = nil ) if session_id.nil? session_id = get_user_input( "Session: ", history: @rlh_sessions, initial_text: @session_dir, do_complete: DO_COMPLETE ) end return if session_id.nil? or session_id.empty? path = session_filepath_for( session_id ) if not File.exist?( path ) set_iline "No such session: #{session_id}" else if pid_session?( @session[ 'filename' ] ) File.delete @session[ 'filename' ] end @session = nil @buffers.each do |buffer| close_buffer buffer end new_session( path ) @session[ 'files' ].each do |file| open_file file end end end def name_session name = get_user_input( 'Session name: ' ) if name new_session "#{@session_dir}/#{name}" save_session end end def set_session_dir path = get_user_input( "Session directory: ", history: @rlh_files, initial_text: @session[ 'dir' ], do_complete: DONT_COMPLETE, on_dirs: :accept_dirs ) if path @session[ 'dir' ] = File.expand_path( path ) save_session set_iline "Session dir changed to: #{@session['dir']}" else set_iline "(Session dir is: #{@session['dir']})" end end def toggle_session_setting( key_ = nil, do_redraw = DONT_REDRAW ) key = key_ || get_user_input( "Setting: " ) return if key.nil? value = nil if @session[ 'settings' ][ key ].class == TrueClass or @session[ 'settings' ][ key ].class == FalseClass value = ! @session[ 'settings' ][ key ] elsif @settings[ key ].class == TrueClass or @settings[ key ].class == FalseClass value = ! @settings[ key ] end if value != nil # explicitly true or false @session[ 'settings' ][ key ] = value merge_session_settings redraw if do_redraw set_iline "#{key} = #{value}" end end end enddiakonos-0.9.0/lib/diakonos/functions/shell.rb000066400000000000000000000166021161735554400213700ustar00rootroot00000000000000module Diakonos module Functions # Change the current working directory (CWD) of the Diakonos process. # @param [String] dir The directory to change to def chdir( dir = nil ) dir ||= get_user_input( "Change to directory: ", initial_text: Dir.pwd ) if dir Dir.chdir dir end end # Substitutes Diakonos shell variables in a String. # - $f: The current buffer's filename # - $d: The current buffer's directory # - $F: A space-separated list of all buffer filenames # - $i: A string acquired from the user with a prompt # - $c: The current clipboard text # - $s: The currently selected text # @param [String] string # The string containing variables to substitute # @return [String] # A new String with values substituted for all variables def sub_shell_variables( string ) return if string.nil? retval = string.dup # Current buffer filename retval.gsub!( /\$f/, ( $1 or "" ) + File.expand_path( buffer_current.name || "" ) ) # Current buffer dir retval.gsub!( /\$d/, ( $1 or "" ) + File.dirname( File.expand_path( buffer_current.name || '' ) ) ) # space-separated list of all buffer filenames name_array = Array.new @buffers.each do |b| name_array.push b.name end retval.gsub!( /\$F/, ( $1 or "" ) + ( name_array.join(' ') or "" ) ) # Get user input, sub it in if retval =~ /\$i/ user_input = get_user_input( "Argument: ", history: @rlh_shell, initial_text: buffer_current.selected_string ) retval.gsub!( /\$i/, user_input ) end # Current clipboard text if retval =~ /\$[ck]/ clip_filename = @diakonos_home + "/clip.txt" File.open( clip_filename, "w" ) do |clipfile| if @clipboard.clip clipfile.puts( @clipboard.clip.join( "\n" ) ) end end retval.gsub!( /\$[ck]/, clip_filename ) end # Currently selected text if retval =~ /\$s/ text_filename = @diakonos_home + "/selected.txt" File.open( text_filename, "w" ) do |textfile| selected_text = buffer_current.selected_text if selected_text textfile.puts( selected_text.join( "\n" ) ) end end retval.gsub!( /\$s/, text_filename ) end retval end # Executes a command in a shell, captures the results, and displays them # (if any) in a new buffer. Substitutes Diakonos shell variables. # Interaction with Diakonos is not possible while the shell is running. # For asynchronous shelling, use #spawn. The shell function does not # allow interaction with applications run in the shell. Use #execute # for interactivity. # # @param [String] command_ # The shell command to execute # @param [String] result_filename # The name of the temporary file to write the shell results to # @see #sub_shell_variables # @see #execute # @see #spawn # @see #paste_shell_result def shell( command_ = nil, result_filename = 'shell-result.txt' ) command = command_ || get_user_input( "Command: ", history: @rlh_shell ) return if command.nil? command = sub_shell_variables( command ) completed = false result_file = "#{@diakonos_home}/#{result_filename}" File.open( result_file , "w" ) do |f| Curses::close_screen stdin, stdout, stderr = Open3.popen3( command ) t1 = Thread.new do stdout.each_line do |line| f.puts line end end t2 = Thread.new do stderr.each_line do |line| f.puts line end end catch :stop do loop do begin Timeout::timeout( 5 ) do t1.join t2.join Curses::init_screen refresh_all completed = true throw :stop end rescue Timeout::Error => e choice = get_choice( "Keep waiting for shell results?", [ CHOICE_YES, CHOICE_NO ], CHOICE_YES ) if choice != CHOICE_YES t1.terminate t2.terminate throw :stop end end end end end if File.size?( result_file ) open_file result_file set_iline "#{completed ? '' : '(interrupted) '}Results for: #{command}" else set_iline "Empty result for: #{command}" end end # Executes a command in a shell, and displays the exit code. # Results of the shell command are discarded. # Substitutes Diakonos shell variables. # Interaction with Diakonos is not possible while the shell is running. # For asynchronous shelling, use #spawn. The #execute function allows # interaction with shell programs that accept keyboard interaction. # # @param [String] command_ # The shell command to execute # @see #sub_shell_variables # @see #shell # @see #spawn # @see #paste_shell_result def execute( command_ = nil ) command = command_ || get_user_input( "Command: ", history: @rlh_shell ) return if command.nil? command = sub_shell_variables( command ) Curses::close_screen success = system( command ) if ! success result = "Could not execute: #{command}" else result = "Exit code: #{$?}" end Curses::init_screen refresh_all set_iline result end # Executes a command in a shell, captures the results, and pastes them # in the current buffer at the current cursor location. # Substitutes Diakonos shell variables. # Interaction with Diakonos is not possible while the shell is running. # For asynchronous shelling, use #spawn. # # @param [String] command_ # The shell command to execute # @see #sub_shell_variables # @see #execute # @see #shell # @see #spawn def paste_shell_result( command_ = nil ) command = command_ || get_user_input( "Command: ", history: @rlh_shell ) return if command.nil? command = sub_shell_variables( command ) Curses::close_screen begin buffer_current.paste( `#{command} 2<&1`.split( /\n/, -1 ) ) rescue Exception => e debug_log e.message debug_log e.backtrace.join( "\n\t" ) show_exception e end Curses::init_screen refresh_all end # Executes a command in a shell, captures the results, and pastes them # in the current buffer at the current cursor location. # Substitutes Diakonos shell variables. # The shell is executed in a separate thread, so interaction with Diakonos # is possible during execution. # # @param [String] command_ # The shell command to execute # @see #sub_shell_variables # @see #execute # @see #shell # @see #paste_shell_result def spawn( command_ = nil ) command = command_ || get_user_input( "Command: ", history: @rlh_shell ) return if command.nil? command = sub_shell_variables( command ) Thread.new do if system( command ) set_iline "Return code #{$?} from '#{command}'" else set_iline "Error code #{$?} executing '#{command}'" end end end end enddiakonos-0.9.0/lib/diakonos/functions/tags.rb000066400000000000000000000032521161735554400212140ustar00rootroot00000000000000module Diakonos module Functions def go_to_tag( tag_ = nil ) load_tags # If necessary, prompt for tag name. if tag_.nil? if buffer_current.changing_selection selected_text = buffer_current.copy_selection[ 0 ] end tag_name = get_user_input( "Tag name: ", history: @rlh_general, initial_text: selected_text || "", completion_array: @tags.keys ) else tag_name = tag_ end tag_array = @tags[ tag_name ] if tag_array and tag_array.length > 0 if i = tag_array.index( @last_tag ) tag = ( tag_array[ i + 1 ] or tag_array[ 0 ] ) else tag = tag_array[ 0 ] end @last_tag = tag @tag_stack.push [ buffer_current.name, buffer_current.last_row, buffer_current.last_col ] if switch_to( @buffers.find { |b| b.name == tag.file } ) #buffer_current.go_to_line( 0 ) else open_file tag.file end line_number = tag.command.to_i if line_number > 0 buffer_current.go_to_line( line_number - 1 ) else find tag.command case_sensitive: true end elsif tag_name set_iline "No such tag: '#{tag_name}'" end end def go_to_tag_under_cursor go_to_tag buffer_current.word_under_cursor end def pop_tag tag = @tag_stack.pop if tag if not switch_to( @buffers.find { |b| b.name == tag[ 0 ] } ) open_file tag[ 0 ] end buffer_current.cursor_to( tag[ 1 ], tag[ 2 ], Buffer::DO_DISPLAY ) else set_iline "Tag stack empty." end end end end diakonos-0.9.0/lib/diakonos/functions/text-manipulation.rb000066400000000000000000000121211161735554400237330ustar00rootroot00000000000000module Diakonos module Functions def close_code buffer_current.close_code end def collapse_whitespace buffer_current.collapse_whitespace end def columnize( delimiter = nil, num_spaces_padding = 0 ) delimiter ||= get_user_input( "Column delimiter (regexp): ", history: @rlh_general, initial_text: @settings[ "lang.#{buffer_current.original_language}.column_delimiters" ] || '' ) if delimiter && num_spaces_padding buffer_current.columnize Regexp.new( delimiter ), num_spaces_padding end end def comment_out buffer_current.comment_out end def complete_word( direction = :down ) b = buffer_current if b.selecting? old_word = b.word_before_cursor b.delete_selection end partial = b.word_before_cursor return if partial.nil? all_words = @buffers.find_all { |b_| b_.original_language == b.original_language }.collect { |b_| b_.words( /^#{Regexp.escape(partial)}./ ) }.flatten if all_words.any? words = all_words.uniq.sort if old_word i = ( ( direction == :up ? words.size - 1 : 1 ) + words.find_index { |w| w == old_word } ) % words.size else freq_word = words.sort_by { |word| all_words.find_all { |w| w == word }.size }[ -1 ] i = words.find_index { |w| w == freq_word } end word = words[ i ] b.insert_string word[ partial.length..-1 ] r, c = b.last_row, b.last_col b.cursor_to( b.last_row, b.last_col + word.length - partial.length ) b.set_selection( r, c, r, c + word.length - partial.length ) n = words.size middle_word = words[ i ].center( Curses::cols / 4, ' ' ) shown_words = [ words[ ( n+i-2 ) % n ], words[ ( n+i-1 ) % n ], middle_word, words[ ( n+i+1 ) % n ], words[ ( n+i+2 ) % n ], ].compact.uniq.reject { |w| w == middle_word.strip }.join( ' ' ) mi = shown_words.index( middle_word ) padding = " " * ( Curses::cols / 2 - mi - ( middle_word.length / 2 ) ) set_iline padding + shown_words end end def join_lines_upward buffer_current.join_lines_upward( buffer_current.current_row, Buffer::STRIP_LINE ) end def join_lines buffer_current.join_lines( buffer_current.current_row, Buffer::STRIP_LINE ) end def operate_on_string( ruby_code = get_user_input( 'Ruby code: ', history: @rlh_general, initial_text: 'str.' ) ) if ruby_code str = buffer_current.selected_string if str and not str.empty? buffer_current.paste eval( ruby_code ) end end end def operate_on_lines( ruby_code = get_user_input( 'Ruby code: ', history: @rlh_general, initial_text: 'lines.collect { |l| l }' ) ) if ruby_code lines = buffer_current.selected_text if lines and not lines.empty? if lines[ -1 ].empty? lines.pop popped = true end new_lines = eval( ruby_code ) if popped new_lines << '' end buffer_current.paste new_lines end end end def operate_on_each_line( ruby_code = get_user_input( 'Ruby code: ', history: @rlh_general, initial_text: 'line.' ) ) if ruby_code lines = buffer_current.selected_text if lines and not lines.empty? if lines[ -1 ].empty? lines.pop popped = true end new_lines = eval( "lines.collect { |line| #{ruby_code} }" ) if popped new_lines << '' end buffer_current.paste new_lines end end end def surround_line( envelope = nil ) buffer_current.set_selection_current_line surround_selection envelope end def surround_paragraph( envelope = nil ) ( first, _ ), ( last, length ) = buffer_current.paragraph_under_cursor_pos buffer_current.set_selection( first, 0, last, length+1 ) surround_selection envelope end def surround_selection( parenthesis = nil ) if ! buffer_current.selecting? set_iline "Nothing selected." return end parenthesis ||= get_user_input( "Surround with: " ) if parenthesis text = buffer_current.surround( buffer_current.selected_text, parenthesis ) if text buffer_current.paste text end end end def surround_word( envelope = nil ) ( start_row, start_col ), ( end_row, end_col ) = buffer_current.word_under_cursor_pos if start_row && start_col && end_row && end_col buffer_current.set_selection( start_row, start_col, end_row, end_col ) surround_selection envelope end end def uncomment buffer_current.uncomment end def wrap_paragraph buffer_current.wrap_paragraph end end end diakonos-0.9.0/lib/diakonos/grep.rb000066400000000000000000000050541161735554400172050ustar00rootroot00000000000000module Diakonos def self.grep_array( regexp, array, lines_of_context, prefix, filepath ) num_lines = array.size line_numbers = [] array.each_with_index do |line,index| next if line !~ regexp start_index = [ 0, index - lines_of_context ].max end_index = [ index + lines_of_context, num_lines-1 ].min (start_index..end_index).each do |i| line_numbers << i end end line_numbers.uniq! results = [] last_i = line_numbers[ 0 ] one_result = [] line_numbers.each do |i| if i - last_i > 1 results << one_result.join( "\n" ) one_result = [] end one_result << ( "#{prefix}#{i+1}: " << ( "%-300s | #{filepath}:#{i+1}" % array[ i ] ) ) last_i = i end if not one_result.empty? results << one_result.join( "\n" ) end results end class Diakonos def actually_grep( regexp_source, *buffers ) begin regexp = Regexp.new( regexp_source, Regexp::IGNORECASE ) grep_results = buffers.map { |buffer| buffer.grep( regexp ) }.flatten if settings[ 'grep.context' ] == 0 join_str = "\n" else join_str = "\n---\n" end with_list_file do |list| list.puts grep_results.join( join_str ) end list_buffer = open_list_buffer list_buffer.highlight_matches regexp display_buffer list_buffer rescue RegexpError # Do nothing end end def grep_( regexp_source, *buffers ) original_buffer = buffer_current if buffer_current.changing_selection selected_text = buffer_current.copy_selection[ 0 ] end starting_row, starting_col = buffer_current.last_row, buffer_current.last_col selected = get_user_input( "Grep regexp: ", history: @rlh_search, initial_text: regexp_source || selected_text || "" ) { |input| next if input.length < 2 actually_grep input, *buffers } if selected spl = selected.split( "| " ) if spl.size > 1 open_file spl[ -1 ] end else original_buffer.cursor_to starting_row, starting_col end end def increase_grep_context current = settings[ 'grep.context' ] @session[ 'settings' ][ 'grep.context' ] = current + 1 merge_session_settings end def decrease_grep_context current = settings[ 'grep.context' ] if current > 0 @session[ 'settings' ][ 'grep.context' ] = current - 1 merge_session_settings end end end enddiakonos-0.9.0/lib/diakonos/help.rb000066400000000000000000000023251161735554400171760ustar00rootroot00000000000000module Diakonos class Diakonos def init_help @help_dir = INSTALL_SETTINGS[ :help_dir ] @help_tags = `grep -h Tags #{@help_dir}/* | cut -d ' ' -f 2-`.split.uniq end def open_help_buffer @help_buffer = open_file( @help_filename ) end def close_help_buffer close_buffer @help_buffer @help_buffer = nil end def matching_help_documents( str ) docs = [] if str =~ %r{^/(.+)$} regexp = $1 files = Dir[ "#{@help_dir}/*" ].select{ |f| File.open( f ) { |io| io.grep( /#{regexp}/i ) }.any? } else terms = str.gsub( /[^a-zA-Z0-9-]/, ' ' ).split.join( '|' ) file_grep = `egrep -i -l '^Tags.*\\b(#{terms})\\b' #{@help_dir}/*` files = file_grep.split( /\s+/ ) end files.each do |file| File.open( file ) do |f| docs << ( "%-300s | %s" % [ f.gets.strip, file ] ) end end docs.sort { |a,b| a.gsub( /^# (?:an?|the) */i, '# ' ) <=> b.gsub( /^# (?:an?|the) */i, '# ' ) } end def open_help_document( selected_string ) help_file = selected_string.split( "| " )[ -1 ] if File.exist? help_file open_file help_file end end end enddiakonos-0.9.0/lib/diakonos/hooks.rb000066400000000000000000000005101161735554400173630ustar00rootroot00000000000000module Diakonos class Diakonos def register_proc( the_proc, hook_name, priority = 0 ) @hooks[ hook_name ] << { :proc => the_proc, :priority => priority } end def run_hook_procs( hook_id, *args ) @hooks[ hook_id ].each do |hook_proc| hook_proc[ :proc ].call( *args ) end end end enddiakonos-0.9.0/lib/diakonos/installation.rb000066400000000000000000000005701161735554400207470ustar00rootroot00000000000000# This file is completely overwritten by install.rb upon installation. # This copy is here to permit the tests to execute. module Diakonos INSTALL_SETTINGS = { :prefix => '.', :bin_dir => 'bin', :doc_dir => '.', :help_dir => 'help', :conf_dir => '.', :lib_dir => 'lib', :installed => { :files => [], :dirs => [], }, } end diakonos-0.9.0/lib/diakonos/interaction.rb000066400000000000000000000077441161735554400205770ustar00rootroot00000000000000module Diakonos TAB = 9 ENTER = 13 ESCAPE = 27 BACKSPACE = 127 CTRL_C = 3 CTRL_D = 4 CTRL_K = 11 CTRL_Q = 17 CTRL_H = 263 CTRL_W = 23 RESIZE2 = 4294967295 DO_COMPLETE = true DONT_COMPLETE = false CHOICE_NO = 0 CHOICE_YES = 1 CHOICE_ALL = 2 CHOICE_CANCEL = 3 CHOICE_YES_TO_ALL = 4 CHOICE_NO_TO_ALL = 5 CHOICE_YES_AND_STOP = 6 CHOICE_DELETE = 7 CHOICE_KEYS = [ [ "n".ord, "N".ord ], [ "y".ord, "Y".ord ], [ "a".ord, "A".ord ], [ "c".ord, "C".ord, ESCAPE, CTRL_C, CTRL_D, CTRL_Q ], [ "e".ord ], [ "o".ord ], [ "s".ord ], [ "d".ord ], ] CHOICE_STRINGS = [ '(n)o', '(y)es', '(a)ll', '(c)ancel', 'y(e)s to all', 'n(o) to all', 'yes and (s)top', '(d)elete' ] class Diakonos attr_reader :readline # completion_array is the array of strings that tab completion can use # @param options :initial_text, :completion_array, :history, :do_complete, :on_dirs def get_user_input( prompt, options = {}, &block ) options[ :history ] ||= @rlh_general options[ :initial_text ] ||= "" options[ :do_complete ] ||= DONT_COMPLETE options[ :on_dirs ] ||= :go_into_dirs if @playing_macro retval = @macro_input_history.shift else cursor_pos = set_iline( prompt ) @readline = Readline.new( self, @win_interaction, cursor_pos, options, &block ) while ! @readline.done? process_keystroke Array.new, 'input' end close_list_buffer retval = @readline.input options[ :history ][ -1 ] = @readline.input @readline = nil if @macro_history @macro_input_history.push retval end set_iline end retval end def interaction_blink( message = nil ) terminate_message set_iline @settings[ 'interaction.blink_string' ] sleep @settings[ 'interaction.blink_duration' ] set_iline message if message end # choices should be an array of CHOICE_* constants. # default is what is returned when Enter is pressed. def get_choice( prompt, choices, default = nil ) retval = @iterated_choice if retval @choice_iterations -= 1 if @choice_iterations < 1 @iterated_choice = nil @do_display = true end return retval end @saved_main_x = @win_main.curx @saved_main_y = @win_main.cury msg = prompt + " " choice_strings = choices.collect do |choice| CHOICE_STRINGS[ choice ] end msg << choice_strings.join( ", " ) if default set_iline msg else show_message msg end c = nil while retval.nil? c = @win_interaction.getch.ord case c when Curses::KEY_NPAGE page_down when Curses::KEY_PPAGE page_up else if @message_expiry and Time.now < @message_expiry interaction_blink show_message msg else case c when ENTER retval = default when '0'.ord..'9'.ord if @choice_iterations < 1 @choice_iterations = ( c - '0'.ord ) else @choice_iterations = @choice_iterations * 10 + ( c - '0'.ord ) end else choices.each do |choice| if CHOICE_KEYS[ choice ].include? c retval = choice break end end end if retval.nil? interaction_blink( msg ) end end end end terminate_message set_iline if @choice_iterations > 0 @choice_iterations -= 1 @iterated_choice = retval @do_display = false end retval end def get_char( prompt ) set_iline prompt char = @win_main.getch set_iline char end end enddiakonos-0.9.0/lib/diakonos/key-map.rb000066400000000000000000000026111161735554400176070ustar00rootroot00000000000000module Diakonos module KeyMap # path is an array of hash keys # This method deletes a path of hash keys, with each step in the path # being a recursively deeper key in a hash tree. # Returns the possibly modified hash. def delete_key_path( path ) if path.length > 1 subtree = self[ path[ 0 ] ] if subtree.respond_to?( :delete_key_path ) subtree.delete_key_path( path[ 1..-1 ] ) if subtree.empty? delete( path[ 0 ] ) end end elsif path.length == 1 delete( path[ 0 ] ) end self end def set_key_path( path, leaf ) if path.length > 1 node = self[ path[ 0 ] ] if ! node.respond_to?( :set_key_path ) node = self[ path[ 0 ] ] = {}.extend( KeyMap ) end node.set_key_path( path[ 1..-1 ], leaf ) elsif path.length == 1 self[ path[ 0 ] ] = leaf end self end def get_node( path ) node = self[ path[ 0 ] ] if path.length > 1 if node && node.respond_to?( :get_node ) return node.get_node( path[ 1..-1 ] ) end elsif path.length == 1 return node end nil end def get_leaf( path ) node = get_node( path ) if node.respond_to?( :get_node ) # Only want a leaf node nil else node end end end enddiakonos-0.9.0/lib/diakonos/keying.rb000066400000000000000000000304541161735554400175400ustar00rootroot00000000000000module Diakonos module Keying KEYSTRINGS = [ "ctrl+space", # 0 "ctrl+a", # 1 "ctrl+b", # 2 "ctrl+c", # 3 "ctrl+d", # 4 "ctrl+e", # 5 "ctrl+f", # 6 "ctrl+g", # 7 nil, # 8 "tab", # 9 "ctrl+j", # 10 "ctrl+k", # 11 "ctrl+l", # 12 "enter", # 13 "ctrl+n", # 14 "ctrl+o", # 15 "ctrl+p", # 16 "ctrl+q", # 17 "ctrl+r", # 18 "ctrl+s", # 19 "ctrl+t", # 20 "ctrl+u", # 21 "ctrl+v", # 22 "ctrl+w", # 23 "ctrl+x", # 24 "ctrl+y", # 25 "ctrl+z", # 26 "esc", # 27 nil, # 28 nil, # 29 nil, # 30 nil, # 31 "space", # 32 33.chr, 34.chr, 35.chr, 36.chr, 37.chr, 38.chr, 39.chr, 40.chr, 41.chr, 42.chr, 43.chr, 44.chr, 45.chr, 46.chr, 47.chr, 48.chr, 49.chr, 50.chr, 51.chr, 52.chr, 53.chr, 54.chr, 55.chr, 56.chr, 57.chr, 58.chr, 59.chr, 60.chr, 61.chr, 62.chr, 63.chr, 64.chr, 65.chr, 66.chr, 67.chr, 68.chr, 69.chr, 70.chr, 71.chr, 72.chr, 73.chr, 74.chr, 75.chr, 76.chr, 77.chr, 78.chr, 79.chr, 80.chr, 81.chr, 82.chr, 83.chr, 84.chr, 85.chr, 86.chr, 87.chr, 88.chr, 89.chr, 90.chr, 91.chr, 92.chr, 93.chr, 94.chr, 95.chr, 96.chr, 97.chr, 98.chr, 99.chr, 100.chr, 101.chr, 102.chr, 103.chr, 104.chr, 105.chr, 106.chr, 107.chr, 108.chr, 109.chr, 110.chr, 111.chr, 112.chr, 113.chr, 114.chr, 115.chr, 116.chr, 117.chr, 118.chr, 119.chr, 120.chr, 121.chr, 122.chr, 123.chr, 124.chr, 125.chr, 126.chr, "backspace" # 127 ] def self.keycodes_for( str ) retval = case str.downcase when "down" Curses::KEY_DOWN when "up" Curses::KEY_UP when "left" Curses::KEY_LEFT when "right" Curses::KEY_RIGHT when "home" Curses::KEY_HOME when "end" Curses::KEY_END when "insert", "ins" Curses::KEY_IC when "delete", "del" Curses::KEY_DC when "backspace" ::Diakonos::BACKSPACE when "tab" 9 when "pageup", "page-up" Curses::KEY_PPAGE when "pagedown", "page-down" Curses::KEY_NPAGE when "enter", "return" ::Diakonos::ENTER when "numpad7", "keypad7", "kp-7" Curses::KEY_A1 when "numpad9", "keypad9", "kp-9" Curses::KEY_A3 when "numpad5", "keypad5", "kp-5" Curses::KEY_B2 when "numpad1", "keypad1", "kp-1" Curses::KEY_C1 when "numpad3", "keypad3", "kp-3" Curses::KEY_C3 when "escape", "esc" ::Diakonos::ESCAPE when "space" 32 when "ctrl+space" 0 when "find" Curses::KEY_FIND when "select" Curses::KEY_SELECT when "suspend" Curses::KEY_SUSPEND when /^f(\d\d?)$/ Curses::KEY_F0 + $1.to_i when /^ctrl\+[a-gi-z]$/ str.downcase[ -1 ].ord - 96 when /^ctrl\+h$/ ::Diakonos::CTRL_H when /^alt\+(.)$/ [ ::Diakonos::ESCAPE, $1[ 0 ].ord ] when /^ctrl\+alt\+(.)$/, /^alt\+ctrl\+(.)$/ [ ::Diakonos::ESCAPE, str.downcase[ -1 ].ord - 96 ] when /^keycode(\d+)$/ $1.to_i when /^.$/ str[ 0 ].ord end Array( retval ) end def self.key_string_for( num ) retval = KEYSTRINGS[ num ] if retval.nil? retval = case num when Curses::KEY_DOWN "down" when Curses::KEY_UP "up" when Curses::KEY_LEFT "left" when Curses::KEY_RIGHT "right" when Curses::KEY_HOME "home" when Curses::KEY_END "end" when Curses::KEY_IC "insert" when Curses::KEY_DC "delete" when Curses::KEY_PPAGE "page-up" when Curses::KEY_NPAGE "page-down" when Curses::KEY_A1 "numpad7" when Curses::KEY_A3 "numpad9" when Curses::KEY_B2 "numpad5" when Curses::KEY_C1 "numpad1" when Curses::KEY_C3 "numpad3" when Curses::KEY_FIND "find" when Curses::KEY_SELECT "select" when Curses::KEY_SUSPEND "suspend" when Curses::KEY_F0..(Curses::KEY_F0 + 24) "f" + ( num - Curses::KEY_F0 ).to_s when CTRL_H "ctrl+h" when Curses::KEY_RESIZE "resize" when RESIZE2 "resize2" end end if retval.nil? && num.class == Fixnum retval = "keycode#{num}" end retval end end class Diakonos def keychain_str_for( array ) chain_str = "" array.each do |key| key_str = Keying.key_string_for( key ) if key_str chain_str << key_str + " " else chain_str << key.to_s + " " end end chain_str.strip end def capture_keychain( c, context ) if c == ENTER @capturing_keychain = false buffer_current.delete_selection str = keychain_str_for( context ) buffer_current.insert_string str cursor_right( Buffer::STILL_TYPING, str.length ) else keychain_pressed = context.concat [ c ] function_and_args = @modes[ 'edit' ].keymap.get_leaf( keychain_pressed ) if function_and_args function, args = function_and_args end partial_keychain = @modes[ 'edit' ].keymap.get_node( keychain_pressed ) if partial_keychain set_iline( "Part of existing keychain: " + keychain_str_for( keychain_pressed ) + "..." ) else set_iline keychain_str_for( keychain_pressed ) + "..." end process_keystroke keychain_pressed end end def capture_mapping( c, context ) if c == ENTER @capturing_mapping = false buffer_current.delete_selection set_iline else keychain_pressed = context.concat [ c ] function_and_args = @modes[ 'edit' ].keymap.get_leaf( keychain_pressed ) if function_and_args function, args = function_and_args set_iline "#{keychain_str_for( keychain_pressed )} -> #{function}( #{args} )" else partial_keychain = @modes[ 'edit' ].keymap.get_node( keychain_pressed ) if partial_keychain set_iline( "Several mappings start with: " + keychain_str_for( keychain_pressed ) + "..." ) process_keystroke keychain_pressed else set_iline "There is no mapping for " + keychain_str_for( keychain_pressed ) end end end end def typeable?( char ) char > 31 && char < 255 && char != BACKSPACE end # context is an array of characters (bytes) which are keystrokes previously # typed (in a chain of keystrokes) def process_keystroke( context = [], mode = 'edit', ch = nil ) ch ||= @modes[ mode ].window.getch return if ch.nil? c = ch.ord # UTF-8 if 194 <= c && c <= 244 if 194 <= c && c <= 223 # 2-byte character byte_array = [c, @modes[mode].window.getch.ord] elsif 224 <= c && c <= 239 # 3-byte character byte_array = [ c, @modes[mode].window.getch.ord, @modes[mode].window.getch.ord, ] elsif 240 <= c && c <= 244 # 4-byte character byte_array = [ c, @modes[mode].window.getch.ord, @modes[mode].window.getch.ord, @modes[mode].window.getch.ord, ] end char = byte_array.pack('C*').force_encoding('utf-8') type_character char, mode return end if @capturing_keychain capture_keychain c, context elsif @capturing_mapping capture_mapping c, context else if context.empty? && typeable?( c ) type_character ch, mode # Handle X windows paste s = "" loop do ch = nil begin Timeout::timeout( 0.02 ) do ch = @modes[ mode ].window.getch end rescue Timeout::Error => e break end break if ch.nil? c = ch.ord # UTF-8 if 194 <= c && c <= 244 if 194 <= c && c <= 223 # 2-byte character byte_array = [c, @modes[mode].window.getch.ord] elsif 224 <= c && c <= 239 # 3-byte character byte_array = [ c, @modes[mode].window.getch.ord, @modes[mode].window.getch.ord, ] elsif 240 <= c && c <= 244 # 4-byte character byte_array = [ c, @modes[mode].window.getch.ord, @modes[mode].window.getch.ord, @modes[mode].window.getch.ord, ] end char = byte_array.pack('C*').force_encoding('utf-8') s << char elsif typeable?( c ) s << c elsif c == ENTER && mode == 'edit' s << "\n" else break end end if ! s.empty? case mode when 'edit' buffer_current.paste s, Buffer::TYPING when 'input' @readline.paste s end end if ch process_keystroke( [], mode, ch ) end return end keychain_pressed = context.concat [ c ] function_and_args = ( @modes[mode].keymap_after[@function_last].get_leaf( keychain_pressed ) || @modes[mode].keymap.get_leaf( keychain_pressed ) ) if function_and_args function, args = function_and_args @function_last = function if mode != 'input' && ! @settings[ "context.combined" ] set_iline end if args to_eval = "#{function}( #{args} )" else to_eval = function end if @macro_history @macro_history.push to_eval end begin if buffer_current.search_area? && ! ( /^(?:find|readline)/ === to_eval ) buffer_current.search_area = nil end eval to_eval, nil, "eval" @functions_last << to_eval unless to_eval == "repeat_last" if ! @there_was_non_movement @there_was_non_movement = !( /^((cursor|page|scroll)_?(up|down|left|right)|find|seek)/i === to_eval ) end rescue Exception => e debug_log e.message debug_log e.backtrace.join( "\n\t" ) show_exception e end else partial_keychain = @modes[ mode ].keymap.get_node( keychain_pressed ) if partial_keychain if mode != 'input' set_iline( keychain_str_for( keychain_pressed ) + "..." ) end process_keystroke keychain_pressed, mode elsif mode != 'input' set_iline "Nothing assigned to #{keychain_str_for( keychain_pressed )}" end end end end def type_character( c, mode = 'edit' ) if @macro_history @macro_history.push "type_character #{c}, #{mode.inspect}" end @there_was_non_movement = true case mode when 'edit' buffer_current.delete_selection Buffer::DONT_DISPLAY buffer_current.insert_string c cursor_right Buffer::STILL_TYPING when 'input' if ! @readline.numbered_list? @readline.paste c else if( showing_list? && ( (48..57).include?( c.ord ) || (97..122).include?( c.ord ) ) ) line = list_buffer.to_a.select { |l| l =~ /^#{c} / }[ 0 ] if line @readline.list_sync line @readline.finish end end end end end end end diakonos-0.9.0/lib/diakonos/list.rb000066400000000000000000000020211161735554400172120ustar00rootroot00000000000000module Diakonos class Diakonos attr_reader :list_buffer def open_list_buffer @list_buffer = open_file( @list_filename ) end def close_list_buffer close_buffer @list_buffer @list_buffer = nil end def showing_list? @list_buffer end def list_item_selected? @list_buffer and @list_buffer.selecting? end def current_list_item if @list_buffer @list_buffer.set_selection_current_line end end def select_list_item if @list_buffer line = @list_buffer.set_selection_current_line display_buffer @list_buffer line end end def previous_list_item if @list_buffer cursor_up @list_buffer[ @list_buffer.current_row ] end end def next_list_item if @list_buffer cursor_down @list_buffer[ @list_buffer.current_row ] end end def with_list_file File.open( @list_filename, "w" ) do |f| yield f end end end end diakonos-0.9.0/lib/diakonos/logging.rb000066400000000000000000000006441161735554400176760ustar00rootroot00000000000000module Diakonos class Diakonos def log( string ) @log.puts string @log.flush end def debug_log( string ) @debug.puts( Time.now.strftime( "[%a %H:%M:%S] #{string}" ) ) @debug.flush end def log_backtrace begin raise Exception rescue Exception => e e.backtrace[ 1..-1 ].each do |x| debug_log x end end end end enddiakonos-0.9.0/lib/diakonos/mode.rb000066400000000000000000000005451161735554400171740ustar00rootroot00000000000000module Diakonos class Mode attr_reader :keymap, :keymap_after, :window def initialize @keymap = Hash.new.extend( KeyMap ) # keys of @keymap_after are Strings of Diakonos functions @keymap_after = Hash.new { |h,k| h[k] = Hash.new.extend( KeyMap ) } end def window=( w ) @window = w end end end diakonos-0.9.0/lib/diakonos/readline.rb000066400000000000000000000120121161735554400200230ustar00rootroot00000000000000module Diakonos class Readline attr_reader :input # completion_array is the array of strings that tab completion can use # The block returns true if a refresh is needed? # @param options :initial_text, :completion_array, :history, :do_complete, :on_dirs def initialize( diakonos, window, start_pos, options = {}, &block ) @diakonos = diakonos @window = window @start_pos = start_pos @window.setpos( 0, start_pos ) @initial_text = options[ :initial_text ] || '' @completion_array = options[ :completion_array ] @list_filename = @diakonos.list_filename @history = options[ :history ] || [] @history << @initial_text @history_index = [ @history.length - 1, 0 ].max @do_complete = options[ :do_complete ] || ::Diakonos::DONT_COMPLETE @on_dirs = options[ :on_dirs ] || :go_into_dirs @numbered_list = options[ :numbered_list ] @block = block # --- @input = @initial_text.dup if ! @input.empty? call_block end @icurx = @window.curx @icury = @window.cury @view_y = 0 @window.addstr @initial_text @input_cursor = @initial_text.length @opened_list_file = false if @do_complete complete_input end end def call_block if @block @block.call( @input ) @window.refresh end end def set_input( input = '' ) if numbered_list? && input =~ /^\w / input = input[ 3..-1 ] end @input = input end def done? @done end def finish @done = true end def list_sync( line ) return if line.nil? set_input line cursor_write_input end def numbered_list? @numbered_list end def sync if @input_cursor > @input.length @input_cursor = @input.length elsif @input_cursor < @view_y @view_y = @input_cursor end diff = ( @input_cursor - @view_y ) + 1 - ( Curses::cols - @start_pos ) if diff > 0 @view_y += diff end @window.setpos( @window.cury, @start_pos + @input_cursor - @view_y ) redraw_input call_block end def paste( s ) @input = @input[ 0...@input_cursor ] + s + @input[ @input_cursor..-1 ] @input_cursor += s.length sync end def redraw_input input = @input[ @view_y...(@view_y + Curses::cols) ] curx = @window.curx cury = @window.cury @window.setpos( @icury, @icurx ) @window.addstr "%-#{ Curses::cols - curx }s%s" % [ input, " " * [ ( Curses::cols - input.length ), 0 ].max ] @window.setpos( cury, curx ) @window.refresh end # Redisplays the input text starting at the start of the user input area, # positioning the cursor at the end of the text. def cursor_write_input if @input @input_cursor = @input.length @window.setpos( @window.cury, @icurx + @input.length ) redraw_input end end def complete_input if @completion_array && @input.length > 0 len = @input.length matches = @completion_array.find_all { |el| el[ 0...len ] == @input && len <= el.length } else path = File.expand_path( @input || '.' ) if FileTest.directory? path path << '/' end matches = Dir.glob( ( path + "*" ).gsub( /\*\*/, "*" ) ) if @on_dirs == :accept_dirs matches = matches.select { |m| File.directory? m } end end matches.sort! if matches.length == 1 @input = matches[ 0 ] cursor_write_input File.open( @list_filename, "w" ) do |f| if @completion_array.nil? f.puts "(unique)" else f.puts @input end end if @completion_array.nil? && FileTest.directory?( @input ) @input << "/" cursor_write_input if @on_dirs != :accept_dirs complete_input end end elsif matches.length > 1 common = matches[ 0 ] File.open( @list_filename, "w" ) do |f| i = nil matches.each do |match| f.print match if FileTest.directory?( match ) f.print '/' end f.puts if match[ 0 ] != common[ 0 ] common = nil break end up_to = [ common.length - 1, match.length - 1 ].min i = 1 while ( i <= up_to ) && ( match[ 0..i ] == common[ 0..i ] ) i += 1 end common = common[ 0...i ] end end if common.nil? File.open( @list_filename, "w" ) do |f| f.puts "(no matches)" end else @input = common cursor_write_input end else File.open( @list_filename, "w" ) do |f| f.puts "(no matches)" end end @diakonos.open_list_buffer @window.setpos( @window.cury, @window.curx ) end end end diakonos-0.9.0/lib/diakonos/readline/000077500000000000000000000000001161735554400175025ustar00rootroot00000000000000diakonos-0.9.0/lib/diakonos/readline/functions.rb000066400000000000000000000027731161735554400220500ustar00rootroot00000000000000module Diakonos class Readline def abort @input = nil @done = true end def accept( item ) if item && @on_dirs == :go_into_dirs && File.directory?( item ) complete_input else @done = true end end def backspace if cursor_left delete end end def cursor_bol @input_cursor = 0 sync end def cursor_eol @input_cursor = @input.length sync end def cursor_left return false if @input_cursor < 1 @input_cursor -= 1 sync true end def cursor_right return if @input_cursor >= @input.length @input_cursor += 1 sync end def delete return if @input_cursor >= @input.length @input = @input[ 0...@input_cursor ] + @input[ (@input_cursor + 1)..-1 ] sync end def delete_line @input = "" sync end def delete_word head = @input[ 0...@input_cursor ] chopped = head.sub( /\w+\W*$/, '' ) @input = chopped + @input[ @input_cursor..-1 ] @input_cursor -= head.length - chopped.length sync end def history_up return if @history_index < 1 @history[ @history_index ] = @input @history_index -= 1 @input = @history[ @history_index ] end def history_down return if @history_index > @history.length - 2 @history[ @history_index ] = @input @history_index += 1 @input = @history[ @history_index ] end end enddiakonos-0.9.0/lib/diakonos/search.rb000066400000000000000000000033231161735554400175120ustar00rootroot00000000000000module Diakonos class Diakonos # @return [Fixnum] the number of replacements made def find_( options = {} ) regexp_source, replacement = options.values_at( :regexp_source, :replacement ) return if regexp_source.nil? || regexp_source.empty? rs_array = regexp_source.newline_split regexps = Array.new exception_thrown = nil rs_array.each do |source| begin warning_verbosity = $VERBOSE $VERBOSE = nil regexps << Regexp.new( source, options[:case_sensitive] ? nil : Regexp::IGNORECASE ) $VERBOSE = warning_verbosity rescue RegexpError => e if ! exception_thrown exception_thrown = e source = Regexp.escape( source ) retry else raise e end end end if replacement == ASK_REPLACEMENT replacement = get_user_input( "Replace with: ", history: @rlh_search ) end if exception_thrown && ! options[:quiet] set_iline "Searching literally; #{exception_thrown.message}" end # The execution order of the #find and the @last_search_regexps assignment is likely deliberate num_replacements = buffer_current.find( regexps, :direction => options[:direction], :replacement => replacement, :starting_row => options[:starting_row], :starting_col => options[:starting_col], :quiet => options[:quiet], :show_context_after => @settings[ 'find.show_context_after' ], :starting => true ) @last_search_regexps = regexps num_replacements end end end diakonos-0.9.0/lib/diakonos/sessions.rb000066400000000000000000000130131161735554400201100ustar00rootroot00000000000000module Diakonos class Diakonos def new_session( filepath ) basename = File.basename( filepath ) if ! pid_session?( filepath ) name = basename end @session = { 'filename' => File.expand_path( filepath ), 'settings' => Hash.new, 'name' => name, 'buffers' => [], 'buffer_current' => 1, 'dir' => Dir.getwd, } end def initialize_session @session_dir = "#{@diakonos_home}/sessions" mkdir @session_dir new_session "#{@session_dir}/#{Process.pid}" end def session_file_hash_for( filepath ) filepath, line_number = parse_filename_and_line_number( filepath ) { 'filepath' => filepath, 'read_only' => false, 'cursor' => { 'row' => line_number || 0, 'col' => 0, }, 'display' => { 'top_line' => 0, 'left_column' => 0 }, } end def load_session_data( filename ) return if ! File.exist? filename File.open( filename ) do |f| loaded = YAML::load( f ) or break if( loaded[ 'filename' ] && loaded[ 'settings' ] && loaded[ 'settings' ].respond_to?( :values ) && loaded.has_key?( 'name' ) && ( loaded[ 'files' ] && loaded[ 'files' ].respond_to?( :each ) || loaded[ 'buffers' ] && loaded[ 'buffers' ].respond_to?( :each ) ) ) # Convert old sessions if loaded[ 'files' ] loaded[ 'buffers' ] = loaded[ 'files' ].map { |f| session_file_hash_for f } loaded.delete 'files' end @session = loaded end end end def load_session( session_file ) load_session_data session_file if @session @files.concat @session['buffers'] rlh = @session['readline_histories'] if rlh @rlh_general = rlh['general'] || @rlh_general @rlh_files = rlh['files'] || @rlh_files @rlh_search = rlh['search'] || @rlh_search @rlh_shell = rlh['shell'] || @rlh_shell @rlh_help = rlh['help'] || @rlh_help @rlh_sessions = rlh['sessions'] || @rlh_sessions end end end def save_session( session_file = @session[ 'filename' ] ) return if session_file.nil? return if @testing && pid_session?( session_file ) @session[ 'buffers' ] = @buffers.reject { |buffer| buffer.name.nil? }.collect { |buffer| { 'filepath' => buffer.name, 'read_only' => buffer.read_only, 'cursor' => { 'row' => buffer.last_row, 'col' => buffer.last_col, }, 'display' => { 'top_line' => buffer.top_line, 'left_column' => buffer.left_column }, 'last_search_regexps' => buffer.last_search_regexps.map { |r| r.to_s }, } }.compact @session['readline_histories'] = { 'general' => @rlh_general, 'files' => @rlh_files, 'search' => @rlh_search, 'shell' => @rlh_shell, 'help' => @rlh_help, 'sessions' => @rlh_sessions, } File.open( session_file, 'w' ) do |f| f.puts @session.to_yaml end end def session_filepath_for( session_id ) if session_id && session_id !~ %r{/} "#{@session_dir}/#{session_id}" else session_id end end def pid_session?( path = @session[ 'filename' ] ) %r{/\d+$} === path end def session_filepaths @session[ 'buffers' ].map { |b| b[ 'filepath' ] } end def session_startup if @session_to_load pid_session = @session @session = nil session_path = session_filepath_for( @session_to_load ) load_session session_path if ! @session new_session session_path end else session_buffers = [] session_files = Dir[ "#{@session_dir}/*" ].grep( %r{/\d+$} ) pids = session_files.map { |sf| sf[ %r{/(\d+)$}, 1 ].to_i } pids.each do |pid| begin Process.kill 0, pid session_files.reject! { |sf| pid_session? sf } rescue Errno::ESRCH, Errno::EPERM # Process is no longer alive, so we consider the session stale end end session_files.each_with_index do |session_file,index| session_buffers << open_file( session_file ) choice = get_choice( "#{session_files.size} unclosed session(s) found. Open the above files? (session #{index+1} of #{session_files.size})", [ CHOICE_YES, CHOICE_NO, CHOICE_DELETE ], index > 0 ? CHOICE_NO : nil ) case choice when CHOICE_YES load_session session_file if @session File.delete session_file break end when CHOICE_DELETE File.delete session_file end end if session_buffers.empty? && @files.empty? && @settings[ 'session.default_session' ] session_file = session_filepath_for( @settings[ 'session.default_session' ] ) if File.exist? session_file load_session session_file end end end session_buffers end def cleanup_session if pid_session? && File.exists?( @session[ 'filename' ] ) File.delete @session[ 'filename' ] end end end enddiakonos-0.9.0/lib/diakonos/sized-array.rb000066400000000000000000000015021161735554400204740ustar00rootroot00000000000000class SizedArray < Array attr_reader :capacity def initialize( capacity = 10, *args ) @capacity = capacity super( *args ) end def resize if size > @capacity slice!( (0...-@capacity) ) end end private :resize def concat( other_array ) super( other_array ) resize self end def fill( *args ) retval = super( *args ) resize self end def <<( item ) retval = super( item ) if size > @capacity retval = shift end retval end def push( item ) self << item end def unshift( item ) retval = super( item ) if size > @capacity retval = pop end retval end end diakonos-0.9.0/lib/diakonos/text-mark.rb000066400000000000000000000011721161735554400201610ustar00rootroot00000000000000module Diakonos class TextMark attr_reader :formatting, :start_row, :start_col, :end_row, :end_col def initialize( start_row, start_col, end_row, end_col, formatting ) @start_row = start_row @start_col = start_col @end_row = end_row @end_col = end_col @formatting = formatting end def to_s "(#{start_row},#{start_col})-(#{end_row},#{end_col}) #{formatting}" end def contains?( row, col ) if row == start_row start_col <= col elsif row == end_row col < end_col else start_row < row && row < end_row end end end enddiakonos-0.9.0/lib/diakonos/vendor/000077500000000000000000000000001161735554400172145ustar00rootroot00000000000000diakonos-0.9.0/lib/diakonos/vendor/fuzzy_file_finder.rb000066400000000000000000000277141161735554400232710ustar00rootroot00000000000000#-- # ================================================================== # Author: Jamis Buck (jamis@jamisbuck.org) # Date: 2008-10-09 # # This file is in the public domain. Usage, modification, and # redistribution of this file are unrestricted. # ================================================================== #++ # The "fuzzy" file finder provides a way for searching a directory # tree with only a partial name. This is similar to the "cmd-T" # feature in TextMate (http://macromates.com). # # Usage: # # finder = FuzzyFileFinder.new # finder.search("app/blogcon") do |match| # puts match[:highlighted_path] # end # # In the above example, all files matching "app/blogcon" will be # yielded to the block. The given pattern is reduced to a regular # expression internally, so that any file that contains those # characters in that order (even if there are other characters # in between) will match. # # In other words, "app/blogcon" would match any of the following # (parenthesized strings indicate how the match was made): # # * (app)/controllers/(blog)_(con)troller.rb # * lib/c(ap)_(p)ool/(bl)ue_(o)r_(g)reen_(co)loratio(n) # * test/(app)/(blog)_(con)troller_test.rb # # And so forth. class FuzzyFileFinder module Version MAJOR = 1 MINOR = 0 TINY = 4 STRING = [MAJOR, MINOR, TINY].join(".") end # This is the exception that is raised if you try to scan a # directory tree with too many entries. By default, a ceiling of # 10,000 entries is enforced, but you can change that number via # the +ceiling+ parameter to FuzzyFileFinder.new. class TooManyEntries < RuntimeError; end # Used internally to represent a run of characters within a # match. This is used to build the highlighted version of # a file name. class CharacterRun < Struct.new(:string, :inside) #:nodoc: def to_s if inside "(#{string})" else string end end end # Used internally to represent a file within the directory tree. class FileSystemEntry #:nodoc: attr_reader :parent attr_reader :name def initialize(parent, name) @parent = parent @name = name end def path File.join(parent.name, name) end end # Used internally to represent a subdirectory within the directory # tree. class Directory #:nodoc: attr_reader :name def initialize(name, is_root=false) @name = name @is_root = is_root end def root? is_root end end # The roots directory trees to search. attr_reader :roots # The list of files beneath all +roots+ attr_reader :files # The maximum number of files beneath all +roots+ attr_reader :ceiling # The prefix shared by all +roots+. attr_reader :shared_prefix # The list of glob patterns to ignore. attr_reader :ignores # Initializes a new FuzzyFileFinder. This will scan the # given +directories+, using +ceiling+ as the maximum number # of entries to scan. If there are more than +ceiling+ entries # a TooManyEntries exception will be raised. def initialize(directories=['.'], ceiling=10_000, ignores=nil) directories = Array(directories) directories << "." if directories.empty? # expand any paths with ~ root_dirnames = directories.map { |d| File.expand_path(d) }.select { |d| File.directory?(d) }.uniq @roots = root_dirnames.map { |d| Directory.new(d, true) } @shared_prefix = determine_shared_prefix @shared_prefix_re = Regexp.new("^#{Regexp.escape(shared_prefix)}" + (shared_prefix.empty? ? "" : "/")) @files = [] @ceiling = ceiling @ignores = Array(ignores) rescan! end # Rescans the subtree. If the directory contents every change, # you'll need to call this to force the finder to be aware of # the changes. def rescan! @files.clear roots.each { |root| follow_tree(root) } end # Takes the given +pattern+ (which must be a string) and searches # all files beneath +root+, yielding each match. # # +pattern+ is interpreted thus: # # * "foo" : look for any file with the characters 'f', 'o', and 'o' # in its basename (discounting directory names). The characters # must be in that order. # * "foo/bar" : look for any file with the characters 'b', 'a', # and 'r' in its basename (discounting directory names). Also, # any successful match must also have at least one directory # element matching the characters 'f', 'o', and 'o' (in that # order. # * "foo/bar/baz" : same as "foo/bar", but matching two # directory elements in addition to a file name of "baz". # # Each yielded match will be a hash containing the following keys: # # * :path refers to the full path to the file # * :directory refers to the directory of the file # * :name refers to the name of the file (without directory) # * :highlighted_directory refers to the directory of the file with # matches highlighted in parentheses. # * :highlighted_name refers to the name of the file with matches # highlighted in parentheses # * :highlighted_path refers to the full path of the file with # matches highlighted in parentheses # * :abbr refers to an abbreviated form of :highlighted_path, where # path segments without matches are compressed to just their first # character. # * :score refers to a value between 0 and 1 indicating how closely # the file matches the given pattern. A score of 1 means the # pattern matches the file exactly. def search(pattern, &block) pattern.strip! path_parts = pattern.split("/") path_parts.push "" if pattern[-1,1] == "/" file_name_part = path_parts.pop || "" if path_parts.any? path_regex_raw = "^(.*?)" + path_parts.map { |part| make_pattern(part) }.join("(.*?/.*?)") + "(.*?)$" path_regex = Regexp.new(path_regex_raw, Regexp::IGNORECASE) end file_regex_raw = "^(.*?)" << make_pattern(file_name_part) << "(.*)$" file_regex = Regexp.new(file_regex_raw, Regexp::IGNORECASE) path_matches = {} files.each do |file| path_match = match_path(file.parent, path_matches, path_regex, path_parts.length) next if path_match[:missed] match_file(file, file_regex, path_match, &block) end end # Takes the given +pattern+ (which must be a string, formatted as # described in #search), and returns up to +max+ matches in an # Array. If +max+ is nil, all matches will be returned. def find(pattern, max=nil) results = [] search(pattern) do |match| results << match break if max && results.length >= max end return results end # Displays the finder object in a sane, non-explosive manner. def inspect #:nodoc: "#<%s:0x%x roots=%s, files=%d>" % [self.class.name, object_id, roots.map { |r| r.name.inspect }.join(", "), files.length] end private # Recursively scans +directory+ and all files and subdirectories # beneath it, depth-first. def follow_tree(directory) Dir.entries(directory.name).each do |entry| next if entry[0,1] == "." raise TooManyEntries if files.length > ceiling full = File.join(directory.name, entry) if File.directory?(full) follow_tree(Directory.new(full)) elsif !ignore?(full.sub(@shared_prefix_re, "")) files.push(FileSystemEntry.new(directory, entry)) end end end # Returns +true+ if the given name matches any of the ignore # patterns. def ignore?(name) ignores.any? { |pattern| File.fnmatch(pattern, name) } end # Takes the given pattern string "foo" and converts it to a new # string "(f)([^/]*?)(o)([^/]*?)(o)" that can be used to create # a regular expression. def make_pattern(pattern) pattern = pattern.split(//) pattern << "" if pattern.empty? pattern.inject("") do |regex, character| regex << "([^/]*?)" if regex.length > 0 regex << "(" << Regexp.escape(character) << ")" end end # Given a MatchData object +match+ and a number of "inside" # segments to support, compute both the match score and the # highlighted match string. The "inside segments" refers to how # many patterns were matched in this one match. For a file name, # this will always be one. For directories, it will be one for # each directory segment in the original pattern. def build_match_result(match, inside_segments) runs = [] inside_chars = total_chars = 0 match.captures.each_with_index do |capture, index| if capture.length > 0 # odd-numbered captures are matches inside the pattern. # even-numbered captures are matches between the pattern's elements. inside = index % 2 != 0 total_chars += capture.gsub(%r(/), "").length # ignore '/' delimiters inside_chars += capture.length if inside if runs.last && runs.last.inside == inside runs.last.string << capture else runs << CharacterRun.new(capture, inside) end end end # Determine the score of this match. # 1. fewer "inside runs" (runs corresponding to the original pattern) # is better. # 2. better coverage of the actual path name is better inside_runs = runs.select { |r| r.inside } run_ratio = inside_runs.length.zero? ? 1 : inside_segments / inside_runs.length.to_f char_ratio = total_chars.zero? ? 1 : inside_chars.to_f / total_chars score = run_ratio * char_ratio return { :score => score, :result => runs.join } end # Match the given path against the regex, caching the result in +path_matches+. # If +path+ is already cached in the path_matches cache, just return the cached # value. def match_path(path, path_matches, path_regex, path_segments) return path_matches[path] if path_matches.key?(path) name_with_slash = path.name + "/" # add a trailing slash for matching the prefix matchable_name = name_with_slash.sub(@shared_prefix_re, "") matchable_name.chop! # kill the trailing slash if path_regex match = matchable_name.match(path_regex) path_matches[path] = match && build_match_result(match, path_segments) || { :score => 1, :result => matchable_name, :missed => true } else path_matches[path] = { :score => 1, :result => matchable_name } end end # Match +file+ against +file_regex+. If it matches, yield the match # metadata to the block. def match_file(file, file_regex, path_match, &block) if file_match = file.name.match(file_regex) match_result = build_match_result(file_match, 1) full_match_result = path_match[:result].empty? ? match_result[:result] : File.join(path_match[:result], match_result[:result]) shortened_path = path_match[:result].gsub(/[^\/]+/) { |m| m.index("(") ? m : m[0,1] } abbr = shortened_path.empty? ? match_result[:result] : File.join(shortened_path, match_result[:result]) result = { :path => file.path, :abbr => abbr, :directory => file.parent.name, :name => file.name, :highlighted_directory => path_match[:result], :highlighted_name => match_result[:result], :highlighted_path => full_match_result, :score => path_match[:score] * match_result[:score] } yield result end end def determine_shared_prefix # the common case: if there is only a single root, then the entire # name of the root is the shared prefix. return roots.first.name if roots.length == 1 split_roots = roots.map { |root| root.name.split(%r{/}) } segments = split_roots.map { |root| root.length }.max master = split_roots.pop segments.times do |segment| if !split_roots.all? { |root| root[segment] == master[segment] } return master[0,segment].join("/") end end # shouldn't ever get here, since we uniq the root list before # calling this method, but if we do, somehow... return roots.first.name end end diakonos-0.9.0/lib/diakonos/version.rb000066400000000000000000000010721161735554400177310ustar00rootroot00000000000000module Diakonos VERSION = '0.9.0' LAST_MODIFIED = 'July 31, 2011' def self.parse_version( s ) if s s.split( '.' ).map { |part| part.to_i }.extend( Comparable ) end end def self.check_ruby_version ruby_version = parse_version( RUBY_VERSION ) if ruby_version < [ 1, 9 ] $stderr.puts "This version of Diakonos (#{Diakonos::VERSION}) requires Ruby 1.9." if ruby_version >= [ 1, 8 ] $stderr.puts "Version 0.8.9 is the last version of Diakonos which can run under Ruby 1.8." end exit 1 end end end diakonos-0.9.0/lib/diakonos/window.rb000066400000000000000000000011231161735554400175500ustar00rootroot00000000000000module Diakonos class Window < ::Curses::Window if $diakonos.testing def initialize( *args ) # Setup some variables to keep track of a fake cursor @row, @col = 0, 0 super Curses::close_screen end def refresh # Don't refresh when testing end def setpos( row, col ) @row, @col = row, col end def addstr( str ) @col += str.length end def curx @col end def cury @row end def attrset( *args ) # noop end end end enddiakonos-0.9.0/make-help.sh000077500000000000000000000003261161735554400155450ustar00rootroot00000000000000#!/bin/bash if [[ $# == 0 || $1 == --help ]]; then echo "$0 " exit 1 fi VERSION=${1} cp -r help "$VERSION" && \ tar czvf "diakonos-help-$VERSION.tar.gz" "$VERSION" && \ rm -rf "$VERSION" diakonos-0.9.0/make-release.rb000077500000000000000000000042151161735554400162270ustar00rootroot00000000000000#!/usr/bin/env ruby class String def brightRed return "\033[1;31m" + self + "\033[0m" end def brightGreen return "\033[1;32m" + self + "\033[0m" end end def doCommand( command ) puts command.brightGreen if $step do_it = false print "Execute? [y]es, [n]o, yes to [a]ll "; $stdout.flush input = $stdin.gets.strip.downcase case input when 'y' do_it = true when 'a' do_it = true $step = false end else do_it = true end if do_it puts `#{command}` if not $?.nil? and $?.exitstatus > 0 puts "'#{command}' failed with exit code #{$?}".brightRed exit $? end else puts "(skipping)" end end def printUsage puts "#{$0} [--work-dir ] [--step]" end # --------------- if ARGV.length < 1 printUsage exit 1 end version = nil work_dir = '/misc/pistos/unpack' $step = false args = ARGV.dup while args.length > 0 arg = args.shift case arg when '-h', '--help' printUsage exit 1 when '--step' $step = true when '--work-dir' work_dir = args.shift else version = arg end end puts "git tag and export..." doCommand "git tag -a v#{version} -m 'Tagged Diakonos version #{version}.'" doCommand "git archive --format=tar --prefix=diakonos-#{version}/ refs/tags/v#{version} | bzip2 > diakonos-#{version}.tar.bz2" doCommand "git archive --format=tar --prefix=diakonos-#{version}/ refs/tags/v#{version} | gzip > diakonos-#{version}.tar.gz" puts "MD5 sums:" doCommand( "md5sum diakonos-#{version}.tar.gz" ) doCommand( "md5sum diakonos-#{version}.tar.bz2" ) puts "Copying files to website..." doCommand( "scp diakonos-#{version}.tar.bz2 diakonos-#{version}.tar.gz CHANGELOG README.rdoc pistos@diakonos.pist0s.ca:/var/www/diakonos.pist0s.ca/archives" ) puts "Release complete." puts puts "Announcement sites:" puts "1) rubyforge.org" puts "4) diakonos.pist0s.ca" puts "5) blog.purepistos.net" puts "6) RAA" puts "7) http://en.wikipedia.org/wiki/Diakonos" diakonos-0.9.0/make-tarballs.rb000077500000000000000000000006261161735554400164150ustar00rootroot00000000000000#!/bin/sh # This script is only for quickly making the tarballs. # The make-release.rb script is the full script to run for making a release. VERSION=`grep VERSION lib/diakonos/version.rb | egrep -o '[0-9.]+'` git archive --format=tar --prefix=diakonos-${VERSION}/ HEAD | bzip2 > diakonos-${VERSION}.tar.bz2 git archive --format=tar --prefix=diakonos-${VERSION}/ HEAD | gzip > diakonos-${VERSION}.tar.gz diakonos-0.9.0/scripts/000077500000000000000000000000001161735554400150315ustar00rootroot00000000000000diakonos-0.9.0/scripts/home-on-save.rb000066400000000000000000000004441161735554400176560ustar00rootroot00000000000000# This is a trivial example of how to hook Ruby code onto a Diakonos event. # Create a Proc object, then register it with $diakonos.register_proc. example_proc = Proc.new do |buffer| filename = buffer.name $diakonos.cursorBOF end $diakonos.register_proc( example_proc, :after_save )diakonos-0.9.0/spec/000077500000000000000000000000001161735554400142745ustar00rootroot00000000000000diakonos-0.9.0/spec/buffer.rb000066400000000000000000000221011161735554400160660ustar00rootroot00000000000000require_relative 'preparation' def check_word_at( row, col, expected_word ) @b.cursor_to row, col @b.word_under_cursor.should.equal expected_word end def check_paragraph_at( row, col, expected_paragraph ) @b.cursor_to row, col @b.paragraph_under_cursor.should.equal expected_paragraph end describe 'A Diakonos::Buffer' do before do @b = Diakonos::Buffer.new( 'filepath' => SAMPLE_FILE ) end it 'can provide selected text' do @b.anchor_selection( 0, 0 ) @b.cursor_to( 3, 0 ) clip = @b.copy_selection clip.should.equal( [ "#!/usr/bin/env ruby", "", "# This is only a sample file used in the tests.", "" ] ) end it 'can replace text' do @b.find( [ /only/ ], :direction => :down, :replacement => "\\2", :auto_choice => Diakonos::CHOICE_YES_AND_STOP ) @b[ 2 ].should.equal "# This is a sample file used in the tests." @b.find( [ /@x\b/ ], :direction => :down, :replacement => "\\0_", :auto_choice => Diakonos::CHOICE_YES_AND_STOP ) @b[ 8 ].should.equal " @x_ = 1" @b.find( [ /@(y)\b/ ], :direction => :down, :replacement => "@\\1_", :auto_choice => Diakonos::CHOICE_YES_AND_STOP ) @b[ 9 ].should.equal " @y_ = 2" @b.find( [ /(\w+)\.inspect/ ], :direction => :down, :replacement => "print \\1", :auto_choice => Diakonos::CHOICE_YES_AND_STOP ) @b[ 13 ].should.equal " print x" @b.find( [ /(\w+)\.inspect/ ], :direction => :down, :replacement => "puts \\1, \\1, \\1", :auto_choice => Diakonos::CHOICE_YES_AND_STOP ) @b[ 14 ].should.equal " puts y, y, y" @b.find( [ /Sample\.(\w+)/ ], :direction => :down, :replacement => "\\1\\\\\\1", :auto_choice => Diakonos::CHOICE_YES_AND_STOP ) @b[ 18 ].should.equal "s = new\\new" end it 'knows indentation level' do @b.indentation_level( 0 ).should.equal 0 @b.indentation_level( 1 ).should.equal 0 @b.indentation_level( 2 ).should.equal 0 @b.indentation_level( 3 ).should.equal 0 @b.indentation_level( 4 ).should.equal 0 @b.indentation_level( 5 ).should.equal 1 @b.indentation_level( 6 ).should.equal 0 @b.indentation_level( 7 ).should.equal 1 @b.indentation_level( 8 ).should.equal 2 @b.indentation_level( 9 ).should.equal 2 @b.indentation_level( 10 ).should.equal 1 @b.indentation_level( 11 ).should.equal 0 @b.indentation_level( 12 ).should.equal 1 @b.indentation_level( 13 ).should.equal 2 @b.indentation_level( 14 ).should.equal 2 @b.indentation_level( 15 ).should.equal 1 @b.indentation_level( 16 ).should.equal 0 @b.indentation_level( 17 ).should.equal 0 @b.indentation_level( 18 ).should.equal 0 @b.indentation_level( 19 ).should.equal 0 @b.indentation_level( 20 ).should.equal 0 @b.indentation_level( 21 ).should.equal 0 @b.indentation_level( 22 ).should.equal 1 @b.indentation_level( 23 ).should.equal 1 @b.indentation_level( 24 ).should.equal 0 @b.indentation_level( 25 ).should.equal 0 indentation_file = File.join( TEST_DIR, 'indentation.test1' ) b2 = Diakonos::Buffer.new( 'filepath' => indentation_file ) indentation_file = File.join( TEST_DIR, 'indentation.test2' ) b3 = Diakonos::Buffer.new( 'filepath' => indentation_file ) b2.indentation_level( 0 ).should.equal 0 b3.indentation_level( 0 ).should.equal 0 b2.indentation_level( 1 ).should.equal 0 b3.indentation_level( 1 ).should.equal 0 b2.indentation_level( 2 ).should.equal 1 b3.indentation_level( 2 ).should.equal 0 b2.indentation_level( 3 ).should.equal 1 b3.indentation_level( 3 ).should.equal 1 b2.indentation_level( 4 ).should.equal 2 b3.indentation_level( 4 ).should.equal 1 b2.indentation_level( 5 ).should.equal 2 b3.indentation_level( 5 ).should.equal 2 b2.indentation_level( 6 ).should.equal 2 b3.indentation_level( 6 ).should.equal 2 b2.indentation_level( 7 ).should.equal 4 b3.indentation_level( 7 ).should.equal 4 b2.indentation_level( 8 ).should.equal 3 b3.indentation_level( 8 ).should.equal 2 b2.indentation_level( 9 ).should.equal 3 b3.indentation_level( 9 ).should.equal 3 b2.indentation_level( 10 ).should.equal 4 b3.indentation_level( 10 ).should.equal 4 b2.indentation_level( 11 ).should.equal 5 b3.indentation_level( 11 ).should.equal 4 b2.indentation_level( 12 ).should.equal 5 b3.indentation_level( 12 ).should.equal 4 b2.indentation_level( 13 ).should.equal 5 b3.indentation_level( 13 ).should.equal 5 end def indent_rows( from_row = 0, to_row = 20 ) (from_row..to_row).each do |row| @b.parsed_indent row, ::Diakonos::Buffer::DONT_DISPLAY end end it 'can indent smartly' do indent_rows @b.save_copy TEMP_FILE File.read( TEMP_FILE ).should.equal File.read( SAMPLE_FILE ) @b.insert_string " " @b.cursor_to( 5, 0 ) @b.insert_string " " @b.cursor_to( 7, 0 ) @b.insert_string " " @b.cursor_to( 8, 0 ) @b.insert_string " " @b.cursor_to( 14, 0 ) @b.insert_string " " @b.cursor_to( 20, 0 ) @b.insert_string " " @b.save_copy TEMP_FILE File.read( TEMP_FILE ).should.not.equal File.read( SAMPLE_FILE ) indent_rows @b.save_copy TEMP_FILE File.read( TEMP_FILE ).should.equal File.read( SAMPLE_FILE ) # ------- @b = Diakonos::Buffer.new( 'filepath' => SAMPLE_FILE_C ) indent_rows 0, 14 @b.save_copy TEMP_FILE_C File.read( TEMP_FILE_C ).should.equal File.read( SAMPLE_FILE_C ) @b.cursor_to( 3, 0 ) @b.insert_string " " @b.cursor_to( 10, 0 ) @b.insert_string " " @b.cursor_to( 12, 0 ) @b.insert_string " " @b.save_copy TEMP_FILE_C File.read( TEMP_FILE_C ).should.not.equal File.read( SAMPLE_FILE_C ) indent_rows 0, 14 @b.save_copy TEMP_FILE_C File.read( TEMP_FILE_C ).should.equal File.read( SAMPLE_FILE_C ) end it 'can paste an Array of Strings' do lines = @b.to_a new_lines = [ 'line 1', 'line 2' ] @b.paste( new_lines + [ '' ] ) lines2 = @b.to_a lines2.should.equal( new_lines + lines ) end it 'can delete a line' do original_lines = @b.to_a @b.delete_line.should.equal '#!/usr/bin/env ruby' @b.to_a.should.equal original_lines[ 1..-1 ] end it 'knows the word under the cursor' do check_word_at 0, 16, 'ruby' check_word_at 2, 0, nil check_word_at 2, 2, 'This' check_word_at 2, 3, 'This' check_word_at 2, 4, 'This' check_word_at 2, 5, 'This' check_word_at 2, 6, nil check_word_at 2, 45, 'tests' check_word_at 2, 46, nil check_word_at 2, 47, nil check_word_at 3, 0, nil check_word_at 5, 14, nil check_word_at 5, 15, 'x' check_word_at 5, 16, nil check_word_at 14, 4, 'y' check_word_at 14, 5, nil check_word_at 14, 6, 'inspect' check_word_at 21, 0, nil check_word_at 22, 8, nil check_word_at 22, 9, nil check_word_at 26, 39, 'EOF' check_word_at 26, 40, nil end it 'knows the paragraph under the cursor' do check_paragraph_at 0, 0, [ '#!/usr/bin/env ruby', ] check_paragraph_at 2, 0, [ '# This is only a sample file used in the tests.', ] check_paragraph_at 4, 0, [ 'class Sample', ' attr_reader :x, :y', ] check_paragraph_at 7, 0, [ ' def initialize', ' @x = 1', ' @y = 2', ' end', ] check_paragraph_at 14, 7, [ ' def inspection', ' x.inspect', ' y.inspect', ' end', 'end', ] check_paragraph_at 22, 7, [ '{', ' :just => :a,', ' :test => :hash,', '}', ] check_paragraph_at 26, 12, [ '# Comment at end, with no newline at EOF', ] end end describe 'A Diakonos user' do before do @b = Diakonos::Buffer.new( 'filepath' => SAMPLE_FILE ) end it 'can close XML tags' do @b.set_type 'html' @b.cursor_to 0,0 @b.cursor_to_eol @b.carriage_return @b.paste "
" @b.close_code @b[ @b.last_row ].should.equal '
' cursor_should_be_at @b.last_row, 5 @b.cursor_to_eol @b.carriage_return @b.paste "
" @b.close_code @b[ @b.last_row ].should.equal '
' cursor_should_be_at @b.last_row, 11 @b.set_type 'xml' @b.cursor_to_eol @b.carriage_return @b.paste "" @b.close_code @b[ @b.last_row ].should.equal '' cursor_should_be_at @b.last_row, 19 @b.cursor_to_eol @b.carriage_return @b.paste "" @b.close_code @b[ @b.last_row ].should.equal '' cursor_should_be_at @b.last_row, 31 @b.cursor_to_eol @b.carriage_return @b.paste "" @b.close_code @b[ @b.last_row ].should.equal "" cursor_should_be_at @b.last_row, 30 @b.cursor_to_eol @b.carriage_return @b.paste "" @b.close_code @b[ @b.last_row ].should.equal "" cursor_should_be_at @b.last_row, 49 end enddiakonos-0.9.0/spec/clipboard.rb000066400000000000000000000035651161735554400165710ustar00rootroot00000000000000require_relative 'preparation' describe 'A Diakonos::Clipboard' do it 'can accept new clips via #add_clip' do c = Diakonos::Clipboard.new( 3 ) c.add_clip( nil ).should.be.false c.add_clip( [ 'foo' ] ).should.be.true c.add_clip( [ 'bar' ] ).should.be.true c.add_clip( [ 'baz' ] ).should.be.true c[ 2 ].should.equal [ 'foo' ] c[ 3 ].should.be.nil c.add_clip( [ 'fiz' ] ).should.be.true c[ 2 ].should.equal [ 'bar' ] c[ 3 ].should.be.nil end it 'provides access to clips via #[]' do c = Diakonos::Clipboard.new( 3 ) c[ -1 ].should.be.nil c[ 0 ].should.be.nil c[ 1 ].should.be.nil c.add_clip( nil ).should.be.false x = [ 'foo' ] c.add_clip( x ).should.be.true c[ -1 ].should.equal x c[ 0 ].should.equal x c[ 1 ].should.be.nil end it 'can be iterated over via #each' do c = Diakonos::Clipboard.new( 10 ) 9.downto( 0 ) do |i| c.add_clip( [ i.to_s ] ) end i = 0 c.each do |clip| clip.should.equal [ i.to_s ] i += 1 end end it 'provides #append_to_clip to append to clips' do c = Diakonos::Clipboard.new( 10 ) c.append_to_clip( nil ).should.be.false x = [ 'foo' ] c.append_to_clip( x ).should.be.true c.clip.should.equal [ 'foo' ] c.append_to_clip( [ 'bar', 'baz' ] ).should.be.true c.clip.should.equal [ 'foo', 'bar', 'baz' ] y = [ 'line with newline', '' ] c.add_clip( y ).should.be.true c.clip.should.equal y c.append_to_clip( [ 'another line' ] ).should.be.true c.clip.should.equal [ 'line with newline', 'another line' ] c.add_clip( [ 'line1', '' ] ).should.be.true c.clip.should.equal [ 'line1', '' ] c.append_to_clip( [ '', '' ] ).should.be.true c.clip.should.equal [ 'line1', '', '' ] c.append_to_clip( [ 'line2', '' ] ).should.be.true c.clip.should.equal [ 'line1', '', 'line2', '' ] end enddiakonos-0.9.0/spec/functions/000077500000000000000000000000001161735554400163045ustar00rootroot00000000000000diakonos-0.9.0/spec/functions/basics.rb000066400000000000000000000015611161735554400201000ustar00rootroot00000000000000require_relative '../preparation' describe 'A Diakonos user can' do before do @d = $diakonos @b = @d.open_file( SAMPLE_FILE ) cursor_should_be_at 0,0 end after do @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL end it 'delete the current character' do @d.delete cursor_should_be_at 0,0 @b.to_a[ 0 ].should.equal '!/usr/bin/env ruby' end it 'backspace the previous character' do 3.times{ @d.cursor_right } cursor_should_be_at 0,3 @d.backspace @b.to_a[ 0 ].should.equal '#!usr/bin/env ruby' cursor_should_be_at 0,2 end it 'insert a newline character' do 5.times{ @d.cursor_right } @d.carriage_return cursor_should_be_at 1,0 lines = @b.to_a lines[ 0..3 ].should.equal [ '#!/us', 'r/bin/env ruby', '', '# This is only a sample file used in the tests.', ] end end diakonos-0.9.0/spec/functions/buffer.rb000066400000000000000000000105421161735554400201040ustar00rootroot00000000000000require_relative '../preparation' describe 'A Diakonos user can' do before do @d = $diakonos @b = @d.open_file( SAMPLE_FILE ) cursor_should_be_at 0,0 end after do @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL end it 'can close a buffer' do name = @d.buffer_current.name n = @d.buffers.size n.should > 0 @d.buffers.map(&:name).should.include name @d.close_buffer @d.buffers.size.should.equal n-1 @d.buffer_current.name.should.not.equal name @d.buffers.map(&:name).should.not.include name end it 'open a file at a specific line number' do @b = @d.open_file( "#{SAMPLE_FILE_LONGER}:45" ) cursor_should_be_at 44, 0 @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL @b = @d.open_file( "#{SAMPLE_FILE_LONGER}:50:" ) cursor_should_be_at 49, 0 @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL @b = @d.open_file( "#{SAMPLE_FILE_LONGER}:54: in `block in methodname'" ) cursor_should_be_at 53, 0 @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL @b = @d.open_file( " from #{SAMPLE_FILE_LONGER}:57: in `block in methodname'" ) cursor_should_be_at 56, 0 @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL @b = @d.open_file( %{ File "#{SAMPLE_FILE_LONGER}", line 55, in decoration} ) cursor_should_be_at 54, 0 @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL @b = @d.open_file( " at #{SAMPLE_FILE_LONGER} line 61" ) cursor_should_be_at 60, 0 end it 'start up Diakonos and open a file at a specific line' do d2 = Diakonos::Diakonos.new [ '-e', 'quit', '--test', "#{SAMPLE_FILE_LONGER}:45" ] d2.start @b = d2.buffer_current cursor_should_be_at 44, 0 end it 'renumber a buffer' do @d.open_file SAMPLE_FILE_LONGER @d.open_file SAMPLE_FILE_C numbered_buffer_should_be_named 2, 'sample-file.rb' numbered_buffer_should_be_named 3, 'longer-sample-file.rb' numbered_buffer_should_be_named 4, 'sample-file.c' @d.switch_to_buffer_number 2 name = File.basename( @d.buffer_current.name ) name.should.equal 'sample-file.rb' @d.renumber_buffer 4 name = File.basename( @d.buffer_current.name ) name.should.equal 'sample-file.rb' numbered_buffer_should_be_named 2, 'longer-sample-file.rb' numbered_buffer_should_be_named 3, 'sample-file.c' numbered_buffer_should_be_named 4, 'sample-file.rb' @d.switch_to_buffer_number 3 name = File.basename( @d.buffer_current.name ) name.should.equal 'sample-file.c' @d.renumber_buffer 2 name = File.basename( @d.buffer_current.name ) name.should.equal 'sample-file.c' numbered_buffer_should_be_named 2, 'sample-file.c' numbered_buffer_should_be_named 3, 'longer-sample-file.rb' numbered_buffer_should_be_named 4, 'sample-file.rb' @d.switch_to_buffer_number 2 # Switch twice because of Diakonos' behaviour of switching to previous # buffer when trying to switching to the current buffer. @d.switch_to_buffer_number 2 name = File.basename( @d.buffer_current.name ) name.should.equal 'sample-file.c' @d.renumber_buffer 2 numbered_buffer_should_be_named 2, 'sample-file.c' numbered_buffer_should_be_named 3, 'longer-sample-file.rb' numbered_buffer_should_be_named 4, 'sample-file.rb' name = File.basename( @d.buffer_current.name ) name.should.equal 'sample-file.c' @d.renumber_buffer 5 numbered_buffer_should_be_named 2, 'longer-sample-file.rb' numbered_buffer_should_be_named 3, 'sample-file.rb' numbered_buffer_should_be_named 4, 'sample-file.c' @d.renumber_buffer 99 numbered_buffer_should_be_named 2, 'longer-sample-file.rb' numbered_buffer_should_be_named 3, 'sample-file.rb' numbered_buffer_should_be_named 4, 'sample-file.c' @d.renumber_buffer 1 numbered_buffer_should_be_named 1, 'sample-file.c' numbered_buffer_should_be_named 3, 'longer-sample-file.rb' numbered_buffer_should_be_named 4, 'sample-file.rb' should.raise do @d.renumber_buffer 0 end numbered_buffer_should_be_named 1, 'sample-file.c' numbered_buffer_should_be_named 3, 'longer-sample-file.rb' numbered_buffer_should_be_named 4, 'sample-file.rb' should.raise do @d.renumber_buffer -1 end numbered_buffer_should_be_named 1, 'sample-file.c' numbered_buffer_should_be_named 3, 'longer-sample-file.rb' numbered_buffer_should_be_named 4, 'sample-file.rb' end end diakonos-0.9.0/spec/functions/clipboard.rb000066400000000000000000000042311161735554400205700ustar00rootroot00000000000000require_relative '../preparation' describe 'A Diakonos user can' do before do @d = $diakonos @b = @d.open_file( SAMPLE_FILE ) cursor_should_be_at 0,0 end after do @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL end it 'copy selected text' do @d.anchor_selection @d.cursor_down @d.cursor_down @d.cursor_down @d.copy_selection @d.clipboard.clip.should.equal [ '#!/usr/bin/env ruby', '', '# This is only a sample file used in the tests.', '', ] end it 'cut selected text' do @d.anchor_selection @d.cursor_down @d.cursor_down @d.cursor_down @d.cut_selection @d.clipboard.clip.should.equal [ '#!/usr/bin/env ruby', '', '# This is only a sample file used in the tests.', '', ] lines = @b.to_a lines.size.should.equal 24 lines[ 0..2 ].should.equal [ '', 'class Sample', ' attr_reader :x, :y', ] end it 'paste from the clipboard' do @d.anchor_selection 3.times { @d.cursor_down } @d.copy_selection @d.paste lines = @b.to_a lines.size.should.equal 30 lines[ 0..8 ].should.equal [ '#!/usr/bin/env ruby', '', '# This is only a sample file used in the tests.', '#!/usr/bin/env ruby', '', '# This is only a sample file used in the tests.', '', 'class Sample', ' attr_reader :x, :y', ] end it 'cut consecutive lines' do original_lines = @b.to_a @d.cursor_bof @d.delete_and_store_line @d.functions_last << 'delete_and_store_line' @d.clipboard.clip.should.equal( [ '#!/usr/bin/env ruby', '', ] ) @d.delete_and_store_line @d.functions_last << 'delete_and_store_line' @d.clipboard.clip.should.equal( [ '#!/usr/bin/env ruby', '', '', ] ) @d.delete_and_store_line @d.functions_last << 'delete_and_store_line' @d.clipboard.clip.should.equal( [ '#!/usr/bin/env ruby', '', '# This is only a sample file used in the tests.', '', ] ) @b.to_a.should.not.equal original_lines @d.paste @b.to_a.should.equal original_lines end end diakonos-0.9.0/spec/functions/cursor.rb000066400000000000000000000066511161735554400201560ustar00rootroot00000000000000require_relative '../preparation' describe 'A Diakonos user can' do before do @d = $diakonos @b = @d.open_file( SAMPLE_FILE ) end after do @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL end it 'move the cursor in the four basic directions' do cursor_should_be_at 0,0 @d.cursor_down cursor_should_be_at 1,0 @d.cursor_up cursor_should_be_at 0,0 @d.cursor_right cursor_should_be_at 0,1 @d.cursor_left cursor_should_be_at 0,0 end it 'move the cursor to the end of a line' do @d.cursor_eol cursor_should_be_at 0,19 end it 'move the cursor to the beginning of a line' do @b.cursor_to 2,2 @d.cursor_bol cursor_should_be_at 2,0 end it 'move the cursor to the end of a file' do @d.cursor_eof cursor_should_be_at 26,40 end it 'move the cursor to the beginning of a file' do @b.cursor_to 2,2 @d.cursor_bof cursor_should_be_at 0,0 end it 'move the cursor to the next occurrence of a character' do cursor_should_be_at 0,0 @d.go_to_char :on, '.' cursor_should_be_at 2,46 @d.go_to_char :on, 'c' cursor_should_be_at 4,0 @d.go_to_char :on, 'a' cursor_should_be_at 4,2 @d.go_to_char :on, 'a' cursor_should_be_at 4,7 @d.go_to_char :on, ':' cursor_should_be_at 5,14 @d.go_to_char :on, '=' cursor_should_be_at 8,7 @d.go_to_char :on, '`' cursor_should_be_at 8,7 @b.cursor_to 0,0 @d.go_to_char :after, '.' cursor_should_be_at 2,47 @d.go_to_char :after, 'c' cursor_should_be_at 4,1 @d.go_to_char :after, 'a' cursor_should_be_at 4,3 @d.go_to_char :after, 'a' cursor_should_be_at 4,8 @d.go_to_char :after, ':' cursor_should_be_at 5,15 @d.go_to_char :after, '=' cursor_should_be_at 8,8 @d.go_to_char :after, '`' cursor_should_be_at 8,8 @b.cursor_to 18,0 @b.go_to_char 's' cursor_should_be_at 19,0 @b.cursor_to 18,0 @b.go_to_char 's', Diakonos::ON_CHAR cursor_should_be_at 19,0 @b.cursor_to 18,0 @b.go_to_char 's', Diakonos::AFTER_CHAR cursor_should_be_at 19,1 end it 'move the cursor to the closest previous occurrence of a character' do @d.cursor_eof cursor_should_be_at 26,40 @d.go_to_char_previous :on, '.' cursor_should_be_at 19,1 @d.go_to_char_previous :on, 'e' cursor_should_be_at 18,12 @d.go_to_char_previous :on, 's' cursor_should_be_at 18,0 @d.go_to_char_previous :on, 't' cursor_should_be_at 14,12 @d.go_to_char_previous :on, 't' r,c = 13,12 cursor_should_be_at r,c @d.go_to_char_previous :on, '%' cursor_should_be_at r,c @d.cursor_eof cursor_should_be_at 26,40 @d.go_to_char_previous :after, '.' cursor_should_be_at 19,2 @d.go_to_char_previous :after, 'e' cursor_should_be_at 18,13 @d.go_to_char_previous :after, 's' cursor_should_be_at 18,1 @d.go_to_char_previous :after, 't' cursor_should_be_at 14,13 @d.go_to_char_previous :after, 'i' cursor_should_be_at 14,7 @d.go_to_char_previous :after, 'n' r,c = 13,8 cursor_should_be_at r,c @d.go_to_char_previous :after, '%' cursor_should_be_at r,c @b.cursor_to 19,0 @b.go_to_char_previous 's' cursor_should_be_at 18,0 @b.cursor_to 19,0 @b.go_to_char_previous 's', Diakonos::ON_CHAR cursor_should_be_at 18,0 @b.cursor_to 19,0 @b.go_to_char_previous 's', Diakonos::AFTER_CHAR cursor_should_be_at 18,1 end enddiakonos-0.9.0/spec/functions/selection.rb000066400000000000000000000053251161735554400206230ustar00rootroot00000000000000require_relative '../preparation' describe 'A Diakonos user can' do before do @d = $diakonos @b = @d.open_file( SAMPLE_FILE ) cursor_should_be_at 0,0 end after do @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL end it 'select text' do @d.anchor_selection @d.cursor_down @d.cursor_down @d.cursor_down cursor_should_be_at 3,0 selection = @b.selection_mark selection.start_row.should.equal 0 selection.start_col.should.equal 0 selection.end_row.should.equal 3 selection.end_col.should.equal 0 end it 'stop selecting text' do @b.selection_mark.should.be.nil @d.anchor_selection @d.cursor_down @d.cursor_down @b.selection_mark.should.not.be.nil @d.remove_selection @b.selection_mark.should.be.nil end it 'select the whole file at once' do @b.selection_mark.should.be.nil @d.select_all s = @b.selection_mark s.start_row.should.equal 0 s.start_col.should.equal 0 s.end_row.should.equal 26 s.end_col.should.equal 40 end it 'delete the selection' do @d.anchor_selection 3.times { @d.cursor_down } @d.delete @b.to_a[ 0..2 ].should.equal [ '', 'class Sample', ' attr_reader :x, :y', ] cursor_should_be_at 0,0 end it 'select the word at the cursor position' do @b.cursor_to 2,4 @d.select_word selection_should_be 2,2, 2,6 cursor_should_be_at 2,6 @b.cursor_to 2,2 @d.select_word selection_should_be 2,2, 2,6 cursor_should_be_at 2,6 @b.cursor_to 2,5 @d.select_word selection_should_be 2,2, 2,6 cursor_should_be_at 2,6 @b.cursor_to 2,1 @d.select_word selection_should_be 2,2, 2,6 cursor_should_be_at 2,6 @d.cursor_right selection_should_be 2,2, 2,7 cursor_should_be_at 2,7 @d.remove_selection @b.cursor_to 26,40 @d.select_word s = @b.selection_mark s.should.be.nil cursor_should_be_at 26,40 end it 'extend a selection wordwise' do @b.cursor_to 2,4 @d.select_word selection_should_be 2,2, 2,6 @d.select_word_another selection_should_be 2,2, 2,9 cursor_should_be_at 2,9 @d.select_word_another selection_should_be 2,2, 2,14 cursor_should_be_at 2,14 @d.select_word_another selection_should_be 2,2, 2,16 cursor_should_be_at 2,16 @d.select_word_another selection_should_be 2,2, 2,23 cursor_should_be_at 2,23 @d.cursor_right selection_should_be 2,2, 2,24 cursor_should_be_at 2,24 @d.remove_selection @b.cursor_to 26,34 @d.select_word selection_should_be 26,34, 26,36 @d.select_word_another selection_should_be 26,34, 26,40 @d.select_word_another selection_should_be 26,34, 26,40 end end diakonos-0.9.0/spec/functions/text-manipulation.rb000066400000000000000000000206771161735554400223270ustar00rootroot00000000000000require_relative '../preparation' describe 'A Diakonos user can' do before do @d = $diakonos @b = @d.open_file( SAMPLE_FILE ) cursor_should_be_at 0,0 end after do @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL end it 'collapse whitespace' do @b.to_a[ 2 ].should.equal '# This is only a sample file used in the tests.' @b.cursor_to 2,9 5.times { @d.type_character ' ' } cursor_should_be_at 2,14 @b.to_a[ 2 ].should.equal '# This is only a sample file used in the tests.' @d.collapse_whitespace cursor_should_be_at 2,9 @b.to_a[ 2 ].should.equal '# This is only a sample file used in the tests.' end it 'columnize source code' do @b.cursor_to 8,7 3.times { @d.type_character ' ' } @b.to_a[ 8..10 ].should.equal [ ' @x = 1', ' @y = 2', ' end', ] @b.cursor_to 8,0 @d.anchor_selection 2.times { @d.cursor_down } @d.columnize '=' @b.to_a[ 8..10 ].should.equal [ ' @x = 1', ' @y = 2', ' end', ] cursor_should_be_at 10,0 end it 'comment out and uncomment a single line' do @b.cursor_to 4,0 @b.selection_mark.should.be.nil @b.to_a[ 4 ].should.equal 'class Sample' @d.comment_out @b.to_a[ 4 ].should.equal '# class Sample' @d.comment_out @b.to_a[ 4 ].should.equal '# # class Sample' @d.uncomment @b.to_a[ 4 ].should.equal '# class Sample' @d.uncomment @b.to_a[ 4 ].should.equal 'class Sample' @d.uncomment @b.to_a[ 4 ].should.equal 'class Sample' end it 'comment out and uncomment selected lines' do @b.cursor_to 7,0 @d.anchor_selection 4.times { @d.cursor_down } @d.comment_out @b.to_a[ 7..11 ].should.equal [ ' # def initialize', ' # @x = 1', ' # @y = 2', ' # end', '', ] @b.selection_mark.should.not.be.nil cursor_should_be_at 11,0 @d.uncomment @b.to_a[ 7..11 ].should.equal [ ' def initialize', ' @x = 1', ' @y = 2', ' end', '', ] @b.selection_mark.should.not.be.nil cursor_should_be_at 11,0 # Uncommenting lines that are not commented should do nothing @d.uncomment @b.to_a[ 7..11 ].should.equal [ ' def initialize', ' @x = 1', ' @y = 2', ' end', '', ] @b.selection_mark.should.not.be.nil cursor_should_be_at 11,0 end it 'not comment out blank lines' do @b.cursor_to 3,0 @b.selection_mark.should.be.nil @b.to_a[ 3 ].should.equal '' @d.comment_out @b.to_a[ 3 ].should.equal '' @b.cursor_to 6,0 @b.selection_mark.should.be.nil @b.to_a[ 6 ].should.equal '' @d.comment_out @b.to_a[ 6 ].should.equal '' @b.cursor_to 5,0 @d.anchor_selection 3.times { @d.cursor_down } @d.comment_out @b.to_a[ 5..7 ].should.equal [ ' # attr_reader :x, :y', '', ' # def initialize', ] @b.selection_mark.should.not.be.nil cursor_should_be_at 8,0 end it 'delete until a character' do @b.cursor_to 5,2 @b.to_a[ 5 ].should.equal ' attr_reader :x, :y' @d.delete_to ':' cursor_should_be_at 5,2 @b.to_a[ 5 ].should.equal ' :x, :y' end it 'delete from a character' do @b.cursor_to 12,11 @d.delete_from ' ' cursor_should_be_at 12,6 @b.to_a[12].should.equal ' def ction' @b.cursor_to 7,6 @d.delete_from ' ' cursor_should_be_at 7,6 @b.to_a[7].should.equal ' def initialize' @b.cursor_to 7,5 @d.delete_from ' ' cursor_should_be_at 7,2 @b.to_a[7].should.equal ' initialize' end it 'not delete from a non-existent character' do @b.cursor_to 7,6 @d.delete_from '@' @b.should.not.be.modified @b.to_a[7].should.equal ' def initialize' end it 'delete between matching characters' do @b.cursor_to 2,15 @b.to_a[ 2 ].should.equal '# This is only a sample file used in the tests.' @d.delete_to_and_from :not_inclusive, 'h' @b.to_a[ 2 ].should.equal '# Thhe tests.' cursor_should_be_at 2,4 @b.cursor_to 22,2 @d.delete_to_and_from :not_inclusive, '{' lines = @b.to_a lines.size.should.equal 24 lines[ 21..22 ].should.equal [ '{}', '', ] end it 'delete between matching characters, inclusive' do @b.cursor_to 2,15 @b.to_a[ 2 ].should.equal '# This is only a sample file used in the tests.' @d.delete_to_and_from :inclusive, 'h' @b.to_a[ 2 ].should.equal '# Te tests.' cursor_should_be_at 2,3 @b.cursor_to 22,2 @d.delete_to_and_from :inclusive, '{' lines = @b.to_a lines.size.should.equal 24 lines[ 21..22 ].should.equal [ '', '', ] end it 'automatically indent selected code' do @d.set_buffer_type 'text' @d.anchor_selection @d.cursor_eof @b.selection_mark.should.not.be.nil @d.parsed_indent @b.to_a.should.equal [ '#!/usr/bin/env ruby', '', '# This is only a sample file used in the tests.', '', 'class Sample', 'attr_reader :x, :y', '', 'def initialize', '@x = 1', '@y = 2', 'end', '', 'def inspection', 'x.inspect', 'y.inspect', 'end', 'end', '', 's = Sample.new', 's.inspection', '', '{', ':just => :a,', ':test => :hash,', '}', '', '# Comment at end, with no newline at EOF', ] @d.set_buffer_type 'ruby' @b.selection_mark.should.not.be.nil @d.parsed_indent @b.to_a.should.equal [ '#!/usr/bin/env ruby', '', '# This is only a sample file used in the tests.', '', 'class Sample', ' attr_reader :x, :y', ' ', ' def initialize', ' @x = 1', ' @y = 2', ' end', ' ', ' def inspection', ' x.inspect', ' y.inspect', ' end', 'end', '', 's = Sample.new', 's.inspection', '', '{', ' :just => :a,', ' :test => :hash,', '}', '', '# Comment at end, with no newline at EOF', ] end it 'join lines' do @d.join_lines @b.to_a[ 0..2 ].should.equal [ '#!/usr/bin/env ruby ', '# This is only a sample file used in the tests.', '', ] @d.join_lines @b.to_a[ 0..2 ].should.equal [ '#!/usr/bin/env ruby # This is only a sample file used in the tests.', '', 'class Sample', ] end it 'surround selections with parentheses' do @b.set_selection 4, 6, 4, 12 @d.surround_selection '(' @b[ 4 ].should.equal 'class ( Sample )' @d.undo @b.set_selection 4, 0, 4, 12 @d.surround_selection '(' @b[ 4 ].should.equal '( class Sample )' @d.undo @b.set_selection 4, 0, 5, 20 @d.surround_selection '(' @b[ 4..5 ].should.equal [ '( class Sample', ' attr_reader :x, :y )' ] @d.undo @b.set_type 'html' @b.set_selection 7, 2, 7, 5 @d.surround_selection ' initialize' @d.undo @b.set_selection 7, 2, 7, 5 @d.surround_selection '' @b[ 7 ].should.equal ' def initialize' @d.undo end it 'word wrap paragraphs of text' do @b = @d.open_file( File.join(TEST_DIR, '/lorem-ipsum.txt') ) @b.length.should == 2 cursor_should_be_at 0,0 @b.wrap_paragraph @b.to_a.should == [ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus.', 'Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec', 'consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget', 'libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut', 'porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a', 'non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean', 'ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id', 'dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur', 'dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut', 'convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec', 'viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque', 'penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum', 'accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.', '', ] cursor_should_be_at 13,0 end end diakonos-0.9.0/spec/internal.rb000066400000000000000000000015141161735554400164360ustar00rootroot00000000000000require_relative 'preparation' describe 'Diakonos can' do before do @d = $diakonos end after do end it 'parse a filename and line number from a String' do @d.parse_filename_and_line_number( 'abc.rb' ).should.equal [ 'abc.rb', nil ] @d.parse_filename_and_line_number( '/absolute/path/abc.rb' ).should.equal [ '/absolute/path/abc.rb', nil ] @d.parse_filename_and_line_number( 'abc.rb:1' ).should.equal [ 'abc.rb', 0 ] @d.parse_filename_and_line_number( 'abc.rb:5' ).should.equal [ 'abc.rb', 4 ] @d.parse_filename_and_line_number( 'abc.rb:10' ).should.equal [ 'abc.rb', 9 ] @d.parse_filename_and_line_number( '/absolute/path/abc.rb:15' ).should.equal [ '/absolute/path/abc.rb', 14 ] @d.parse_filename_and_line_number( 'relative/path/abc.rb:15' ).should.equal [ 'relative/path/abc.rb', 14 ] end end diakonos-0.9.0/spec/key-map.rb000066400000000000000000000140421161735554400161650ustar00rootroot00000000000000require_relative 'preparation' describe 'A KeyMap' do it 'can delete a key path' do g = {}.extend( Diakonos::KeyMap ) h = g.deep_clone h.delete_key_path( [] ).should.equal( {} ) h = g.deep_clone h.delete_key_path( [ 'test' ] ).should.equal( {} ) h = g.deep_clone h.delete_key_path( [ 'test', 'test2' ] ).should.equal( {} ) g = { 'a' => 'x' }.extend( Diakonos::KeyMap ) h = g.deep_clone h.delete_key_path( [] ).should.equal( { 'a' => 'x' } ) h = g.deep_clone h.delete_key_path( [ 'test' ] ).should.equal( { 'a' => 'x' } ) h = g.deep_clone h.delete_key_path( [ 'test', 'test2' ] ).should.equal( { 'a' => 'x' } ) h = g.deep_clone h.delete_key_path( [ 'a' ] ).should.equal( {} ) h = g.deep_clone h.delete_key_path( [ 'a', 'b' ] ).should.equal( { 'a' => 'x' } ) g = { 'a' => { 'b' => 'x' } }.extend( Diakonos::KeyMap ) h = g.deep_clone h.delete_key_path( [] ).should.equal( { 'a' => { 'b' => 'x' } } ) h = g.deep_clone h.delete_key_path( [ 'z' ] ).should.equal( { 'a' => { 'b' => 'x' } } ) h = g.deep_clone h.delete_key_path( [ 'z', 'zz' ] ).should.equal( { 'a' => { 'b' => 'x' } } ) h = g.deep_clone h.delete_key_path( [ 'a', 'b', 'c' ] ).should.equal( { 'a' => { 'b' => 'x' } } ) h = g.deep_clone h.delete_key_path( [ 'a' ] ).should.equal( {} ) h = g.deep_clone h.delete_key_path( [ 'a', 'b' ] ).should.equal( {} ) g = { 'a' => { 'b' => 'x', 'c' => 'y' } }.extend( Diakonos::KeyMap ) h = g.deep_clone h.delete_key_path( [] ).should.equal( { 'a' => { 'b' => 'x', 'c' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'z' ] ).should.equal( { 'a' => { 'b' => 'x', 'c' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'z', 'zz' ] ).should.equal( { 'a' => { 'b' => 'x', 'c' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'a', 'b', 'c' ] ).should.equal( { 'a' => { 'b' => 'x', 'c' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'a' ] ).should.equal( {} ) h = g.deep_clone h.delete_key_path( [ 'a', 'b' ] ).should.equal( { 'a' => { 'c' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'a', 'c' ] ).should.equal( { 'a' => { 'b' => 'x' } } ) g = { 'a' => { 'b' => 'x' }, 'c' => { 'd' => 'y' } }.extend( Diakonos::KeyMap ) h = g.deep_clone h.delete_key_path( [] ).should.equal( { 'a' => { 'b' => 'x' }, 'c' => { 'd' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'z' ] ).should.equal( { 'a' => { 'b' => 'x' }, 'c' => { 'd' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'z', 'zz' ] ).should.equal( { 'a' => { 'b' => 'x' }, 'c' => { 'd' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'a', 'b', 'c' ] ).should.equal( { 'a' => { 'b' => 'x' }, 'c' => { 'd' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'a' ] ).should.equal( { 'c' => { 'd' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'c' ] ).should.equal( { 'a' => { 'b' => 'x' } } ) h = g.deep_clone h.delete_key_path( [ 'a', 'b' ] ).should.equal( { 'c' => { 'd' => 'y' } } ) h = g.deep_clone h.delete_key_path( [ 'c', 'd' ] ).should.equal( { 'a' => { 'b' => 'x' } } ) end it 'can set a key path' do g = {}.extend( Diakonos::KeyMap ) h = g.deep_clone h.set_key_path( [], 'x' ).should.equal( {} ) h = g.deep_clone h.set_key_path( [ 'a' ], 'x' ).should.equal( { 'a' => 'x' } ) h = g.deep_clone h.set_key_path( [ 'a', 'b' ], 'x' ).should.equal( { 'a' => { 'b' => 'x' } } ) g = { 'a' => 'x' }.extend( Diakonos::KeyMap ) h = g.deep_clone h.set_key_path( [], 'x' ).should.equal( { 'a' => 'x' } ) h = g.deep_clone h.set_key_path( [ 'a' ], 'x' ).should.equal( { 'a' => 'x' } ) h = g.deep_clone h.set_key_path( [ 'a', 'b' ], 'x' ).should.equal( { 'a' => { 'b' => 'x' } } ) g = { 'c' => 'y' }.extend( Diakonos::KeyMap ) h = g.deep_clone h.set_key_path( [], 'x' ).should.equal( { 'c' => 'y' } ) h = g.deep_clone h.set_key_path( [ 'a' ], 'x' ).should.equal( { 'c' => 'y', 'a' => 'x' } ) h = g.deep_clone h.set_key_path( [ 'a', 'b' ], 'x' ).should.equal( { 'c' => 'y', 'a' => { 'b' => 'x' } } ) g = { 'a' => { 'b' => 'x' } }.extend( Diakonos::KeyMap ) h = g.deep_clone h.set_key_path( [], 'x' ).should.equal( { 'a' => { 'b' => 'x' } } ) h = g.deep_clone h.set_key_path( [ 'a' ], 'x' ).should.equal( { 'a' => 'x' } ) h = g.deep_clone h.set_key_path( [ 'c' ], 'y' ).should.equal( { 'a' => { 'b' => 'x' }, 'c' => 'y' } ) h = g.deep_clone h.set_key_path( [ 'c', 'd' ], 'y' ).should.equal( { 'a' => { 'b' => 'x' }, 'c' => { 'd' => 'y' } } ) end it 'can get a node' do h = {}.extend( Diakonos::KeyMap ) h.get_node( [] ).should.be.nil h.get_node( [ 'a' ] ).should.be.nil h.get_node( [ 'a', 'b' ] ).should.be.nil h = { 'a' => 'x' }.extend( Diakonos::KeyMap ) h.get_node( [] ).should.be.nil h.get_node( [ 'b' ] ).should.be.nil h.get_node( [ 'a' ] ).should.equal( 'x' ) h = { 'a' => { 'b' => 'x' } }.extend( Diakonos::KeyMap ) h.get_node( [] ).should.be.nil h.get_node( [ 'b' ] ).should.be.nil h.get_node( [ 'a' ] ).should.equal( { 'b' => 'x' } ) h.get_node( [ 'a', 'b', 'c' ] ).should.be.nil h.get_node( [ 'a', 'c' ] ).should.be.nil h.get_node( [ 'a', 'b' ] ).should.equal( 'x' ) end it 'can get a leaf' do h = {}.extend( Diakonos::KeyMap ) h.get_leaf( [] ).should.be.nil h.get_leaf( [ 'a' ] ).should.be.nil h.get_leaf( [ 'a', 'b' ] ).should.be.nil h = { 'a' => 'x' }.extend( Diakonos::KeyMap ) h.get_leaf( [] ).should.be.nil h.get_leaf( [ 'b' ] ).should.be.nil h.get_leaf( [ 'a' ] ).should.equal( 'x' ) h = { 'a' => { 'b' => 'x' } }.extend( Diakonos::KeyMap ) h.get_leaf( [] ).should.be.nil h.get_leaf( [ 'b' ] ).should.be.nil h.get_leaf( [ 'a' ] ).should.be.nil h.get_leaf( [ 'a', 'b', 'c' ] ).should.be.nil h.get_leaf( [ 'a', 'c' ] ).should.be.nil h.get_leaf( [ 'a', 'b' ] ).should.equal( 'x' ) end enddiakonos-0.9.0/spec/preparation.rb000066400000000000000000000032021161735554400171420ustar00rootroot00000000000000__DIR__ = File.dirname( File.expand_path( __FILE__ ) ) lib_dir = "#{__DIR__}/../lib" if $LOAD_PATH[ 0 ] != lib_dir $LOAD_PATH.unshift lib_dir end require 'bacon' require 'diakonos' if ! Object.const_defined? 'TEST_DIR' TEST_DIR = File.join( File.dirname( File.expand_path( __FILE__ ) ), 'test-files' ) end if ! Object.const_defined? 'SAMPLE_FILE' SAMPLE_FILE = File.join( TEST_DIR, '/sample-file.rb' ) end if ! Object.const_defined? 'SAMPLE_FILE_LONGER' SAMPLE_FILE_LONGER = File.join( TEST_DIR, '/longer-sample-file.rb' ) end if ! Object.const_defined? 'SAMPLE_FILE_C' SAMPLE_FILE_C = File.join( TEST_DIR, '/sample-file.c' ) end if ! Object.const_defined? 'BRACKET_FILE' BRACKET_FILE = File.join( TEST_DIR, '/bracket-file.rb' ) end if ! Object.const_defined? 'TEMP_FILE' TEMP_FILE = File.join( TEST_DIR, '/temp-file.rb' ) end if ! Object.const_defined? 'TEMP_FILE_C' TEMP_FILE_C = File.join( TEST_DIR, '/temp-file.c' ) end def cursor_should_be_at( row, col ) @b.current_row.should.equal row @b.current_column.should.equal col end def numbered_buffer_should_be_named( number, name_expected ) name = File.basename( @d.buffer_number_to_name( number ) ) name.should.equal name_expected end def selection_should_be( start_row, start_col, end_row, end_col ) s = @b.selection_mark s.should.not.be.nil s.start_row.should.equal start_row s.end_row.should.equal end_row s.start_col.should.equal start_col s.end_col.should.equal end_col end if $diakonos.nil? $diakonos = Diakonos::Diakonos.new [ '-e', 'quit', '--test', ] $diakonos.start $diakonos.parse_configuration_file( File.join( __DIR__, 'test-files', 'test.conf' ) ) end diakonos-0.9.0/spec/regexp.rb000066400000000000000000000003341161735554400161130ustar00rootroot00000000000000require_relative 'preparation' describe 'A Regexp' do it 'knows if beginning-of-string is used' do /^test/.uses_bos.should.be.true /test/.uses_bos.should.be.false /t^est/.uses_bos.should.be.false end enddiakonos-0.9.0/spec/searching.rb000066400000000000000000000067011161735554400165700ustar00rootroot00000000000000require_relative 'preparation' describe 'A Diakonos user' do before do @d = $diakonos @b = @d.open_file( SAMPLE_FILE ) cursor_should_be_at 0,0 end after do @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL end it 'can grep the open buffers' do dir = File.dirname( File.expand_path( __FILE__ ) ) @d.actually_grep( 'inspect', @d.buffer_current ) lines = File.readlines( @d.list_filename ) lines[ 0 ].should.match %r(^sample-file\.rb:13: def inspection {100,} \| #{dir}/test-files/sample-file\.rb:13\n$) lines[ 1 ].should.match %r(^sample-file\.rb:14: x\.inspect {100,} \| #{dir}/test-files/sample-file\.rb:14\n$) lines[ 2 ].should.match %r(^sample-file\.rb:15: y\.inspect {100,} \| #{dir}/test-files/sample-file\.rb:15\n$) lines[ 3 ].should.match %r(^sample-file\.rb:20: s\.inspection {100,} \| #{dir}/test-files/sample-file\.rb:20\n$) lines.size.should.equal 4 @d.close_list_buffer end it 'can find words' do @d.find 'is', word_only: true cursor_should_be_at 2,9 selection_should_be 2,7, 2,9 @d.find 'InSpEcT', word_only: true cursor_should_be_at 13,13 selection_should_be 13,6, 13,13 end end describe 'A Diakonos Buffer' do before do @d = $diakonos @b = @d.open_file( BRACKET_FILE ) cursor_should_be_at 0,0 end after do @d.close_buffer @b, Diakonos::CHOICE_NO_TO_ALL end it 'can find next closest characters' do @b.pos_of_next( /x/, 0, 0 ).should.equal [ 1, 2, 'x' ] @b.pos_of_next( /a/, 0, 0 ).should.equal [ 2, 4, 'a' ] @b.pos_of_next( /b/, 0, 0 ).should.equal [ 3, 4, 'b' ] @b.pos_of_next( /\}/, 0, 0 ).should.equal [ 5, 15, '}' ] @b.pos_of_next( /:/, 1, 2 ).should.equal [ 1, 3, ':' ] @b.pos_of_next( /a/, 2, 4 ).should.equal [ 2, 4, 'a' ] @b.pos_of_next( /\]/, 5, 9 ).should.equal [ 5, 23, ']' ] @b.pos_of_next( /q/, 0, 0 ).should.be.nil end it 'can find previous closest characters' do @b.pos_of_prev( /x/, 4, 9 ).should.equal [ 1, 2, 'x' ] @b.pos_of_prev( /a/, 4, 9 ).should.equal [ 2, 4, 'a' ] @b.pos_of_prev( /:/, 4, 7 ).should.equal [ 4, 7, ':' ] @b.pos_of_prev( /c/, 4, 7 ).should.equal [ 4, 6, 'c' ] @b.pos_of_prev( /\{/, 1, 4 ).should.be.equal [ 0, 0, '{' ] @b.pos_of_prev( /\[/, 5, 23 ).should.equal [ 5, 9, '[' ] @b.pos_of_prev( /q/, 4, 9 ).should.be.nil end it 'knows the positions of matching pairs' do @b.pos_of_pair_match( 0, 0 ).should.equal [ 11, 0 ] @b.pos_of_pair_match( 1, 5 ).should.equal [ 10, 2 ] @b.pos_of_pair_match( 3, 7 ).should.equal [ 6, 4 ] @b.pos_of_pair_match( 5, 9 ).should.equal [ 5, 23 ] @b.pos_of_pair_match( 5, 10 ).should.equal [ 5, 15 ] @b.pos_of_pair_match( 11, 0 ).should.equal [ 0, 0 ] @b.pos_of_pair_match( 10, 2 ).should.equal [ 1, 5 ] @b.pos_of_pair_match( 6, 4 ).should.equal [ 3, 7 ] @b.pos_of_pair_match( 5, 23 ).should.equal [ 5, 9 ] @b.pos_of_pair_match( 5, 15 ).should.equal [ 5, 10 ] end it 'can handle mismatched pairs' do @b.pos_of_pair_match( 17, 0 ).should.equal [ nil, nil ] @b.pos_of_pair_match( 18, 0 ).should.equal [ nil, nil ] @b.pos_of_pair_match( 19, 0 ).should.equal [ nil, nil ] @b.pos_of_pair_match( 21, 2 ).should.equal [ 22, 0 ] @b.pos_of_pair_match( 22, 0 ).should.equal [ 21, 2 ] @b.pos_of_pair_match( 5, 20 ).should.equal [ nil, nil ] @b.pos_of_pair_match( 5, 13 ).should.equal [ nil, nil ] @b.pos_of_pair_match( 23, 0 ).should.equal [ nil, nil ] end end diakonos-0.9.0/spec/sizedarray.rb000066400000000000000000000026441161735554400170040ustar00rootroot00000000000000require_relative 'preparation' describe 'A SizedArray' do it 'can be instantiated with a size parameter' do a = SizedArray.new( 2 ) a.capacity.should.equal 2 a = SizedArray.new( 4 ) a.capacity.should.equal 4 end it 'can be appended to and provide overflow items' do a = SizedArray.new( 2 ) a << 1 a.should.equal [ 1 ] a << 2 a.should.equal [ 1, 2 ] ( a << 3 ).should.equal 1 a.should.equal [ 2, 3 ] ( a << 1 ).should.equal 2 a.should.equal [ 3, 1 ] end it 'can be pushed to' do a = SizedArray.new( 2 ) b = SizedArray.new( 2 ) a.should.equal b a << 1 b.push 1 a.should.equal b a << 2 b.push 2 a.should.equal b a << 3 b.push 3 a.should.equal b end it 'can be unshifted to and provide overflow items' do a = SizedArray.new( 2 ) a.unshift( 1 ).should.equal [ 1 ] a.unshift( 2 ).should.equal [ 2, 1 ] a.unshift( 3 ).should.equal 1 a.should.equal [ 3, 2 ] a.unshift( 1 ).should.equal 2 a.should.equal [ 1, 3 ] end it 'can be accept multiple items up to its size via #concat' do a = SizedArray.new( 4 ) a.concat( [ 1, 2 ] ).should.equal [ 1, 2 ] a.concat( [ 3, 4 ] ).should.equal [ 1, 2, 3, 4 ] a.concat( [ 5, 6 ] ).should.equal [ 3, 4, 5, 6 ] a.concat( [ 7, 8, 9, 10 ] ).should.equal [ 7, 8, 9, 10 ] a.concat( [ 1, 2, 3, 4, 5, 6 ] ).should.equal [ 3, 4, 5, 6 ] end enddiakonos-0.9.0/spec/string.rb000066400000000000000000000043161161735554400161330ustar00rootroot00000000000000require_relative 'preparation' describe 'A String' do it 'can be interpreted as and converted to a boolean' do "true".to_b.should.be.true "True".to_b.should.be.true "TRUE".to_b.should.be.true "tRue".to_b.should.be.true "t".to_b.should.be.true "T".to_b.should.be.true "1".to_b.should.be.true "yes".to_b.should.be.true "Yes".to_b.should.be.true "YES".to_b.should.be.true "yEs".to_b.should.be.true "y".to_b.should.be.true "Y".to_b.should.be.true "on".to_b.should.be.true "On".to_b.should.be.true "ON".to_b.should.be.true "oN".to_b.should.be.true "+".to_b.should.be.true "false".to_b.should.be.false "False".to_b.should.be.false "FALSE".to_b.should.be.false "fALse".to_b.should.be.false "f".to_b.should.be.false "F".to_b.should.be.false "n".to_b.should.be.false "N".to_b.should.be.false "x".to_b.should.be.false "X".to_b.should.be.false "0".to_b.should.be.false "2".to_b.should.be.false "no".to_b.should.be.false "No".to_b.should.be.false "NO".to_b.should.be.false "nO".to_b.should.be.false "off".to_b.should.be.false "Off".to_b.should.be.false "OFF".to_b.should.be.false "oFf".to_b.should.be.false "-".to_b.should.be.false "*".to_b.should.be.false "foobar".to_b.should.be.false end it 'can expand its tabs' do s = " " s.expand_tabs( 8 ).should.equal s s = "\t" s.expand_tabs( 8 ).should.equal " " * 8 s = "\t\t" s.expand_tabs( 8 ).should.equal " " * 8*2 s = "\t \t" s.expand_tabs( 8 ).should.equal " " * 8*2 s = "\t \t " s.expand_tabs( 8 ).should.equal " " * (8*2 + 2) s = "\t \t" s.expand_tabs( 8 ).should.equal " " * 8*3 s = "\t \t" s.expand_tabs( 8 ).should.equal " " * 8*3 end it 'knows the index of a first matching regexp group' do s = "abc def ghi" s.group_index( /abc/ ).should.equal [ 0, "abc" ] s.group_index( /def/ ).should.equal [ 4, "def" ] s.group_index( /a(b)c/ ).should.equal [ 1, "b" ] s.group_index( /a(b)c d(e)f/ ).should.equal [ 1, "b" ] s.group_index( /q/ ).should.equal [ nil, nil ] s.group_index( /abc(q?)/ ).should.equal [ 3, '' ] end enddiakonos-0.9.0/spec/test-files/000077500000000000000000000000001161735554400163535ustar00rootroot00000000000000diakonos-0.9.0/spec/test-files/bracket-file.rb000066400000000000000000000002361161735554400212310ustar00rootroot00000000000000{ x: { a: 2, b: { c: 3, d: [{1=>2},{3=>4}], }, e: { f: 5, }, } } # Test mismatched pairs __END__ } ] ) { { } < diakonos-0.9.0/spec/test-files/indentation.test1000066400000000000000000000001231161735554400216450ustar00rootroot00000000000000 x x x x x x x x x x x x x diakonos-0.9.0/spec/test-files/indentation.test2000066400000000000000000000001231161735554400216460ustar00rootroot00000000000000 x x x x x x x x x x x x x diakonos-0.9.0/spec/test-files/longer-sample-file.rb000066400000000000000000000015561161735554400223710ustar00rootroot00000000000000module MyModule class MyClass attr_reader :foo def initialize( foo ) @foo = foo # blah # blah # blah end def method1 # blah # blah # blah # blah # blah # blah end def method2 # blah # blah # blah # blah # blah # blah end def method3 # blah # blah # blah # blah # blah # blah end def method4 # blah # blah # blah # blah # blah # blah end def method5 # blah # blah # blah # blah # blah # blah end def method6 # blah # blah # blah # blah # blah # blah end def method7 # blah # blah # blah # blah # blah # blah end end enddiakonos-0.9.0/spec/test-files/lorem-ipsum.txt000066400000000000000000000017031161735554400213660ustar00rootroot00000000000000Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est. diakonos-0.9.0/spec/test-files/sample-file.c000066400000000000000000000002501161735554400207120ustar00rootroot00000000000000#include int main() { printf( "Hello World!\n" ); if( condition ) { f(); } if( condition ) g(); h(); return 0; } diakonos-0.9.0/spec/test-files/sample-file.rb000066400000000000000000000004721161735554400211010ustar00rootroot00000000000000#!/usr/bin/env ruby # This is only a sample file used in the tests. class Sample attr_reader :x, :y def initialize @x = 1 @y = 2 end def inspection x.inspect y.inspect end end s = Sample.new s.inspection { :just => :a, :test => :hash, } # Comment at end, with no newline at EOFdiakonos-0.9.0/spec/test-files/temp-file.c000066400000000000000000000002501161735554400203760ustar00rootroot00000000000000#include int main() { printf( "Hello World!\n" ); if( condition ) { f(); } if( condition ) g(); h(); return 0; } diakonos-0.9.0/spec/test-files/test.conf000066400000000000000000000006021161735554400201770ustar00rootroot00000000000000lang.test1.filemask \.test1$ lang.test1.indent.size 4 lang.test1.indent.auto true lang.test1.indent.roundup true lang.test1.indent.ignore ^(.+:|\s*?)$ lang.test1.context.ignore ^(.+:|\s*\{?)$ lang.test2.filemask \.test2$ lang.test2.indent.size 4 lang.test2.indent.auto true lang.test2.indent.roundup false lang.test2.indent.ignore ^(.+:|\s*?)$ lang.test2.context.ignore ^(.+:|\s*\{?)$