Komodo / KomodoEdit

Komodo Edit is a fast and free multi-language code editor. Written in JS, Python, C++ and based on the Mozilla platform.
http://www.komodoide.com/komodo-edit
Other
2.15k stars 301 forks source link

Something in my file makes Komodo want to use 23 spaces per tab #1756

Closed mkimberling closed 8 years ago

mkimberling commented 8 years ago

Short Summary

Komodo wants to use 23 spaces per tab with the attached file. The problem goes away after I remove the "Allow file contents to override Tab and Indentation setting" check from Preferences.

Steps to Reproduce

Open the attached file in Komodo 10 and observe 23 spaces per tab.

Expected results

The settings in a file should not change how Komodo interprets the size of a tab.

Actual results

Platform Information

Komodo Edit or IDE? IDE Komodo Version? 10.0.1 build 89222 Operating System (and version)? Windows

10

Additional Information

before newfile

after saveastestdotpy

-- eg. Error logs, screenshots, workarounds --

mitchell-as commented 8 years ago

@mkimberling I'm not seeing the attached file. Would you please reattach it? Thanks!

mkimberling commented 8 years ago
  From: mitchell <notifications@github.com>

To: Komodo/KomodoEdit KomodoEdit@noreply.github.com Cc: mkimberling matt_kimberling@yahoo.com; Mention mention@noreply.github.com Sent: Tuesday, June 28, 2016 10:34 AM Subject: Re: [Komodo/KomodoEdit] Something in my file makes Komodo want to use 23 spaces per tab (#1756)

@mkimberling I'm not seeing the attached file. Would you please reattach it? Thanks!— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

import json import hashlib import rat.ratbatchutil as ratbatchutil import serverdb as serverdb from sqlalchemy import and, not, literal from sqlalchemy.sql import functions, func

import rat.ratcumulusutil as ratcumulusutil import sqlalchemy import time as _time from memcache import MemCache from rat.ratbatchutil import TestRoot from flask import render_template

gTestRootStatusConfig = { ratbatchutil.TestRoot.kStatusCreated : { 'image': 'res/rat_waiting.png', 'fastrefresh' : True, 'pending' : True, 'canabort' : True }, ratbatchutil.TestRoot.kStatusPending : { 'image': 'res/rat_running.png', 'fastrefresh' : True, 'pending' : True, 'canabort' : True }, ratbatchutil.TestRoot.kStatusFailed : { 'image': 'res/rat_fail.png', 'fastrefresh' : False, 'pending' : False }, ratbatchutil.TestRoot.kStatusCompleted : { 'image': 'res/rat_success.png', 'fastrefresh' : False, 'pending' : False }, ratbatchutil.TestRoot.kStatusAborted : { 'image': 'res/rat_fail.png', 'fastrefresh' : False, 'pending' : False }, }

gRatTestStatusConfig = { ratbatchutil.Test.kStatusCreated : { 'textcolor' : 'gray' }, ratbatchutil.Test.kStatusRunning : { 'textcolor' : 'blue', 'abortedtextcolor' : 'red' }, ratbatchutil.Test.kStatusFailed : { 'textcolor' : 'red' }, ratbatchutil.Test.kStatusCompleted : { 'textcolor' : 'green' }, ratbatchutil.Test.kStatusSkipped : { 'textcolor' : 'gray' }, }

CONTEXT_ABORT_PENDING_LOCAL = "AbortAllLocal" CONTEXT_OPTION_ABORT = "Abort" CONTEXT_OPTION_HIDE = "Hide" CONTEXT_OPTION_SHOW = "Show" CONTEXT_OPTION_SAVE_TARGETS = "Save Targets"

ContextMenuOptions = [ CONTEXT_OPTION_ABORT, CONTEXT_OPTION_HIDE, CONTEXT_OPTION_SHOW, CONTEXT_OPTION_SAVE_TARGETS ]

ContextMenuIndexLookup = { name:idx for (idx, name) in enumerate( ContextMenuOptions ) }

memCache = MemCache( 3 )

def handleAction( requestArgs ):

action = requestArgs['action']

testRoot = None
if "testrootid" in requestArgs:
    testRoot = serverdb.db_session.query( ratbatchutil.TestRoot ).get( int(requestArgs['testrootid']) )

if action == CONTEXT_OPTION_SHOW:
    testRoot.visible = True
if action == CONTEXT_OPTION_HIDE:
    testRoot.visible = False
if action == CONTEXT_OPTION_ABORT:
    testRoot.status = ratbatchutil.TestRoot.kStatusAborted

    if testRoot.cumulusTaskId == -1:
        print "Aborting Local Test TestRoot %d" % ( testRoot.id )
        testRoot.abortedText = "Test aborted by user"
    else:
        print "Aborting Remote Test TestRoot %d, Cumulus Id: %d" % ( testRoot.id, testRoot.cumulusTaskId )
        ratcumulusutil.CancelTask( testRoot.cumulusDBHost, testRoot.cumulusDBName, testRoot.cumulusTaskId )

if action == CONTEXT_OPTION_SAVE_TARGETS:
    testRoot.options.Set( 'ShouldSaveTargets', 'True' )

if action == CONTEXT_ABORT_PENDING_LOCAL:
    user = requestArgs[ 'username' ]
    category = requestArgs[ 'category' ]
    computer = requestArgs[ 'computer' ]
    query = "UPDATE testroot SET status='aborted' WHERE user='%s' and computer='%s' and (status='pending' or status='created') and category='%s'" % ( user, computer, category)
    serverdb.engine.execute( query )

serverdb.db_session.commit()

def getCachedRexRatView( requestArgs ): key = 'rex_rat_view' if 'filter' not in requestArgs or 'hash' not in requestArgs: return None

filter = requestArgs['filter']
subcategory = requestArgs.get( 'subcategory', None )
hash = requestArgs['hash']
key = "%s filter:%s" % ( key, filter )
user = None

if 'user' in requestArgs:
    user = requestArgs['user']
    if filter == 'My Tests':
        key = "%s user:%s" % ( key, user )

#if 'nocache' in requestArgs or not memCache.hasValid( key ):
#   memCache.put( key, generateRexRatView( key, filter, user ) )

#result = memCache.get( key )
result = generateRexRatView( key, filter, subcategory, user )

if hash != result['hash']:
    return json.dumps( result, ensure_ascii=False ) 
else:
    return json.dumps( {'hash': result['hash'] }, ensure_ascii=False ) 

TestHistoryFilter_MyTests = "My Tests" TestHistoryFilter_LocalTests = "Local Tests" TestHistoryFilter_RemoteTests = "Remote Tests" TestHistoryFilter_UserTests = "User Tests" TestHistoryFilter_AllTests = "All Tests" TestHistoryFilter_ContinuousTests = "Continuous Tests" TestHistoryFilter_BudgetTests = "Budget Tests" TestHistoryFilter_Hidden = "Hidden Tests"

TestHistoryFilters = [ TestHistoryFilter_UserTests, TestHistoryFilter_MyTests, TestHistoryFilter_LocalTests, TestHistoryFilter_RemoteTests, TestHistoryFilter_AllTests, TestHistoryFilter_ContinuousTests, TestHistoryFilter_BudgetTests, TestHistoryFilter_Hidden ]

def generateRexRatView( key, filter, subcategory, user ): query = serverdb.db_session.query(ratbatchutil.TestRoot)

if filter == TestHistoryFilter_MyTests:
    query = query.filter( ratbatchutil.TestRoot.user == user )
elif filter == 'All Local Tests' or filter == TestHistoryFilter_LocalTests:
    query = query.filter( ratbatchutil.TestRoot.remote == 0 )
elif filter == 'All Remote Tests' or filter == TestHistoryFilter_RemoteTests:
    query = query.filter( ratbatchutil.TestRoot.remote == 1 )

if filter != TestHistoryFilter_AllTests and filter != TestHistoryFilter_Hidden:
    if filter == TestHistoryFilter_ContinuousTests:
        if subcategory and subcategory != '(all)':
            query = query.filter( and_( ratbatchutil.TestRoot.category == 'Continuous', ratbatchutil.TestRoot.subcategory == subcategory ) )
        else:
            query = query.filter( and_( ratbatchutil.TestRoot.category == 'Continuous', not_( ratbatchutil.TestRoot.subcategory.contains( literal('Budget') ) ) ) )

    elif filter == TestHistoryFilter_BudgetTests:
        query = query.filter( and_( ratbatchutil.TestRoot.category == 'Continuous', ratbatchutil.TestRoot.subcategory.contains( literal('Budget') ) ) )
    else:
        query = query.filter( ratbatchutil.TestRoot.category != 'Continuous' )

if filter == TestHistoryFilter_Hidden:
    query = query.filter( ratbatchutil.TestRoot.visible == 0 )
else:
    query = query.filter( ratbatchutil.TestRoot.visible == 1 )

query = query.order_by(ratbatchutil.TestRoot.id.desc())
query = query.limit(15).from_self().join(ratbatchutil.Test).order_by(ratbatchutil.TestRoot.id.desc()).order_by(ratbatchutil.Test.priority.desc())

testRoots = query.all()

if filter == TestHistoryFilter_ContinuousTests:
    sq = serverdb.db_session.query( ratbatchutil.TestRoot ).filter( and_( ratbatchutil.TestRoot.category == 'Continuous', not_( ratbatchutil.TestRoot.subcategory.contains( literal('Budget') ) ) ) ).limit( 15 )
    subcategories = sorted( list( set( ['(all)'] + [ t.subcategory for t in sq.all() ] ) ) )
else:
    subcategories = None

filters = TestHistoryFilters
htmlItems = generateRexRatViewHTML( testRoots )
testRootEntries = generateRexRatTestEntries( user, testRoots )
newHash = hashlib.md5( str( htmlItems ) + str( filters ) ).hexdigest()

fastRefreshStates = [ ratbatchutil.TestRoot.kStatusCreated, ratbatchutil.TestRoot.kStatusPending ]
refreshTime = 20
if len( [ x for x in testRoots if x.status in fastRefreshStates ] ) > 0:
    refreshTime = 3

result = {}
result['hash']              = newHash;
result['filters']           = filters
if subcategories:
    result['subcategories'] = subcategories
result['options']           = ContextMenuOptions
result['refresh']           = refreshTime
result['testroot-entries']  = testRootEntries
result['html-items']        = htmlItems
return result

def generateRexRatViewHTML( testRoots ): htmlItems = [] for testRoot in testRoots: htmlItem = getHTMLForRootTest( testRoot ) if htmlItem != None: htmlItems.append( htmlItem ) return htmlItems

def generateRexRatTestEntries( user, testRoots ): testEntries = [] for testRoot in testRoots: contextOptions = [] json = {} isAdmin = user in [ "jscheinberg", "atimnak", "mkimberling" ] if user == testRoot.user or isAdmin:

        if testRoot.status == ratbatchutil.TestRoot.kStatusCreated or testRoot.status == ratbatchutil.TestRoot.kStatusPending:
            contextOptions.append( ContextMenuIndexLookup[ CONTEXT_OPTION_ABORT ] )
            contextOptions.append( ContextMenuIndexLookup[ CONTEXT_OPTION_SAVE_TARGETS ] )

        if testRoot.visible:
            contextOptions.append( ContextMenuIndexLookup[ CONTEXT_OPTION_HIDE ] )
        else:
            contextOptions.append( ContextMenuIndexLookup[ CONTEXT_OPTION_SHOW ] )

    json['id'] = testRoot.id
    json['optionsidx'] = contextOptions
    testEntries.append( json )
return testEntries

def getHTMLForRootTest( testRoot ): lines = []

dateText = _time.strftime( "%I:%M %p (%m/%d)", _time.localtime( testRoot.createTime ) )
statusText = " - {0}".format( testRoot.status )
whereText =  "Remote" if testRoot.remote else "Local"
title = '{0} {1} Rat Test {2} - {3}{4}'.format( testRoot.user, whereText, testRoot.id, dateText, statusText )
testRootConfig = gTestRootStatusConfig[ testRoot.status ]
tests = []

if testRoot.status == ratbatchutil.TestRoot.kStatusPending:
    # list the state of each test if running
    for test in testRoot.tests:
        testConfig = gRatTestStatusConfig[ test.status ]
        colorText = testConfig[ 'textcolor' ]
        if test.status == "aborted" and 'abortedtextcolor' in testConfig:
            colorText = testConfig[ 'abortedtextcolor' ]
        tests.append( "<font color='%s'>%s</font>" % ( colorText, test.name ) )
elif testRoot.status in (ratbatchutil.TestRoot.kStatusFailed, ratbatchutil.TestRoot.kStatusAborted):
    # list the state of just the failed tests
    for test in testRoot.tests:
        if test.status == 'failed':
            testConfig = gRatTestStatusConfig[ test.status ]
            colorText = testConfig[ 'textcolor' ]
            if test.status == "aborted" and 'abortedtextcolor' in testConfig:
                colorText = testConfig[ 'abortedtextcolor' ]
            tests.append( "<font color='%s'>%s</font>" % ( colorText, test.name ) )

if testRoot.options != None:
    testTitle = testRoot.options.Get( "Title", None )
    if testTitle != None:
        lines.append( testTitle )

if testRoot.cumulusTaskId != -1:
    cumulusText = ""
    if testRoot.cumulusChangelist != None and testRoot.cumulusChangelist != '':
        cumulusText += 'Changelist %s, ' % ( testRoot.cumulusChangelist )
    cumulusText += "Cumulus Task Id %s" % testRoot.cumulusTaskId        
    if testRoot.options.Get( 'ShouldSaveTargets', None ) == 'True':
        cumulusText += ' (Save Targets)'

    lines.append( cumulusText )

lines.append( ', '.join( tests ) )  

if testRoot.status == ratbatchutil.TestRoot.kStatusPending:
    for test in testRoot.tests:
        if test.status == ratbatchutil.Test.kStatusRunning and test.computer != None:
            currentAction = test.currentAction if test.currentAction != None else ""
            lines.append( '%s: %s %s' % ( test.computer, test.name, test.currentAction ) )
return buildHTMLItem( title, lines, testRootConfig[ 'image' ] )

def buildHTMLItem( title, lines, image ): return render_template( 'rex_rat_item.html', title=title, lines=lines, image=image )

mitchell-as commented 8 years ago

Unfortunately github really likes to mangle e-mail responses. I'm not able to use your inline attachment. When you get the chance, please attach with a web browser. Sorry for all of this inconvenience :(

mkimberling commented 8 years ago

I am using a web browser.  Sorry but can you spell out exactly what I need to do to get you the attachment?

  From: mitchell <notifications@github.com>

To: Komodo/KomodoEdit KomodoEdit@noreply.github.com Cc: mkimberling matt_kimberling@yahoo.com; Mention mention@noreply.github.com Sent: Tuesday, June 28, 2016 10:40 AM Subject: Re: [Komodo/KomodoEdit] Something in my file makes Komodo want to use 23 spaces per tab (#1756)

Unfortunately github really likes to mangle e-mail responses. I'm not able to use your inline attachment. When you get the chance, please attach with a web browser. Sorry for all of this inconvenience :(— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

Defman21 commented 8 years ago

You're replying using your mail (Yahoo mail?). Use Github instead https://github.com/Komodo/KomodoEdit/issues/1756

mkimberling commented 8 years ago

i did last time. I'm on the Git page now.

Defman21 commented 8 years ago

Now attach a file as @mitchell-as asked.

mkimberling commented 8 years ago

And how does one do that?

mkimberling commented 8 years ago

test.txt

mkimberling commented 8 years ago

Renaming the file to .txt worked.

mitchell-as commented 8 years ago

Thanks, I also get a really big indentation default. I'll look into this.

Defman21 commented 8 years ago

I probably know what's going on there. As you can see Mitchell, the first "indent" is 6 tabs. Komodo probably recognizes that as one tab and then changes the indent width using this formula width of the first indent * width of tabs. 6 * 4 = 24. require('ko/editor').scimoz().indent returns 23 (0 seems to be a "legit" indent) in this file.

Defman21 commented 8 years ago

Here's an example file with this behavior being fixed:

test.txt

--- test.txt old 2016-06-28 21:25:52.087558498 +0300
+++ test.txt new 2016-06-28 21:25:06.693058785 +0300
@@ -4,7 +4,7 @@
 import serverdb as serverdb
 from sqlalchemy import and_, not_, literal
 from sqlalchemy.sql import functions, func
-
+   
 import rat.ratcumulusutil as ratcumulusutil
 import sqlalchemy
 import time as _time

require('ko/editor').scimoz().indent => 4

mitchell-as commented 8 years ago

Thanks @Defman21 you are correct that the first, massive indent level is throwing things off.

@mkimberling When it comes to "allow file contents to override indentation settings", we just look for changes in indentation starting from the first line. It's really not more complicated than that. Your file has 6 consecutive lines with 5 tabs + 3 spaces as the "first" level of indentation seen in the file. This caused Komodo to think one level of indentation is 23 spaces (5 tabs @ 4 spaces/tab + 3 spaces = 23).

In this case, you'd go to Edit > Current File Preferences for your particular file, uncheck "Allow file contents to override ...", click Apply, and then re-open the file to get your 4 space indentation. That setting will only apply to the current file. Any other files you open will still have "Allow file contents to override ..." checked.

I'm going to mark this ticket "by design" and close.

mkimberling commented 8 years ago

Thanks for your help getting to the bottom of this. I'm not sure why this code was indented like that but I never would have guessed that this feature would work that way.

tonyattwood commented 8 years ago

Hey,

We've finnaly got home and wanted to share some cool pics of our journey, just take a look http://follow.refinancehow.com/e4evuw

Sincerely, tony.attwood@ntlworld.com

tonyattwood commented 8 years ago

Hi friend!

Here is a good news from our mutual friend, just read it here http://effort.oceanbaypurchasing.com/e4drdfe

Thanks for your consideration, tony.attwood

tonyattwood commented 8 years ago

Hi!

I've visited that new store and found that stuff you were looking for lately, here it is http://place.alrajehfamily.net/e4qcm

tony.attwood

tonyattwood commented 8 years ago

Yo!

I thought this information regarding my favourite stuff may be usefull for you too, just take a look here http://favourite.ap-nyc.com/e4gpacm

Warmly, tony.attwood

tonyattwood commented 8 years ago

Hey friend,

I've been looking for some nice stuff and have come across those amazing things, just take a look http://xaltichysa.twentyfiveattwentyfive.com/e4rgob

Looking forward, tony.attwood

Defman21 commented 7 years ago

Actually, I disagree with this design. You're checking for 300 lines (thanks to Carey for pointing that to me) to detect spaces or tabs (based on the amount of them in the file). Why not checking which space width number is the most popular in the file rather than using the first indentation? So in case someone indents their 8-line config variable with 8 spaces and 280 lines of code with 4 spaces, their indent char will be 4 chars. If it's too complicated to implement then okay that's not that important :)

Naatan commented 7 years ago

I'm with Defman on this, but this isn't the place for it. @Defman21 wanna file a new bug? :)

Defman21 commented 7 years ago

Yeah sure.