ソースを参照

Add :YcmToggleLogs command

micbou 9 年 前
コミット
cbe3e04745
3 ファイル変更143 行追加4 行削除
  1. 15 0
      autoload/youcompleteme.vim
  2. 89 4
      python/ycm/vimsupport.py
  3. 39 0
      python/ycm/youcompleteme.py

+ 15 - 0
autoload/youcompleteme.vim

@@ -310,6 +310,8 @@ function! s:SetUpCommands()
   command! YcmRestartServer call s:RestartServer()
   command! YcmShowDetailedDiagnostic call s:ShowDetailedDiagnostic()
   command! YcmDebugInfo call s:DebugInfo()
+  command! -nargs=? -complete=custom,youcompleteme#LogsComplete
+    \ YcmToggleLogs call s:ToggleLogs(<f-args>)
   command! -nargs=* -complete=custom,youcompleteme#SubCommandsComplete
     \ YcmCompleter call s:CompleterCommand(<f-args>)
   command! YcmForceCompileAndDiagnostics call s:ForceCompileAndDiagnostics()
@@ -763,6 +765,14 @@ function! s:DebugInfo()
 endfunction
 
 
+function! s:ToggleLogs(...)
+  let stderr = a:0 == 0 || a:1 !=? 'Stdout'
+  let stdout = a:0 == 0 || a:1 !=? 'Stderr'
+  py ycm_state.ToggleLogs( stdout = vimsupport.GetBoolValue( 'l:stdout' ),
+                         \ stderr = vimsupport.GetBoolValue( 'l:stderr' ) )
+endfunction
+
+
 function! s:CompleterCommand(...)
   " CompleterCommand will call the OnUserCommand function of a completer.
   " If the first arguments is of the form "ft=..." it can be used to specify the
@@ -796,6 +806,11 @@ function! youcompleteme#OpenGoToList()
 endfunction
 
 
+function! youcompleteme#LogsComplete( arglead, cmdline, cursorpos )
+  return "Stdout\nStderr"
+endfunction
+
+
 function! youcompleteme#SubCommandsComplete( arglead, cmdline, cursorpos )
   return join( pyeval( 'ycm_state.GetDefinedSubcommands()' ),
     \ "\n")

+ 89 - 4
python/ycm/vimsupport.py

@@ -331,9 +331,9 @@ def TryJumpLocationInOpenedTab( filename, line, column ):
   return False
 
 
-# Maps User jump command to vim jump command
-def GetVimJumpCommand( user_command ):
-  vim_command = BUFFER_COMMAND_MAP.get( user_command, 'edit' )
+# Maps User command to vim command
+def GetVimCommand( user_command, default = 'edit' ):
+  vim_command = BUFFER_COMMAND_MAP.get( user_command, default )
   if vim_command == 'edit' and not BufferIsUsable( vim.current.buffer ):
     vim_command = 'split'
   return vim_command
@@ -358,7 +358,7 @@ def JumpToLocation( filename, line, column ):
         return
       user_command = 'new-tab'
 
-    vim_command = GetVimJumpCommand( user_command )
+    vim_command = GetVimCommand( user_command )
     try:
       vim.command( 'keepjumps {0} {1}'.format( vim_command,
                                                EscapedFilepath( filename ) ) )
@@ -610,6 +610,11 @@ def JumpToPreviousWindow():
   vim.command( 'silent! wincmd p' )
 
 
+def JumpToTab( tab_number ):
+  """Jump to Vim tab with corresponding number """
+  vim.command( 'silent! tabn {0}'.format( tab_number ) )
+
+
 def OpenFileInPreviewWindow( filename ):
   """ Open the supplied filename in the preview window """
   vim.command( 'silent! pedit! ' + filename )
@@ -653,3 +658,83 @@ def WriteToPreviewWindow( message ):
     # the information we have. The only remaining option is to echo to the
     # status area.
     EchoText( message )
+
+
+def CheckFilename( filename ):
+  """Check if filename is openable."""
+  try:
+    open( filename ).close()
+  except TypeError:
+    raise RuntimeError( "'{0}' is not a valid filename".format( filename ) )
+  except IOError as error:
+    raise RuntimeError(
+      "filename '{0}' cannot be opened. {1}".format( filename, error ) )
+
+
+def BufferExistsForFilename( filename ):
+  """Check if a buffer exists for a specific file."""
+  return GetBufferNumberForFilename( filename, False ) is not -1
+
+
+def CloseBuffersForFilename( filename ):
+  """Close all buffers for a specific file."""
+  buffer_number = GetBufferNumberForFilename( filename, False )
+  while buffer_number is not -1:
+    vim.command( 'silent! bwipeout! {0}'.format( buffer_number ) )
+    buffer_number = GetBufferNumberForFilename( filename, False )
+
+
+def OpenFilename( filename, options = {} ):
+  """Open a file in Vim. Following options are available:
+  - command: specify which Vim command is used to open the file. Choices
+  are same-buffer, horizontal-split, vertical-split, and new-tab (default:
+  horizontal-split);
+  - size: set the height of the window for a horizontal split or the width for
+  a vertical one (default: '');
+  - fix: set the winfixheight option for a horizontal split or winfixwidth for
+  a vertical one (default: False). See :h winfix for details;
+  - focus: focus the opened file (default: False);
+  - watch: automatically watch for changes (default: False). This is useful
+  for logs;
+  - position: set the position where the file is opened (default: start).
+  Choices are start and end."""
+
+  # Set the options.
+  command = GetVimCommand( options.get( 'command', 'horizontal-split' ),
+                           'horizontal-split' )
+  size = ( options.get( 'size', '' ) if command in [ 'split', 'vsplit' ] else
+           '' )
+  focus = options.get( 'focus', False )
+  watch = options.get( 'watch', False )
+  position = options.get( 'position', 'start' )
+
+  # There is no command in Vim to return to the previous tab so we need to
+  # remember the current tab if needed.
+  if not focus and command is 'tabedit':
+    previous_tab = GetIntValue( 'tabpagenr()' )
+
+  # Open the file
+  CheckFilename( filename )
+  vim.command( 'silent! {0}{1} {2}'.format( size, command, filename ) )
+
+  if command is 'split':
+    vim.current.window.options[ 'winfixheight' ] = options.get( 'fix', False )
+  if command is 'vsplit':
+    vim.current.window.options[ 'winfixwidth' ] = options.get( 'fix', False )
+
+  if watch:
+    vim.current.buffer.options[ 'autoread' ] = True
+    vim.command( "exec 'au BufEnter <buffer> :silent! checktime {0}'"
+                 .format( filename ) )
+
+  if position is 'end':
+    vim.command( 'silent! normal G zz' )
+
+  # Vim automatically set the focus to the opened file so we need to get the
+  # focus back (if the focus option is disabled) when opening a new tab or
+  # window.
+  if not focus:
+    if command is 'tabedit':
+      JumpToTab( previous_tab )
+    if command in [ 'split', 'vsplit' ]:
+      JumpToPreviousWindow()

+ 39 - 0
python/ycm/youcompleteme.py

@@ -176,6 +176,7 @@ class YouCompleteMe( object ):
 
 
   def RestartServer( self ):
+    self._CloseLogs()
     vimsupport.PostVimMessage( 'Restarting ycmd server...' )
     self._user_notified_about_crash = False
     self._ServerCleanup()
@@ -507,6 +508,44 @@ class YouCompleteMe( object ):
     return debug_info
 
 
+  def _OpenLogs( self, stdout = True, stderr = True ):
+    # Open log files in a horizontal window with the same behavior as the
+    # preview window (same height and winfixheight enabled). Automatically
+    # watch for changes. Set the cursor position at the end of the file.
+    options = {
+      'size': vimsupport.GetIntValue( '&previewheight' ),
+      'fix': True,
+      'watch': True,
+      'position': 'end'
+    }
+
+    if stdout:
+      vimsupport.OpenFilename( self._server_stdout, options )
+    if stderr:
+      vimsupport.OpenFilename( self._server_stderr, options )
+
+
+  def _CloseLogs( self, stdout = True, stderr = True ):
+    if stdout:
+      vimsupport.CloseBuffersForFilename( self._server_stdout )
+    if stderr:
+      vimsupport.CloseBuffersForFilename( self._server_stderr )
+
+
+  def ToggleLogs( self, stdout = True, stderr = True ):
+    if ( stdout and
+         vimsupport.BufferExistsForFilename( self._server_stdout ) or
+         stderr and
+         vimsupport.BufferExistsForFilename( self._server_stderr ) ):
+      return self._CloseLogs( stdout = stdout, stderr = stderr )
+
+    try:
+      self._OpenLogs( stdout = stdout, stderr = stderr )
+    except RuntimeError as error:
+      vimsupport.PostVimMessage( 'YouCompleteMe encountered an error when '
+                                 'opening logs: {0}.'.format( error ) )
+
+
   def CurrentFiletypeCompletionEnabled( self ):
     filetypes = vimsupport.CurrentFiletypes()
     filetype_to_disable = self._user_options[