Comint模式每4096个字符插入换行符

时间:2011-04-04 16:44:01

标签: emacs

在Ubuntu Lucid上使用Emacs 23.2.1,任何基于Comint的模式都会为较大的输出插入偶尔的换行符(参见下面的示例Shell和SQL模式输出)。我在SQL模式和Shell模式下都尝试过这种方法,两种情况都有相同的结果。在普通终端仿真器中运行类似的命令不会导致这些问题(对于shell模式和mysql模式命令)。

我尝试过的事情:

  • 在SQL模式下使用MySQL,添加以下标志:-A,-C,-t,-f,-n,并将max_allowed_pa​​cket设置为16MB。

  • 将comint-buffer-maximum-size设置为10240。

这些都不会对此行为产生任何影响。

如果我向上滚动到有问题的行并删除换行符,则输出会正确显示,因此这个问题的可能解决方案可能涉及删除每个第4096个字符的挂钩,如果可能的话。

注意:在终端示例中,输出似乎在每4096个字符以外的点处被截断。在SQL模式下,它恰好是每4096个(确实是一个可疑数字)。

以下是一些示例输出:

brent@battlecruiser:/$ for i in {1..4096}; do echo -n 0; done; echo;

0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

在这种情况下,它应该打印出一行0,但事实上在904个字符后插入了一个新的行字符。

使用MySQL的SQL模式中的示例:

mysql> show variables like '%n%';

+-----------------------------------------+----------------------------------+
| Variable_name                           | Value                            |
+-----------------------------------------+----------------------------------+
| auto_increment_increment                | 1                                |
| auto_increment_offset                   | 1                                |
| binlog_cache_size                       | 32768                            |
| binlog_format                           | STATEMENT                        |
| bulk_insert_buffer_size                 | 8388608                          |
| character_set_client                    | utf8                             |
| character_set_connection                | utf8                             |
| collation_connection                    | utf8_general_ci                  |
| collation_database                      | latin1_swedish_ci                |
| collation_server                        | latin1_swedish_ci                |
| completion_type                         | 0                                |
| concurrent_insert                       | 1                                |
| connect_timeout                         | 10                               |
| delayed_insert_limit                    | 100                              |
| delayed_insert_timeout                  | 300                              |
| div_precision_increment                 | 4                                |
| engine_condition_pushdown               | ON                               |
| error_count                             | 0                                |
| event_scheduler                         | OFF                              |
| foreign_key_checks                      | ON                               |
| ft_boolean_syntax                       | + -><()~*:""&|                   |
| ft_max_word_len                         | 84                               |
| ft_min_word_len                         | 4                                |
| ft_query_expansion_limit                | 20                               |
| general_log                             | OFF                              |
| general_log_file                        | /var/lib/mysql/battlecruiser.log |
| group_concat_max_len                    | 1024                             |
| have_community_features                 | YES                              |
| have_dynamic_loading                    | YES                              |
| have_innodb                             | YES                              |
| have_ndbcluster                         | NO                               |
| have_openssl                            | DISABLED                         |
| have_partitioning                       | YES                              |
| have_symlink                            | YES                              |
| hostname                                | battlecruiser                    |
| identity                                | 0                                |
| ignore_builtin_innodb                   | OFF                              |
| init_connect                            |                                  |
| init_file                               |                                  |
| init_slave                              |                                  |
| innodb_adaptive_hash_index              | ON                               |
| innodb_additional_mem_pool_size         | 1048576                          |
| innodb_autoextend_increment             | 8                                |
| innodb_autoinc_lock_mode                | 1                                |
| innodb_buffer_pool_size                 | 8388608                          |
| innodb_checksums                        | ON                               |
| innodb_commit_concurrency               | 0                                |
| innodb_concurrency_tickets              | 500                              |
| innodb_data_file_path                   | ibdata1:10M:autoextend
           |
| innodb_data_home_dir                    |                                  |
| innodb_doublewrite                      | ON                               |
| innodb_fast_shutdown                    | 1                                |
| innodb_file_io_threads                  | 4                                |
| innodb_file_per_table                   | OFF                              |
| innodb_flush_log_at_trx_commit          | 1                                |
| innodb_flush_method                     |                                  |
| innodb_force_recovery                   | 0                                |
| innodb_lock_wait_timeout                | 50                               |
| innodb_locks_unsafe_for_binlog          | OFF                              |
| innodb_log_buffer_size                  | 1048576                          |
| innodb_log_file_size                    | 5242880                          |
| innodb_log_files_in_group               | 2                                |
| innodb_log_group_home_dir               | ./                               |
| innodb_max_dirty_pages_pct              | 90                               |
| innodb_max_purge_lag                    | 0                                |
| innodb_mirrored_log_groups              | 1                                |
| innodb_open_files                       | 300                              |
| innodb_rollback_on_timeout              | OFF                              |
| innodb_stats_on_metadata                | ON                               |
| innodb_support_xa                       | ON                               |
| innodb_sync_spin_loops                  | 20                               |
| innodb_table_locks                      | ON                               |
| innodb_thread_concurrency               | 8                                |
| innodb_thread_sleep_delay               | 10000                            |
| innodb_use_legacy_cardinality_algorithm | ON                               |
| insert_id                               | 0                                |
| interactive_timeout                     | 28800                            |
| join_buffer_size                        | 131072                           |
| keep_files_on_create                    | OFF                              |
| key_cache_division_limit                | 100                              |
| language                                | /usr/share/mysql/english/        |
| last_insert_id                          | 0                                |
| lc_time_names                           | en_US                            |
| license                                 | GPL                              |
| local_infile                            | ON                               |
| locked_in_memory                        | OFF                              |
| log_bin                                 | OFF                              |
| log_bin_trust_function_creators         | OFF                              |
| log_bin_trust_routine_creators          | OFF                              |
| log_queries_not_using_indexes           | OFF                              |
| log_warnings                            | 1                                |
| long_query_time                         | 10.000000                        |
| lower_case_table_names                  | 0                                |
| max_binlog_cache_size                   | 4294963200                       |
| max_binlog_size                         | 104857600                        |
| max_connect_errors                      | 10                               |
| max_connections                         | 151                              |
| max_error_count                         | 64                               |
| max_insert_delayed_threads              | 20                               |
| max_join_size                           | 18446744073709551615             |
| max_length_for_sort_data                | 1024     
                        |
| max_prepared_stmt_count                 | 16382                            |
| max_sort_length                         | 1024                             |
| max_sp_recursion_depth                  | 0                                |
| max_user_connections                    | 0                                |
| max_write_lock_count                    | 4294967295                       |
| min_examined_row_limit                  | 0                                |
| multi_range_count                       | 256                              |
| myisam_data_pointer_size                | 6                                |
| myisam_recover_options                  | BACKUP                           |
| net_buffer_length                       | 16384                            |
| net_read_timeout                        | 30                               |
| net_retry_count                         | 10                               |
| net_write_timeout                       | 60                               |
| new                                     | OFF                              |
| open_files_limit                        | 1024                             |
| optimizer_prune_level                   | 1                                |
| plugin_dir                              | /usr/lib/mysql/plugin            |
| profiling                               | OFF                              |
| profiling_history_size                  | 15                               |
| protocol_version                        | 10                               |
| query_cache_min_res_unit                | 4096                             |
| query_cache_wlock_invalidate            | OFF                              |
| rand_seed1                              |                                  |
| rand_seed2                              |                                  |
| range_alloc_block_size                  | 4096                             |
| read_only                               | OFF                              |
| read_rnd_buffer_size                    | 262144                           |
| relay_log_index                         |                                  |
| relay_log_info_file                     | relay-log.info                   |
| rpl_recovery_rank                       | 0                                |
| skip_external_locking                   | ON                               |
| skip_networking                         | OFF                              |
| slave_net_timeout                       | 3600                             |
| slave_transaction_retries               | 10                               |
| slow_launch_time                        | 2                                |
| sql_auto_is_null                        | ON                               |
| sql_log_bin                             | ON                               |
| sql_max_join_size                       | 18446744073709551615             |
| sql_notes                               | ON                               |
| sql_slave_skip_counter                  |                                  |
| sql_warnings                            | OFF                              |
| storage_engine                          | MyISAM                           |
| sync_binlog                             | 0                                |
| sync_frm                                | ON                               |
| system_time_zone                        | EDT                              |
| table_definition_cache                  | 256                              |
| table_open_cache                        | 64                               |
| thread_handling                         | one-thread-per-connection        |
| time_zone                               | SYSTEM                           |
| transaction_alloc_block_size            | 8192                             |
| transaction_prealloc_size               | 4096                             |
| tx_isolation                          
  | REPEATABLE-READ                  |
| unique_checks                           | ON                               |
| version                                 | 5.1.41-3ubuntu12.10              |
| version_comment                         | (Ubuntu)                         |
| version_compile_machine                 | i486                             |
| version_compile_os                      | debian-linux-gnu                 |
| warning_count                           | 0                                |
+-----------------------------------------+----------------------------------+
159 rows in set (0.00 sec)

此处的输出始终以换行符中断,精确间隔为4096个字符。

除了可能的解决方案之外,任何有关正在发生的事情的更多信息的新方法都将受到赞赏。

4 个答案:

答案 0 :(得分:4)

我有类似的问题,虽然我的休息似乎是1024个字符( ah-ha!在21_1版本中就是这种情况)。这对我来说并不是什么大不了的事,但我确实写了一些正确连接结果的东西,所以我可以对它们进行后期处理。但这并没有影响输出,所以它没有多大帮助。

问题的根源在于process.c中的read_process_output,其代码为4096:

/* Read pending output from the process channel,
   starting with our buffered-ahead character if we have one.
   Yield number of decoded characters read.

   This function reads at most 4096 characters.
   If you want to read all available subprocess output,
   you must call it repeatedly until it returns zero.

   The characters read are decoded according to PROC's coding-system
   for decoding.  */

static int
read_process_output (proc, channel)
     Lisp_Object proc;
     register int channel;
{
  // ... snip
  int readmax = 4096;

就像你在问题中提到的那样,一个非常可能的解决方案是编写一个函数(称之为clean-up-comint-output-at-4096-chars),并将其添加到comint-output-filter-functions。像这样的东西。 注意:未经测试的代码

(add-hook 'comint-output-filter-functions 'clean-up-comint-output-at-4096-chars)
(defun clean-up-comint-output-at-4096-chars (&optional str)
  "look for string of 4096 length and remove newline in the buffer"
  (let ((magic-block-size 4096))
    (save-match-data
      (when (= magic-block-size (length str))
        ;; at the magic block size, look for a newline
        (goto-char (point-max))
        (when (and (search-backward str nil t)
                   (progn
                     (forward-char magic-block-size)
                     (looking-at "\n")))
          (delete-char 1))))))

答案 1 :(得分:3)

我找到了解决这个问题的方法。我在配置文件中输入了以下来自http://www.emacswiki.org/emacs/SqlMode

的代码
  (defun sql-add-newline-first (output)
    "Add newline to beginning of OUTPUT for `comint-preoutput-filter-functions'"
    (concat "\n" output))

  (defun sqli-add-hooks ()
    "Add hooks to `sql-interactive-mode-hook'."
    (add-hook 'comint-preoutput-filter-functions
              'sql-add-newline-first))

  (add-hook 'sql-interactive-mode-hook 'sqli-add-hooks)

删除代码后(由于它设置了comint-preoutput-filter-functions,也影响了shell-mode),我不再遇到这些问题。

我建议替换此代码以获得我想要的行为(到目前为止适用于我):

(defun sql-add-newline-first (output)
  "Add newline to beginning of OUTPUT for `comint-preoutput-filter-functions'"
  (remove-hook 'comint-preoutput-filter-functions
           'sql-add-newline-first)
  (concat "\n" output))

(defun sql-send-region-better (start end)
  "Send a region to the SQL process."
  (interactive "r")
  (if (buffer-live-p sql-buffer)
      (save-excursion
    (add-hook 'comint-preoutput-filter-functions
          'sql-add-newline-first)
    (comint-send-region sql-buffer start end)
    (if (string-match "\n$" (buffer-substring start end))
        ()
      (comint-send-string sql-buffer "\n"))
    (message "Sent string to buffer %s." (buffer-name sql-buffer))
    (if sql-pop-to-buffer-after-send-region
        (pop-to-buffer sql-buffer)
      (display-buffer sql-buffer)))
    (message "No SQL process started.")))

(defvar sql-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "C-c C-c") 'sql-send-paragraph)
    (define-key map (kbd "C-c C-r") 'sql-send-region-better)
    (define-key map (kbd "C-c C-s") 'sql-send-string)
    (define-key map (kbd "C-c C-b") 'sql-send-buffer)
    map)
  "Mode map used for `sql-mode'.")

基本上,我在我的sql-send-region之前添加了钩子 - 更好的代码开始发送输出,然后 in hook 我再次删除钩子,保证它只插入一个我想要的新行。

答案 2 :(得分:1)

这是我的实现,每次输入只预先加上“\ n”:

(defvar sql-last-prompt-pos 1
  "position of last prompt when added recording started")
(make-variable-buffer-local 'sql-last-prompt-pos)
(put 'sql-last-prompt-pos 'permanent-local t)



(defun sql-add-newline-first (output)
  "Add newline to beginning of OUTPUT for
  `comint-preoutput-filter-functions'

  This fixes up the display of queries sent to the inferior
  buffer programatically.  But also adds extra new-line for
  interactive commands.

  "
  (let ((begin-of-prompt
         (or (and comint-last-prompt-overlay
                  ;; sometimes this overlay is not on prompt
                  (save-excursion
                    (goto-char (overlay-start comint-last-prompt-overlay))
                    (looking-at-p comint-prompt-regexp)
                    (point)))
             1)))
    (if (> begin-of-prompt sql-last-prompt-pos)
        (progn
          (setq sql-last-prompt-pos begin-of-prompt)
          (concat "\n" output))
      output)))

(defun le-sqli-setup ()
  "Add hooks to `sql-interactive-mode-hook'."
  (add-hook 'comint-preoutput-filter-functions
            'sql-add-newline-first t t))
(add-hook 'sql-interactive-mode-hook 'le-sqli-setup)

答案 3 :(得分:0)

我的解决方案 - 添加换行符(但随后删除挂钩以防止多个分隔文本)。然后在每个输入提示符处重新添加挂钩。

(defun sql-add-newline-first (output)
    "Add newline to beginning of sql OUTPUT, but remove the hook so
     that it doesn't output a newline everytime the output cache is
     filled."
    (remove-hook 'comint-preoutput-filter-functions 'sql-add-newline-first)
    (concat "\n" output))

(defun sql-readd-newline-first (ignore)
  "Readd the newline putting hook"
  (add-hook 'comint-preoutput-filter-functions 'sql-add-newline-first))

(defun sqli-add-hooks ()
  "Add the 'suicidal' newline printing hook, and another hook to
   respawn it at every input prompt."
  (add-hook 'comint-preoutput-filter-functions 'sql-add-newline-first)
  (add-hook 'comint-input-filter-functions 'sql-readd-newline-first))

(add-hook 'sql-interactive-mode-hook 'sqli-add-hooks)

另外,就我而言,我使用的是postgresql。在多线查询(例如database-#database-#database-#| col | col |)之后添加额外提示会产生额外提示的恶习。要解决,我最终做到了这一点:

(defun sql-remove-continuing-prompts (output)
  (concat "\n" (replace-regexp-in-string "warren_hero[^=()]# " "" output)))

(defun sqli-add-hooks ()
  (add-hook 'comint-preoutput-filter-functions 'sql-remove-continuing-prompts))

(add-hook 'sql-interactive-mode-hook 'sqli-add-hooks)